.. Comment: this file is automatically generated by `update_example_docs.py`. It should not be modified manually. .. _example-category-basics: Basics ====== In these examples, we show basic examples of using :func:`tyro.cli`: functions, dataclasses, supported annotations, and configuration. .. _example-01_functions: Functions --------- In the simplest case, :func:`tyro.cli()` can be used to run a function with arguments populated from the CLI. .. code-block:: python :linenos: # 01_functions.py import tyro def main(field1: str, field2: int = 3) -> None: """Function, whose arguments will be populated from a CLI interface. Args: field1: A string field. field2: A numeric field, with a default value. """ print(field1, field2) if __name__ == "__main__": tyro.cli(main) We can use ``--help`` to show the help message, or ``--field1`` and ``--field2`` to set the arguments: .. raw:: html
    $ python ./01_functions.py --help
    usage: 01_functions.py [-h] --field1 STR [--field2 INT]
    
    Function, whose arguments will be populated from a CLI interface.
    
    ╭─ options ───────────────────────────────────────────────────────────────╮
     -h, --help          show this help message and exit                     
     --field1 STR        A string field. (required)                          
     --field2 INT        A numeric field, with a default value. (default: 3) 
    ╰─────────────────────────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./01_functions.py --field1 hello
    hello 3
    
.. raw:: html
    $ python ./01_functions.py --field1 hello --field2 10
    hello 10
    
.. _example-02_dataclasses: Dataclasses ----------- In addition to functions, :func:`tyro.cli()` can also take dataclasses as input. .. code-block:: python :linenos: # 02_dataclasses.py from dataclasses import dataclass from pprint import pprint import tyro @dataclass class Args: """Description. This should show up in the helptext!""" field1: str """A string field.""" field2: int = 3 """A numeric field, with a default value.""" if __name__ == "__main__": args = tyro.cli(Args) pprint(args) To show the help message, we can use the ``--help`` flag: .. raw:: html
    $ python ./02_dataclasses.py --help
    usage: 02_dataclasses.py [-h] --field1 STR [--field2 INT]
    
    Description. This should show up in the helptext!
    
    ╭─ options ───────────────────────────────────────────────────────────────╮
     -h, --help          show this help message and exit                     
     --field1 STR        A string field. (required)                          
     --field2 INT        A numeric field, with a default value. (default: 3) 
    ╰─────────────────────────────────────────────────────────────────────────╯
    
We can override ``field1`` and ``field2``: .. raw:: html
    $ python ./02_dataclasses.py --field1 hello
    Args(field1='hello', field2=3)
    
.. raw:: html
    $ python ./02_dataclasses.py --field1 hello --field2 5
    Args(field1='hello', field2=5)
    
.. _example-03_multivalue: Multi-value Arguments --------------------- Arguments of both fixed and variable lengths can be annotated with standard Python collection types. For Python 3.7 and 3.8, we can use either ``from __future__ import annotations`` to support ``list[T]`` and ``tuple[T]``, or the older :py:class:`typing.List` and :py:data:`typing.Tuple`. .. code-block:: python :linenos: # 03_multivalue.py import pathlib from dataclasses import dataclass from pprint import pprint import tyro @dataclass class Config: # Example of a variable-length tuple. `list[T]`, `set[T]`, # `dict[K, V]`, etc are supported as well. source_paths: tuple[pathlib.Path, ...] """This can be multiple!""" # Fixed-length tuples are also okay. dimensions: tuple[int, int] = (32, 32) """Height and width.""" if __name__ == "__main__": config = tyro.cli(Config) pprint(config) To print help: .. raw:: html
    $ python ./03_multivalue.py --help
    usage: 03_multivalue.py [-h] --source-paths [PATH
                            [PATH ...]] [--dimensions INT INT]
    
    ╭─ options ──────────────────────────────────────────────────╮
     -h, --help              show this help message and exit    
     --source-paths [PATH [PATH ...]]                           
                             This can be multiple! (required)   
     --dimensions INT INT    Height and width. (default: 32 32) 
    ╰────────────────────────────────────────────────────────────╯
    
We can override arguments: .. raw:: html
    $ python ./03_multivalue.py --source-paths ./data --dimensions 16 16
    Config(source_paths=(PosixPath('data'),), dimensions=(16, 16))
    
.. raw:: html
    $ python ./03_multivalue.py --source-paths ./data1 ./data2
    Config(source_paths=(PosixPath('data1'), PosixPath('data2')),
           dimensions=(32, 32))
    
.. _example-04_flags: Booleans and Flags ------------------ Booleans can either be expected to be explicitly passed in, or, if given a default value, automatically converted to flags. To turn off conversion, see :class:`tyro.conf.FlagConversionOff`. .. code-block:: python :linenos: # 04_flags.py from dataclasses import dataclass from pprint import pprint import tyro @dataclass class Args: # Boolean. This expects an explicit "True" or "False". boolean: bool # Optional boolean. Same as above, but can be omitted. optional_boolean: bool | None = None # Pass --flag-a in to set this value to True. flag_a: bool = False # Pass --no-flag-b in to set this value to False. flag_b: bool = True if __name__ == "__main__": args = tyro.cli(Args) pprint(args) .. raw:: html
    $ python ./04_flags.py --help
    usage: 04_flags.py [-h] [OPTIONS]
    
    ╭─ options ────────────────────────────────────────────────────────────────╮
     -h, --help                                                               
         show this help message and exit                                      
     --boolean {True,False}                                                   
         Boolean. This expects an explicit "True" or "False". (required)      
     --optional-boolean {None,True,False}                                     
         Optional boolean. Same as above, but can be omitted. (default: None) 
     --flag-a, --no-flag-a                                                    
         Pass --flag-a in to set this value to True. (default: False)         
     --flag-b, --no-flag-b                                                    
         Pass --no-flag-b in to set this value to False. (default: True)      
    ╰──────────────────────────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./04_flags.py --boolean True
    Args(boolean=True, optional_boolean=None, flag_a=False, flag_b=True)
    
.. raw:: html
    $ python ./04_flags.py --boolean False --flag-a
    Args(boolean=False, optional_boolean=None, flag_a=True, flag_b=True)
    
.. raw:: html
    $ python ./04_flags.py --boolean False --no-flag-b
    Args(boolean=False, optional_boolean=None, flag_a=False, flag_b=False)
    
.. _example-05_choices: Choices ------- :py:data:`typing.Literal[]` can be used to restrict inputs to a fixed set of literal choices. .. code-block:: python :linenos: # 05_choices.py import dataclasses from pprint import pprint from typing import Literal import tyro @dataclasses.dataclass class Args: # We can use Literal[] to restrict the set of allowable inputs, for example, over # a set of strings. string: Literal["red", "green"] = "red" # Integers also work. (as well as booleans, enums, etc) number: Literal[0, 1, 2] = 0 if __name__ == "__main__": args = tyro.cli(Args) pprint(args) .. raw:: html
    $ python ./05_choices.py --help
    usage: 05_choices.py [-h] [--string {red,green}] [--number {0,1,2}]
    
    ╭─ options ──────────────────────────────────────────────────────────────────╮
     -h, --help              show this help message and exit                    
     --string {red,green}    We can use Literal[] to restrict the set of        
                             allowable inputs, for example, over a set of       
                             strings. (default: red)                            
     --number {0,1,2}        Integers also work. (as well as booleans, enums,   
                             etc) (default: 0)                                  
    ╰────────────────────────────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./05_choices.py --string red
    Args(string='red', number=0)
    
.. raw:: html
    $ python ./05_choices.py --string blue
    ╭─ Parsing error ────────────────────────────────────────────────────────╮
     Argument --string: invalid choice: 'blue' (choose from 'red', 'green') 
     ────────────────────────────────────────────────────────────────────── 
     For full helptext, run 05_choices.py --help                            
    ╰────────────────────────────────────────────────────────────────────────╯
    
.. _example-06_enums: Enums ----- In addition to literals, enums can also be used to provide a fixed set of choices. .. code-block:: python :linenos: # 06_enums.py import enum from dataclasses import dataclass from pprint import pprint import tyro class Color(enum.Enum): RED = enum.auto() BLUE = enum.auto() @dataclass class Config: color: Color = Color.RED """Color argument.""" opacity: float = 0.5 """Opacity argument.""" if __name__ == "__main__": config = tyro.cli(Config) pprint(config) .. raw:: html
    $ python ./06_enums.py --help
    usage: 06_enums.py [-h] [--color {RED,BLUE}] [--opacity FLOAT]
    
    ╭─ options ────────────────────────────────────────────────╮
     -h, --help              show this help message and exit  
     --color {RED,BLUE}      Color argument. (default: RED)   
     --opacity FLOAT         Opacity argument. (default: 0.5) 
    ╰──────────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./06_enums.py --color RED
    Config(color=<Color.RED: 1>, opacity=0.5)
    
.. raw:: html
    $ python ./06_enums.py --color BLUE --opacity 0.75
    Config(color=<Color.BLUE: 2>, opacity=0.75)
    
.. _example-07_unions: Unions ------ :code:`X | Y` or :py:data:`typing.Union` can be used to expand inputs to multiple types. .. code-block:: python :linenos: # 07_unions.py import dataclasses import enum from pprint import pprint from typing import Literal, Optional import tyro class Color(enum.Enum): RED = enum.auto() GREEN = enum.auto() BLUE = enum.auto() @dataclasses.dataclass(frozen=True) class Args: # Unions can be used to specify multiple allowable types. union_over_types: int | str = 0 string_or_enum: Literal["red", "green"] | Color = "red" # Unions also work over more complex nested types. union_over_tuples: tuple[int, int] | tuple[str] = ("1",) # And can be nested in other types. tuple_of_string_or_enum: tuple[Literal["red", "green"] | Color, ...] = ( "red", Color.RED, ) # Optional[T] is equivalent to `T | None`. integer: Optional[Literal[0, 1, 2, 3]] = None if __name__ == "__main__": args = tyro.cli(Args) pprint(args) .. raw:: html
    $ python ./07_unions.py --help
    usage: 07_unions.py [-h] [OPTIONS]
    
    ╭─ options ──────────────────────────────────────────────────────────────────╮
     -h, --help                                                                 
         show this help message and exit                                        
     --union-over-types INT|STR                                                 
         Unions can be used to specify multiple allowable types. (default: 0)   
     --string-or-enum {red,green,RED,GREEN,BLUE}                                
         Unions can be used to specify multiple allowable types. (default: red) 
     --union-over-tuples {INT INT}|STR                                          
         Unions also work over more complex nested types. (default: 1)          
     --tuple-of-string-or-enum [{red,green,RED,GREEN,BLUE}                      
     [{red,green,RED,GREEN,BLUE} ...]]                                          
         And can be nested in other types. (default: red RED)                   
     --integer {None,0,1,2,3}                                                   
         Optional[T] is equivalent to `T | None`. (default: None)               
    ╰────────────────────────────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./07_unions.py --union-over-types 3
    Args(union_over_types=3,
         string_or_enum='red',
         union_over_tuples=('1',),
         tuple_of_string_or_enum=('red', <Color.RED: 1>),
         integer=None)
    
.. raw:: html
    $ python ./07_unions.py --union-over-types three
    Args(union_over_types='three',
         string_or_enum='red',
         union_over_tuples=('1',),
         tuple_of_string_or_enum=('red', <Color.RED: 1>),
         integer=None)
    
.. raw:: html
    $ python ./07_unions.py --integer None
    Args(union_over_types=0,
         string_or_enum='red',
         union_over_tuples=('1',),
         tuple_of_string_or_enum=('red', <Color.RED: 1>),
         integer=None)
    
.. raw:: html
    $ python ./07_unions.py --integer 0
    Args(union_over_types=0,
         string_or_enum='red',
         union_over_tuples=('1',),
         tuple_of_string_or_enum=('red', <Color.RED: 1>),
         integer=0)
    
.. _example-08_positional: Positional Arguments -------------------- Positional-only arguments in functions are converted to positional CLI arguments. For more general positional arguments, see :class:`tyro.conf.Positional`. .. code-block:: python :linenos: # 08_positional.py from __future__ import annotations import pathlib import tyro def main( source: pathlib.Path, dest: pathlib.Path, /, # Mark the end of positional arguments. verbose: bool = False, ) -> None: """Command-line interface defined using a function signature. This docstring is parsed to generate helptext. Args: source: Source path. dest: Destination path. verbose: Explain what is being done. """ print(f"{source=}\n{dest=}\n{verbose=}") if __name__ == "__main__": tyro.cli(main) .. raw:: html
    $ python 08_positional.py --help
    usage: 08_positional.py [-h] [--verbose | --no-verbose] PATH PATH
    
    Command-line interface defined using a function signature. This docstring is 
    parsed to generate helptext.
    
    ╭─ positional arguments ─────────────────────────────────────────╮
     PATH              Source path. (required)                      
     PATH              Destination path. (required)                 
    ╰────────────────────────────────────────────────────────────────╯
    ╭─ options ──────────────────────────────────────────────────────╮
     -h, --help        show this help message and exit              
     --verbose, --no-verbose                                        
                       Explain what is being done. (default: False) 
    ╰────────────────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python 08_positional.py ./a ./b
    source=PosixPath('a')
    dest=PosixPath('b')
    verbose=False
    
.. raw:: html
    $ python 08_positional.py ./test1 ./test2 --verbose
    source=PosixPath('test1')
    dest=PosixPath('test2')
    verbose=True
    
.. _example-09_conf: Configuration via typing.Annotated[] ------------------------------------ The :mod:`tyro.conf` module contains utilities that can be used in conjunction with :py:data:`typing.Annotated` to configure command-line interfaces beyond what is expressible via static type annotations. Features here are supported, but generally unnecessary and should be used sparingly. .. code-block:: python :linenos: # 09_conf.py import dataclasses from typing_extensions import Annotated import tyro @dataclasses.dataclass class Args: # A numeric field parsed as a positional argument. positional: tyro.conf.Positional[int] # A boolean field with flag conversion turned off. boolean: tyro.conf.FlagConversionOff[bool] = False # A numeric field that can't be changed via the CLI. fixed: tyro.conf.Fixed[int] = 5 # A field with manually overridden properties. manual: Annotated[ str, tyro.conf.arg( name="renamed", metavar="STRING", help="A field with manually overridden properties!", ), ] = "Hello" if __name__ == "__main__": print(tyro.cli(Args)) .. raw:: html
    $ python ./09_conf.py --help
    usage: 09_conf.py [-h] [OPTIONS] INT
    
    ╭─ positional arguments ─────────────────────────────────────────────────────╮
     INT                     A numeric field parsed as a positional argument.   
                             (required)                                         
    ╰────────────────────────────────────────────────────────────────────────────╯
    ╭─ options ──────────────────────────────────────────────────────────────────╮
     -h, --help              show this help message and exit                    
     --boolean {True,False}  A boolean field with flag conversion turned off.   
                             (default: False)                                   
     --fixed {fixed}         A numeric field that can't be changed via the CLI. 
                             (fixed to: 5)                                      
     --renamed STRING        A field with manually overridden properties!       
                             (default: Hello)                                   
    ╰────────────────────────────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./09_conf.py 5 --boolean True
    Args(positional=5, boolean=True, fixed=5, manual='Hello')
    
.. _example-10_aliases: Argument Aliases ---------------- :func:`tyro.conf.arg()` can be used to attach aliases to arguments. .. code-block:: python :linenos: # 10_aliases.py from typing import Annotated import tyro def checkout( branch: Annotated[str, tyro.conf.arg(aliases=["-b"])], ) -> None: """Check out a branch.""" print(f"{branch=}") if __name__ == "__main__": tyro.cli(checkout) .. raw:: html
    $ python ./10_aliases.py --help
    usage: 10_aliases.py [-h] --branch STR
    
    Check out a branch.
    
    ╭─ options ───────────────────────────────────────────────╮
     -h, --help              show this help message and exit 
     --branch STR, -b STR    (required)                      
    ╰─────────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./10_aliases.py --branch main
    branch='main'
    
.. raw:: html
    $ python ./10_aliases.py -b main
    branch='main'
    
.. _example-11_type_aliases_py312: Type Aliases (3.12+) -------------------- In Python 3.12, the :code:`type` statement is introduced to create type aliases. .. code-block:: python :linenos: # 11_type_aliases_py312.py import dataclasses import tyro # Lazily-evaluated type alias. type Field1Type = Inner @dataclasses.dataclass class Inner: a: int b: str @dataclasses.dataclass class Args: """Description. This should show up in the helptext!""" field1: Field1Type """A field.""" field2: int = 3 """A numeric field, with a default value.""" if __name__ == "__main__": args = tyro.cli(Args) print(args) .. raw:: html
    $ python ./11_type_aliases_py312.py --help
    usage: 11_type_aliases_py312.py [-h] [--field2 INT] --field1.a INT --field1.b
                                    STR
    
    Description. This should show up in the helptext!
    
    ╭─ options ─────────────────────────────────────────────────────────────────╮
     -h, --help            show this help message and exit                     
     --field2 INT          A numeric field, with a default value. (default: 3) 
    ╰───────────────────────────────────────────────────────────────────────────╯
    ╭─ field1 options ──────────────────────────────────────────────────────────╮
     A field.                                                                  
     ────────────────────────────────                                          
     --field1.a INT        (required)                                          
     --field1.b STR        (required)                                          
    ╰───────────────────────────────────────────────────────────────────────────╯
    
.. _example-12_counters: Counters -------- Repeatable 'counter' arguments can be specified via :data:`tyro.conf.UseCounterAction`. .. code-block:: python :linenos: # 12_counters.py from typing_extensions import Annotated import tyro from tyro.conf import UseCounterAction def main( verbosity: UseCounterAction[int], aliased_verbosity: Annotated[UseCounterAction[int], tyro.conf.arg(aliases=["-v"])], ) -> None: """Example showing how to use counter actions. Args: verbosity: Verbosity level. aliased_verbosity: Same as above, but can also be specified with -v, -vv, -vvv, etc. """ print("Verbosity level:", verbosity) print("Verbosity level (aliased):", aliased_verbosity) if __name__ == "__main__": tyro.cli(main) .. raw:: html
    $ python ./12_counters.py --help
    usage: 12_counters.py [-h] [--verbosity] [--aliased-verbosity]
    
    Example showing how to use counter actions.
    
    ╭─ options ──────────────────────────────────────────────────────────────────╮
     -h, --help         show this help message and exit                         
     --verbosity        Verbosity level. (repeatable)                           
     --aliased-verbosity, -v                                                    
                        Same as above, but can also be specified with -v, -vv,  
                        -vvv, etc. (repeatable)                                 
    ╰────────────────────────────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./12_counters.py --verbosity
    Verbosity level: 1
    Verbosity level (aliased): 0
    
.. raw:: html
    $ python ./12_counters.py --verbosity --verbosity
    Verbosity level: 2
    Verbosity level (aliased): 0
    
.. raw:: html
    $ python ./12_counters.py -vvv
    Verbosity level: 0
    Verbosity level (aliased): 3
    
.. _example-13_classes: Instantiating Classes --------------------- In addition to functions and dataclasses, we can also generate CLIs from the constructors of standard Python classes. .. code-block:: python :linenos: # 13_classes.py import tyro class Args: def __init__( self, field1: str, field2: int, flag: bool = False, ): """Arguments. Args: field1: A string field. field2: A numeric field. flag: A boolean flag. """ self.data = [field1, field2, flag] if __name__ == "__main__": args = tyro.cli(Args) print(args.data) .. raw:: html
    $ python ./13_classes.py --help
    usage: 13_classes.py [-h] --field1 STR --field2 INT [--flag | --no-flag]
    
    Arguments.
    
    ╭─ options ────────────────────────────────────────────────╮
     -h, --help              show this help message and exit  
     --field1 STR            A string field. (required)       
     --field2 INT            A numeric field. (required)      
     --flag, --no-flag       A boolean flag. (default: False) 
    ╰──────────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./13_classes.py --field1 hello --field2 7
    ['hello', 7, False]