:py:mod:`tyro.extras` ===================== .. py:module:: tyro.extras .. autoapi-nested-parse:: The :mod:`tyro.extras` submodule contains helpers that complement :func:`tyro.cli()`. .. warning:: Compared to the core interface, APIs here are more likely to be changed or deprecated. Package Contents ---------------- .. py:function:: get_parser(f: Type[OutT], *, prog: None | str = None, description: None | str = None, default: OutT | tyro._singleton.NonpropagatingMissingType | tyro._singleton.PropagatingMissingType = MISSING_NONPROP, use_underscores: bool = False, console_outputs: bool = True, add_help: bool = True, config: None | Sequence[tyro.conf._markers.Marker] = None, registry: None | tyro.constructors.ConstructorRegistry = None) -> tyro._backends._argparse.ArgumentParser get_parser(f: Callable[Ellipsis, OutT], *, prog: None | str = None, description: None | str = None, default: OutT | tyro._singleton.NonpropagatingMissingType | tyro._singleton.PropagatingMissingType = MISSING_NONPROP, use_underscores: bool = False, console_outputs: bool = True, add_help: bool = True, config: None | Sequence[tyro.conf._markers.Marker] = None, registry: None | tyro.constructors.ConstructorRegistry = None) -> tyro._backends._argparse.ArgumentParser Get an :py:class:`argparse.ArgumentParser` object that approximates the CLI generated by :func:`tyro.cli`. Useful for tools like ``sphinx-argparse``, ``argcomplete``, etc. .. deprecated:: 1.0.0 This function is deprecated and will be removed in a future version. .. note:: The returned parser uses argparse-style subparsers, which is less flexible than tyro's subcommand parser. For tab completion, we recommend using :func:`tyro.cli`'s built-in ``--tyro-write-completion`` flag. :param f: The function or type to populate from command-line arguments. :param prog: The name of the program to display in the help text. :param description: The description text shown at the top of the help output. :param default: An instance to use for default values. :param use_underscores: If True, uses underscores as word delimiters in the help text. :param console_outputs: If set to False, suppresses parsing errors and help messages. :param add_help: Add a -h/--help option to the parser. This mirrors the argument from :py:class:`argparse.ArgumentParser()`. :param config: A sequence of configuration marker objects from :mod:`tyro.conf`. :param registry: A :class:`tyro.constructors.ConstructorRegistry` instance containing custom constructor rules. .. py:function:: set_accent_color(accent_color: Literal[black, red, green, yellow, blue, magenta, cyan, white, bright_black, bright_red, bright_green, bright_yellow, bright_blue, bright_magenta, bright_cyan, bright_white] | None) -> None Set an accent color to use in help messages. Experimental. .. py:function:: overridable_config_cli(configs: Mapping[str, Tuple[str, T]], *, prog: str | None = None, description: str | None = None, args: Sequence[str] | None = None, use_underscores: bool = False, console_outputs: bool = True, add_help: bool = True, config: Sequence[Any] | None = None, sort_subcommands: bool = False, registry: tyro.constructors.ConstructorRegistry | None = None) -> T Helper function for creating a CLI interface that allows us to choose between default config objects (typically dataclasses) and override values within it. Turns off subcommand creation for any union types within the config object. This is a lightweight wrapper over :func:`tyro.cli()`, with some default arguments populated. Also see :func:`tyro.extras.subcommand_type_from_defaults()`. Example usage: .. code-block:: python import dataclasses import tyro @dataclasses.dataclass class Config: a: int b: str default_configs = { "small": ( "Small config", Config(1, "small"), ), "big": ( "Big config", Config(100, "big"), ), } config = tyro.extras.overridable_config_cli(default_configs) print(config) :param configs: A dictionary of config names mapped to a tuple of (description, config object). :param prog: The name of the program printed in helptext. Mirrors argument from `argparse.ArgumentParser()`. :param description: Description text for the parser, displayed when the --help flag is passed in. If not specified, the class docstring is used. Mirrors argument from `argparse.ArgumentParser()`. :param args: If set, parse arguments from a sequence of strings instead of the commandline. Mirrors argument from `argparse.ArgumentParser.parse_args()`. :param use_underscores: If True, use underscores as a word delimiter instead of hyphens. This primarily impacts helptext; underscores and hyphens are treated equivalently when parsing happens. We default helptext to hyphens to follow the GNU style guide. https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html :param console_outputs: If set to `False`, parsing errors and help messages will be suppressed. :param add_help: Add a -h/--help option to the parser. This mirrors the argument from `argparse.ArgumentParser()`. :param config: Sequence of config marker objects, from `tyro.conf`. We include :class:`tyro.conf.AvoidSubcommands` by default. :param sort_subcommands: If True, sort the subcommands alphabetically by name. :param registry: A :class:`tyro.constructors.ConstructorRegistry` instance containing custom constructor rules. .. py:function:: subcommand_type_from_defaults(defaults: Mapping[str, T], descriptions: Mapping[str, str] = {}, *, prefix_names: bool = True, sort_subcommands: bool = False) -> Type[T] Construct a Union type for defining subcommands that choose between defaults. For example, when ``defaults`` is set to: .. code-block:: python { "small": Config(...), "big": Config(...), } We return: .. code-block:: python Union[ Annotated[ Config, tyro.conf.subcommand("small", default=Config(...)) ], Annotated[ Config, tyro.conf.subcommand("big", default=Config(...)) ] ] Direct use of :py:data:`typing.Union` and :func:`tyro.conf.subcommand()` should generally be preferred, but this function can be helpful for succinctness. .. warning:: The type returned by this function can be safely used as an input to :func:`tyro.cli()`, but for static analysis when used for annotations we recommend applying a `TYPE_CHECKING` guard: .. code-block:: python from typing import TYPE_CHECKING if TYPE_CHECKING: # Static type seen by language servers, type checkers, etc. SelectableConfig = Config else: # Runtime type used by tyro. SelectableConfig = subcommand_type_from_defaults(...) :param defaults: A dictionary of default subcommand instances. :param descriptions: A dictionary conttaining descriptions for helptext. :param prefix_names: Whether to prefix subcommand names. :param sort_subcommands: If True, sort the subcommands alphabetically by name. :returns: A subcommand type, which can be passed to :func:`tyro.cli`. .. py:function:: literal_type_from_choices(choices: Iterable[T]) -> Type[T] Generate a :py:data:`typing.Literal` type that constrains values to a set of choices. Using ``Literal[...]`` directly should generally be preferred, but this function can be helpful when choices are generated dynamically. .. warning:: The type returned by this function can be safely used as an input to :func:`tyro.cli()`, but for static analysis when used for annotations we recommend applying a `TYPE_CHECKING` guard: .. code-block:: python from typing import TYPE_CHECKING if TYPE_CHECKING: # Static type seen by language servers, type checkers, etc. Color = str else: # Runtime type used by tyro. Color = literal_type_from_choices(["red", "green", "blue"]) :param choices: Options to choose from. :returns: A type that can be passed to :func:`tyro.cli()`. .. py:function:: from_yaml(cls: Type[DataclassType], stream: Union[str, IO[str], bytes, IO[bytes]]) -> DataclassType Re-construct a dataclass instance from a yaml-compatible string, which should be generated from :func:`tyro.extras.to_yaml()`. .. warning:: **Deprecated.** Serialization functionality is stable but deprecated. It may be removed in a future version of :code:`tyro`. As a secondary feature aimed at enabling the use of :func:`tyro.cli` for general configuration use cases, we also introduce functions for human-readable dataclass serialization: :func:`tyro.extras.from_yaml` and :func:`tyro.extras.to_yaml` attempt to strike a balance between flexibility and robustness — in contrast to naively dumping or loading dataclass instances (via pickle, PyYAML, etc), explicit type references enable custom tags that are robust against code reorganization and refactor, while a PyYAML backend enables serialization of arbitrary Python objects. :param cls: Type to reconstruct. :param stream: YAML to read from. :returns: Instantiated dataclass. .. py:function:: to_yaml(instance: Any) -> str Serialize a dataclass; returns a yaml-compatible string that can be deserialized via :func:`tyro.extras.from_yaml()`. .. warning:: **Deprecated.** Serialization functionality is stable but deprecated. It may be removed in a future version of :code:`tyro`. As a secondary feature aimed at enabling the use of :func:`tyro.cli` for general configuration use cases, we also introduce functions for human-readable dataclass serialization: :func:`tyro.extras.from_yaml` and :func:`tyro.extras.to_yaml` attempt to strike a balance between flexibility and robustness — in contrast to naively dumping or loading dataclass instances (via pickle, PyYAML, etc), explicit type references enable custom tags that are robust against code reorganization and refactor, while a PyYAML backend enables serialization of arbitrary Python objects. :param instance: Dataclass instance to serialize. :returns: YAML string. .. py:class:: SubcommandApp This class provides a decorator-based API for subcommands in :mod:`tyro`, inspired by `Typer `_ and `cyclopts `_. Under-the-hood, this is a light wrapper over :func:`tyro.cli`. Example: .. code-block:: python from tyro.extras import SubcommandApp app = SubcommandApp() @app.command def greet(name: str, loud: bool = False): '''Greet someone.''' greeting = f"Hello, {name}!" if loud: greeting = greeting.upper() print(greeting) @app.command(name="addition", aliases=["sum"]) def add(a: int, b: int): '''Add two numbers.''' print(f"{a} + {b} = {a + b}") if __name__ == "__main__": app.cli() Subcommand groups can be nested by registering one :class:`SubcommandApp` as a subcommand on another: .. code-block:: python db = SubcommandApp() @db.command def migrate(): ... @db.command def seed(): ... app = SubcommandApp() app.command(db, name="db") # `mycli db migrate`, `mycli db seed` To make one subcommand the default when no subcommand is given, pass ``is_default=True``: .. code-block:: python @app.command(is_default=True) def run(name: str = "world"): print(f"hello {name}") # `mycli` runs `run("world")`; `mycli --name alice` runs `run("alice")`; # `mycli run --name alice` also works. Usage: .. code-block:: bash python my_script.py greet Alice python my_script.py greet Bob --loud python my_script.py addition 5 3 python my_script.py sum 5 3 # via alias .. py:method:: command(func: CallableT) -> CallableT command(func: None = None, *, name: str | None = None, aliases: Sequence[str] | None = None, help: str | None = None, is_default: bool = False) -> Callable[[CallableT], CallableT] command(func: SubcommandApp, *, name: str | None = None, aliases: Sequence[str] | None = None, help: str | None = None, is_default: bool = False) -> SubcommandApp Register a function or nested :class:`SubcommandApp` as a subcommand. This method is inspired by Typer's ``@app.command()`` and cyclopts's ``@app.command()`` decorators. :param func: The function (or :class:`SubcommandApp` instance) to register. If ``None``, returns a decorator. :param name: Name of the subcommand. Defaults to the function's ``__name__``. Required when registering a :class:`SubcommandApp` (since the app has no name of its own). :param aliases: Alternative names that resolve to the same subcommand. For example, ``aliases=["sum"]`` lets users invoke ``add`` as either ``add`` or ``sum``. :param help: Override the helptext for this subcommand. If not set, the function's docstring (or nested app's description) is used. :param is_default: If ``True``, this subcommand becomes the implicit choice when the user invokes the CLI without naming a subcommand. At most one command per :class:`SubcommandApp` may set this. .. py:method:: cli(*, prog: str | None = None, description: str | None = None, args: Sequence[str] | None = None, use_underscores: bool = False, console_outputs: bool = True, add_help: bool = True, config: Sequence[Any] | None = None, sort_subcommands: bool = False, registry: tyro.constructors.ConstructorRegistry | None = None) -> Any Run the command-line interface. This method creates a CLI using tyro, with all subcommands registered using :func:`command()`. :param prog: The name of the program printed in helptext. Mirrors argument from `argparse.ArgumentParser()`. :param description: Description text for the parser, displayed when the --help flag is passed in. If not specified, the class docstring is used. Mirrors argument from `argparse.ArgumentParser()`. :param args: If set, parse arguments from a sequence of strings instead of the commandline. Mirrors argument from `argparse.ArgumentParser.parse_args()`. :param use_underscores: If True, use underscores as a word delimiter instead of hyphens. This primarily impacts helptext; underscores and hyphens are treated equivalently when parsing happens. We default helptext to hyphens to follow the GNU style guide. https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html :param console_outputs: If set to `False`, parsing errors and help messages will be suppressed. :param add_help: Add a -h/--help option to the parser. This mirrors the argument from `argparse.ArgumentParser()`. :param config: Sequence of config marker objects, from `tyro.conf`. :param sort_subcommands: If True, sort the subcommands alphabetically by name. :param registry: A :class:`tyro.constructors.ConstructorRegistry` instance containing custom constructor rules. .. py:function:: subcommand_cli_from_dict(subcommands: Dict[str, Callable[Ellipsis, T]], *, prog: str | None = None, description: str | None = None, args: Sequence[str] | None = None, use_underscores: bool = False, console_outputs: bool = True, add_help: bool = True, config: Sequence[tyro.conf._markers.Marker] | None = None, sort_subcommands: bool = False, registry: tyro.constructors.ConstructorRegistry | None = None) -> T subcommand_cli_from_dict(subcommands: Dict[str, Callable[Ellipsis, Any]], *, prog: str | None = None, description: str | None = None, args: Sequence[str] | None = None, use_underscores: bool = False, console_outputs: bool = True, add_help: bool = True, config: Sequence[tyro.conf._markers.Marker] | None = None, sort_subcommands: bool = False, registry: tyro.constructors.ConstructorRegistry | None = None) -> Any Generate a subcommand CLI from a dictionary of functions. For an input like: .. code-block:: python tyro.extras.subcommand_cli_from_dict( { "checkout": checkout, "commit": commit, } ) This is internally accomplished by generating and calling: .. code-block:: python from typing import Annotated, Any, Union import tyro tyro.cli( Union[ Annotated[ Any, tyro.conf.subcommand(name="checkout", constructor=checkout), ], Annotated[ Any, tyro.conf.subcommand(name="commit", constructor=commit), ], ] ) :param subcommands: Dictionary that maps the subcommand name to function to call. :param prog: The name of the program printed in helptext. Mirrors argument from :py:class:`argparse.ArgumentParser`. :param description: Description text for the parser, displayed when the --help flag is passed in. If not specified, `f`'s docstring is used. Mirrors argument from :py:class:`argparse.ArgumentParser`. :param args: If set, parse arguments from a sequence of strings instead of the commandline. Mirrors argument from :py:meth:`argparse.ArgumentParser.parse_args()`. :param use_underscores: If True, use underscores as a word delimiter instead of hyphens. This primarily impacts helptext; underscores and hyphens are treated equivalently when parsing happens. We default helptext to hyphens to follow the GNU style guide. https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html :param console_outputs: If set to ``False``, parsing errors and help messages will be supressed. This can be useful for distributed settings, where :func:`tyro.cli()` is called from multiple workers but we only want console outputs from the main one. :param add_help: Add a -h/--help option to the parser. This mirrors the argument from :py:class:`argparse.ArgumentParser()`. :param config: Sequence of config marker objects, from :mod:`tyro.conf`. :param registry: A :class:`tyro.constructors.ConstructorRegistry` instance containing custom constructor rules. .. py:class:: Verbosity Parsed verbosity counters from ``-v``/``-q`` CLI flags. Drop into any tyro CLI struct to get standard ``--verbose``/``-v`` and ``--quiet``/``-q`` count flags that map to Python :mod:`logging` levels. The two flags are mutually exclusive. Example:: import logging import tyro from dataclasses import dataclass, field from tyro.extras import Verbosity @dataclass class Args: verbosity: Verbosity = Verbosity() args = tyro.cli(Args) logging.basicConfig(level=args.verbosity.log_level()) Default level mapping (baseline: ``logging.WARNING``): .. code-block:: text (none) → WARNING (30) -v → INFO (20) -vv → DEBUG (10) -q → ERROR (40) -qq → CRITICAL (50) Values are clamped to the ``DEBUG``..``CRITICAL`` range. .. py:attribute:: verbose :type: typing_extensions.Annotated[tyro.conf.UseCounterAction[int], conf.arg(aliases=['-v'], help='Increase log verbosity.'), _verbosity_mutex] :value: 0 .. py:attribute:: quiet :type: typing_extensions.Annotated[tyro.conf.UseCounterAction[int], conf.arg(aliases=['-q'], help='Decrease log verbosity.'), _verbosity_mutex] :value: 0 .. py:method:: log_level(*, default: int = logging.WARNING) -> int Compute the effective logging level, clamped to ``DEBUG``..``CRITICAL``. Formula: ``default + (quiet - verbose) * 10``. :param default: Baseline logging level. Defaults to ``logging.WARNING``. :returns: An integer logging level suitable for :func:`logging.basicConfig`.