Customize CLI options

You can extend download and convert scripts with custom options.

Keep custom args explicit and documented in the README of the fetcher.

Example: override the provider URL in download.py

DownloadCLI accepts a configure_parser callback that lets you add custom options to the base argument parser. The custom values are then available in args when the downloader is instantiated.

download.py
from dbnomics_toolbox.fetcher_utils import (
    DownloadCLI,
    create_base_downloader_init_kwargs,
)

import abc_fetcher
from abc_fetcher.downloader import AbcDownloader


def configure_parser(parser):
    parser.add_argument(
        "--source-url",
        default=None,
        help="override the base URL of the provider (e.g. http://localhost:8080/data)",
    )


def main() -> None:
    cli = DownloadCLI(
        configure_parser=configure_parser,
        create_downloader=lambda args: AbcDownloader(
            **create_base_downloader_init_kwargs(args),
            source_url=args.source_url,
        ),
        package_name=abc_fetcher.__name__,
    )
    cli.run()


if __name__ == "__main__":
    main()

The downloader then uses source_url in its _iter_resources method:

src/abc_fetcher/downloader.py
class AbcDownloader(BaseDownloader):
    def __init__(self, source_url: str | None = None, **kwargs):
        super().__init__(**kwargs)
        self._source_url = source_url or "https://abc-provider.com/data"

    def _iter_resources(self) -> Iterator[BaseResource]:
        # ...
        yield HttpResource(
            id="catalog",
            request=f"{self._source_url}/catalog.json",
            target_file=source_data_dir_manager.catalog_file,
        )

Example: add a language option in convert.py

Here is an example of how to add a language option to the convert script. ConvertCLI accepts the same configure_parser callback:

convert.py
from dbnomics_toolbox.fetcher_utils import (
    ConvertCLI,
    create_base_converter_init_kwargs,
)

import abc_fetcher
from abc_fetcher.converter import AbcConverter


def configure_parser(parser):
    parser.add_argument(
        "--language",
        default=None,
        choices=("en", "fr", "de"),
        help="output language",
    )


def main() -> None:
    cli = ConvertCLI(
        configure_parser=configure_parser,
        create_converter=lambda args: AbcConverter(
            **create_base_converter_init_kwargs(
                args,
                provider_code=AbcConverter.get_provider_metadata().code,
            ),
            language=args.language,
        ),
        package_name=abc_fetcher.__name__,
    )
    cli.run()


if __name__ == "__main__":
    main()

The converter then stores language and can use it wherever it wants:

src/abc_fetcher/converter.py
class AbcConverter(BaseConverter):
    def __init__(self, language: str | None = None, **kwargs):
        super().__init__(**kwargs)
        self._language = language or "en"