Newer
Older
TIASDataHub / src / tiasdata / importers / __init__.py
"""取り込み元の形ごとの読み取りと登録(1 つの形 = 1 モジュール).

設定ファイルの `sources.<名前>.importer` の名前から importer を選ぶ.取り込み元の形を増やすときは
モジュールを追加して `IMPORTERS` に登録する(既存の importer に分岐を足さない).
"""

from contextlib import closing
from pathlib import Path

from tiasdata import catalog
from tiasdata.catalog import identity
from tiasdata.config import Config
from tiasdata.importers import holds as holds_module
from tiasdata.importers import tongue_color_folders
from tiasdata.importers.base import ImportContext, Importer, ImportResult

# importer の名前(設定の `importer`)→ 取り込みの関数
IMPORTERS: dict[str, Importer] = {
    tongue_color_folders.NAME: tongue_color_folders.run,
}


def run_import(
    config: Config,
    source_name: str,
    *,
    holds_dir: Path | None = None,
    show_source_names: bool = False,
) -> ImportResult:
    """設定ファイルの取り込み元を名前で指定して取り込む.

    対応表(`identity.sqlite`)は目録の接続に ATTACH し,目録と対応表への登録を
    1 つのトランザクションにまとめる.

    Args:
        config: 設定.
        source_name: 取り込み元の名前(`sources.<名前>`).
        holds_dir: 保留リストのフォルダ.省略時はリポジトリの `holds/`.
        show_source_names: エラーメッセージに取り込み元での番号・名前を出すか.

    Returns:
        取り込みの結果(件数).

    Raises:
        ValueError: 取り込み元・importer が無い,目録・対応表が無いか古い,保留リストの誤り,
            取り込み元・対応表の不備,または登録済みの内容との食い違い.
    """
    source = config.sources.get(source_name)
    if source is None:
        raise ValueError(f"設定ファイルに取り込み元 '{source_name}' が無い")
    importer = IMPORTERS.get(source.importer)
    if importer is None:
        raise ValueError(
            f"取り込み元 '{source_name}' の importer '{source.importer}' が無い"
            f"(使えるもの: {', '.join(sorted(IMPORTERS))})"
        )
    # 保留リストの場所は呼び出し時に引く(テストで差し替えられるようにモジュール経由で呼ぶ)
    directory = holds_dir if holds_dir is not None else holds_module.default_holds_dir()
    holds = holds_module.load_holds(directory, source_name)

    paths = config.catalog
    context = ImportContext(
        source_name=source_name,
        source=source,
        store_dir=paths.store_dir,
        holds=holds,
        show_source_names=show_source_names,
    )
    with closing(catalog.connect_latest(paths.catalog_path)) as conn:
        identity.attach_identity(conn, paths.identity)
        return importer(conn, context)


__all__ = ["IMPORTERS", "ImportContext", "ImportResult", "Importer", "run_import"]