`_.
.. 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)))