.. Comment: this file is automatically generated by `update_example_docs.py`. It should not be modified manually. .. _example-category-generics: Generics ======== :mod:`tyro`'s understanding of Python's type system includes user-defined parameterized types, which can reduce boilerplate and improve type safety. .. _example-01_generics_py312: Generics (3.12+) ---------------- This example uses syntax introduced in Python 3.12 (`PEP 695 `_). .. note:: If used in conjunction with :code:`from __future__ import annotations`, the updated type parameter syntax requires Python 3.12.4 or newer. For technical details, see `this CPython PR `_. .. code-block:: python :linenos: # 01_generics_py312.py import dataclasses import tyro @dataclasses.dataclass class Point3[ScalarType: (int, float)]: x: ScalarType y: ScalarType z: ScalarType frame_id: str @dataclasses.dataclass class Triangle: a: Point3[float] b: Point3[float] c: Point3[float] @dataclasses.dataclass class Args[ShapeType]: shape: ShapeType if __name__ == "__main__": args = tyro.cli(Args[Triangle]) print(args) .. raw:: html
    $ python ./01_generics_py312.py --help
    usage: 01_generics_py312.py [-h] [OPTIONS]
    
    ╭─ options ───────────────────────────────────────────────╮
     -h, --help              show this help message and exit 
    ╰─────────────────────────────────────────────────────────╯
    ╭─ shape.a options ───────────────────────────────────────╮
     --shape.a.x FLOAT       (required)                      
     --shape.a.y FLOAT       (required)                      
     --shape.a.z FLOAT       (required)                      
     --shape.a.frame-id STR  (required)                      
    ╰─────────────────────────────────────────────────────────╯
    ╭─ shape.b options ───────────────────────────────────────╮
     --shape.b.x FLOAT       (required)                      
     --shape.b.y FLOAT       (required)                      
     --shape.b.z FLOAT       (required)                      
     --shape.b.frame-id STR  (required)                      
    ╰─────────────────────────────────────────────────────────╯
    ╭─ shape.c options ───────────────────────────────────────╮
     --shape.c.x FLOAT       (required)                      
     --shape.c.y FLOAT       (required)                      
     --shape.c.z FLOAT       (required)                      
     --shape.c.frame-id STR  (required)                      
    ╰─────────────────────────────────────────────────────────╯
    
.. _example-02_generics: Generics (Python <3.12) ----------------------- The legacy :py:class:`typing.Generic` and :py:class:`typing.TypeVar` syntax for generic types is also supported. .. code-block:: python :linenos: # 02_generics.py import dataclasses from typing import Generic, TypeVar import tyro ScalarType = TypeVar("ScalarType", int, float) ShapeType = TypeVar("ShapeType") @dataclasses.dataclass class Point3(Generic[ScalarType]): x: ScalarType y: ScalarType z: ScalarType frame_id: str @dataclasses.dataclass class Triangle: a: Point3[float] b: Point3[float] c: Point3[float] @dataclasses.dataclass class Args(Generic[ShapeType]): shape: ShapeType if __name__ == "__main__": args = tyro.cli(Args[Triangle]) print(args) .. raw:: html
    $ python ./02_generics.py --help
    usage: 02_generics.py [-h] [OPTIONS]
    
    ╭─ options ───────────────────────────────────────────────╮
     -h, --help              show this help message and exit 
    ╰─────────────────────────────────────────────────────────╯
    ╭─ shape.a options ───────────────────────────────────────╮
     --shape.a.x FLOAT       (required)                      
     --shape.a.y FLOAT       (required)                      
     --shape.a.z FLOAT       (required)                      
     --shape.a.frame-id STR  (required)                      
    ╰─────────────────────────────────────────────────────────╯
    ╭─ shape.b options ───────────────────────────────────────╮
     --shape.b.x FLOAT       (required)                      
     --shape.b.y FLOAT       (required)                      
     --shape.b.z FLOAT       (required)                      
     --shape.b.frame-id STR  (required)                      
    ╰─────────────────────────────────────────────────────────╯
    ╭─ shape.c options ───────────────────────────────────────╮
     --shape.c.x FLOAT       (required)                      
     --shape.c.y FLOAT       (required)                      
     --shape.c.z FLOAT       (required)                      
     --shape.c.frame-id STR  (required)                      
    ╰─────────────────────────────────────────────────────────╯
    
.. _example-03_generic_subcommands: Generic Subcommands ------------------- Just like standard classes, generic classes within unions can be selected between using subcommands. .. code-block:: python :linenos: # 03_generic_subcommands.py import dataclasses from pathlib import Path import tyro @dataclasses.dataclass class Sgd: lr: float = 1e-4 @dataclasses.dataclass class Adam: lr: float = 3e-4 betas: tuple[float, float] = (0.9, 0.999) @dataclasses.dataclass class Experiment[OptimizerT: (Adam, Sgd)]: path: Path opt: OptimizerT if __name__ == "__main__": args = tyro.cli(Experiment[Adam] | Experiment[Sgd]) print(args) .. raw:: html
    $ python ./03_generic_subcommands.py --help
    usage: 03_generic_subcommands.py [-h] {experiment-adam,experiment-sgd}
    
    ╭─ options ─────────────────────────────────────────╮
     -h, --help        show this help message and exit 
    ╰───────────────────────────────────────────────────╯
    ╭─ subcommands ─────────────────────────────────────╮
     {experiment-adam,experiment-sgd}                  
         experiment-adam                               
         experiment-sgd                                
    ╰───────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./03_generic_subcommands.py experiment-adam --help
    usage: 03_generic_subcommands.py experiment-adam [-h] --path PATH
                                                     [--opt.lr FLOAT]
                                                     [--opt.betas FLOAT FLOAT]
    
    ╭─ options ─────────────────────────────────────────────╮
     -h, --help            show this help message and exit 
     --path PATH           (required)                      
    ╰───────────────────────────────────────────────────────╯
    ╭─ opt options ─────────────────────────────────────────╮
     --opt.lr FLOAT        (default: 0.0003)               
     --opt.betas FLOAT FLOAT                               
                           (default: 0.9 0.999)            
    ╰───────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./03_generic_subcommands.py experiment-sgd --help
    usage: 03_generic_subcommands.py experiment-sgd [-h] --path PATH
                                                    [--opt.lr FLOAT]
    
    ╭─ options ─────────────────────────────────────────────╮
     -h, --help            show this help message and exit 
     --path PATH           (required)                      
    ╰───────────────────────────────────────────────────────╯
    ╭─ opt options ─────────────────────────────────────────╮
     --opt.lr FLOAT        (default: 0.0001)               
    ╰───────────────────────────────────────────────────────╯
    
.. raw:: html
    $ python ./03_generic_subcommands.py experiment-adam --path /tmp --opt.lr 1e-3
    Experiment(path=PosixPath('/tmp'), opt=Adam(lr=0.001, betas=(0.9, 0.999)))