Custom Constructors#

For additional flexibility, tyro.conf.arg() accepts a constructor argument, which makes it easier to load complex objects.

 1import json as json_
 2
 3from typing_extensions import Annotated
 4
 5import tyro
 6
 7
 8def dict_json_constructor(json: str) -> dict:
 9    """Construct a dictionary from a JSON string. Raises a ValueError if the result is
10    not a dictionary."""
11    out = json_.loads(json)
12    if not isinstance(out, dict):
13        raise ValueError(f"{json} is not a dictionary!")
14    return out
15
16
17# A dictionary type, but `tyro` will expect a JSON string from the CLI.
18JsonDict = Annotated[dict, tyro.conf.arg(constructor=dict_json_constructor)]
19
20
21def main(
22    dict1: JsonDict,
23    dict2: JsonDict = {"default": None},
24) -> None:
25    print(f"{dict1=}")
26    print(f"{dict2=}")
27
28
29if __name__ == "__main__":
30    tyro.cli(main)

python 04_additional/11_custom_constructors.py --help
usage: 11_custom_constructors.py [-h] --dict1.json STR [--dict2.json STR]

╭─ options ──────────────────────────────────────────────────────────────────╮
│ -h, --help              show this help message and exit                    │
╰────────────────────────────────────────────────────────────────────────────╯
╭─ dict1 options ────────────────────────────────────────────────────────────╮
│ Construct a dictionary from a JSON string. Raises a ValueError if the      │
│ result is                                                                  │
│ not a dictionary.                                                          │
│ ────────────────────────────────────────────────────────────────────────── │
│ --dict1.json STR        (required)                                         │
╰────────────────────────────────────────────────────────────────────────────╯
╭─ dict2 options ────────────────────────────────────────────────────────────╮
│ Construct a dictionary from a JSON string. Raises a ValueError if the      │
│ result is                                                                  │
│ not a dictionary.                                                          │
│                                                                            │
│ Default: {'default': None}                                                 │
│ ────────────────────────────────────────────────────────────────────────── │
│ --dict2.json STR        (optional)                                         │
╰────────────────────────────────────────────────────────────────────────────╯

python 04_additional/11_custom_constructors.py --dict1.json '{"hello": "world"}'
dict1={'hello': 'world'}
dict2={'default': None}

python 04_additional/11_custom_constructors.py --dict1.json '{"hello": "world"}`' --dict2.json '{"hello": "world"}'
╭─ Value error ────────────────────────────────────────────────────────────────╮
│ Error parsing dict1: Extra data: line 1 column 19 (char 18)                  │
╰──────────────────────────────────────────────────────────────────────────────╯