Skip to content

click won't work with specialzed converter

Given the current version and a specialized converter won't work well together with click as long I don't redefine the type to str.

I would expect that either typed-settings does this under the hood automatically when using a custom converter. Or at least that there is a section in the docu explaining how to do this.

$ pip freeze
pip freeze
APScheduler==3.10.1
attrs==23.1.0
cattrs==23.1.2
click==8.1.6
pytz==2023.3
six==1.16.0
typed-settings @ git+https://gitlab.com/sscherfke/typed-settings.git@e220b900da8e1bee6965e8e8b50b7d419c42c068
types-setuptools==67.8.0.0
tzlocal==5.0.1

The example script mvp.py

#!/bin/env python
from typing import Any

import click
import typed_settings as ts
from apscheduler.triggers.cron import CronTrigger


@ts.settings
class Settings:
    interval: CronTrigger = CronTrigger(minute="*/20", jitter=60 * 8)
# The following version works but is not very intuitive
#    interval: CronTrigger = ts.option(default=CronTrigger(minute="*/20", jitter=60 * 8), click={'type': str})


def convert_cron_entry(val: Any, target: type) -> CronTrigger | None:
    """
    Convert an settings entry (a string) to a CronTrigger, handling None
    """
    if isinstance(val, CronTrigger):
        return val
    return CronTrigger.from_crontab(str(val))


def is_crontrigger(type_: type) -> bool:
    if type_ == CronTrigger:
        return True
    return False


converter = ts.default_converter()
converter.register_structure_hook_func(is_crontrigger, convert_cron_entry)


@click.command()
@ts.click_options(Settings, converter=converter, loaders=[])
def cli(settings: Settings):
    print(f"{settings.interval=}\n{settings=!r}")

if __name__ == '__main__':
    cli()

Now simply executing will brake things:

$ ./mvp.py               
Usage: mvp.py [OPTIONS]
Try 'mvp.py --help' for help.

Error: Invalid value for '--interval': cron[minute='*/20']
$ ./mvp.py --interval "*/30 * * * *"
cron[minute='*/20']
Usage: mvp.py [OPTIONS]
Try 'mvp.py --help' for help.

Error: Invalid value for '--interval': */30 * * * *
Edited by Carli* Freudenberg