.. Comment: this file is automatically generated by `update_example_docs.py`.
   It should not be modified manually.

.. _example-category-overriding_configs:

Overriding Configs
==================

In these examples, we show how :func:`tyro.cli` can be used to override values
in pre-instantiated configuration objects.


.. _example-01_dataclasses_defaults:

Dataclasses + Defaults
----------------------

The :code:`default=` argument can be used to override default values in dataclass
types.


.. note::

    When ``default=`` is used, we advise against mutation of configuration
    objects from a dataclass's :code:`__post_init__` method [#f1]_. In the
    example below, :code:`__post_init__` would be called twice: once for the
    :code:`Args()` object provided as a default value and another time for the
    :code:`Args()` objected instantiated by :func:`tyro.cli()`. This can cause
    confusing behavior! Instead, we show below one example of how derived
    fields can be defined immutably.

    .. [#f1] Official Python docs for ``__post_init__`` can be found `here <https://docs.python.org/3/library/dataclasses.html#dataclasses.__post_init__>`_.


.. code-block:: python
    :linenos:

    # 01_dataclasses_defaults.py
    import dataclasses

    import tyro

    @dataclasses.dataclass
    class Args:
        """Description.
        This should show up in the helptext!"""

        string: str
        """A string field."""

        reps: int = 3
        """A numeric field, with a default value."""

        @property
        def derived_field(self) -> str:
            return ", ".join([self.string] * self.reps)

    if __name__ == "__main__":
        args = tyro.cli(
            Args,
            default=Args(
                string="default string",
                reps=tyro.MISSING,
            ),
        )
        print(args.derived_field)




.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./01_dataclasses_defaults.py --help</strong>
    <span style="font-weight: bold">usage</span>: 01_dataclasses_defaults.py [-h] [--string <span style="font-weight: bold">STR</span>] --reps <span style="font-weight: bold">INT</span>
    
    Description. This should show up in the helptext!
    
    <span style="font-weight: lighter">╭─</span><span style="font-weight: lighter"> options </span><span style="font-weight: lighter">────────────────────────────────────────────────────────────</span><span style="font-weight: lighter">─╮</span>
    <span style="font-weight: lighter">│</span> -h, --help          <span style="font-weight: lighter">show this help message and exit</span>                   <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --string <span style="font-weight: bold">STR</span>        <span style="font-weight: lighter">A string field.</span> <span style="color: #008080">(default: 'default string')</span>       <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --reps <span style="font-weight: bold">INT</span>          <span style="font-weight: lighter">A numeric field, with a default value.</span> <span style="font-weight: bold; color: #e60000">(required)</span> <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">╰───────────────────────────────────────────────────────────────────────╯</span>
    </pre>



.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./01_dataclasses_defaults.py --reps 3</strong>
    default string, default string, default string
    </pre>



.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./01_dataclasses_defaults.py --string hello --reps 5</strong>
    hello, hello, hello, hello, hello
    </pre>
.. _example-02_overriding_yaml:

Overriding YAML Configs
-----------------------

:mod:`tyro` understands a wide range of data structures, including standard
dictionaries and lists.

If you have a library of existing YAML files that you want to use,
:func:`tyro.cli` can help override values within them.

.. note::

    We recommend dataclass configs for new projects.


.. code-block:: python
    :linenos:

    # 02_overriding_yaml.py
    import yaml

    import tyro

    # YAML configuration. This could also be loaded from a file! Environment
    # variables are an easy way to select between different YAML files.
    default_yaml = r"""
    exp_name: test
    optimizer:
        learning_rate: 0.0001
        type: adam
    training:
        batch_size: 32
        num_steps: 10000
        checkpoint_steps:
        - 500
        - 1000
        - 1500
    """.strip()

    if __name__ == "__main__":
        # Convert our YAML config into a nested dictionary.
        default_config = yaml.safe_load(default_yaml)

        # Override fields in the dictionary.
        overridden_config = tyro.cli(dict, default=default_config)

        # Print the overridden config.
        overridden_yaml = yaml.safe_dump(overridden_config)
        print(overridden_yaml)




.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./02_overriding_yaml.py --help</strong>
    <span style="font-weight: bold">usage</span>: 02_overriding_yaml.py [-h] [OPTIONS]
    
    <span style="font-weight: lighter">╭─</span><span style="font-weight: lighter"> options </span><span style="font-weight: lighter">──────────────────────────────────────────────</span><span style="font-weight: lighter">─╮</span>
    <span style="font-weight: lighter">│</span> -h, --help              <span style="font-weight: lighter">show this help message and exit</span> <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --exp-name <span style="font-weight: bold">STR</span>          <span style="color: #008080">(default: test)</span>                 <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">╰─────────────────────────────────────────────────────────╯</span>
    <span style="font-weight: lighter">╭─</span><span style="font-weight: lighter"> optimizer options </span><span style="font-weight: lighter">────────────────────────────────────</span><span style="font-weight: lighter">─╮</span>
    <span style="font-weight: lighter">│</span> --optimizer.learning-rate <span style="font-weight: bold">FLOAT</span>                         <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>                         <span style="color: #008080">(default: 0.0001)</span>               <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --optimizer.type <span style="font-weight: bold">STR</span>    <span style="color: #008080">(default: adam)</span>                 <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">╰─────────────────────────────────────────────────────────╯</span>
    <span style="font-weight: lighter">╭─</span><span style="font-weight: lighter"> training options </span><span style="font-weight: lighter">─────────────────────────────────────</span><span style="font-weight: lighter">─╮</span>
    <span style="font-weight: lighter">│</span> --training.batch-size <span style="font-weight: bold">INT</span>                               <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>                         <span style="color: #008080">(default: 32)</span>                   <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --training.num-steps <span style="font-weight: bold">INT</span>                                <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>                         <span style="color: #008080">(default: 10000)</span>                <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --training.checkpoint-steps <span style="font-weight: bold">[INT [INT ...]]</span>             <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>                         <span style="color: #008080">(default: 500 1000 1500)</span>        <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">╰─────────────────────────────────────────────────────────╯</span>
    </pre>



.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./02_overriding_yaml.py --training.checkpoint-steps 300 1000 9000</strong>
    exp_name: test
    optimizer:
      learning_rate: 0.0001
      type: adam
    training:
      batch_size: 32
      checkpoint_steps:
      - 300
      - 1000
      - 9000
      num_steps: 10000
    
    </pre>
.. _example-03_choosing_base_configs:

Choosing Base Configs
---------------------

One common pattern is to have a set of "base" configurations, which can be
selected from and then overridden.

This is often implemented with a set of configuration files (e.g., YAML files).
With :mod:`tyro`, we can instead define each base configuration as a separate
Python object.

After creating the base configurations, we can use the CLI to select one of
them and then override (existing) or fill in (missing) values.

The helper function used here, :func:`tyro.extras.overridable_config_cli()`, is
a lightweight wrapper over :func:`tyro.cli()` and its Union-based subcommand
syntax.


.. code-block:: python
    :linenos:

    # 03_choosing_base_configs.py
    from dataclasses import dataclass
    from typing import Callable, Literal

    from torch import nn

    import tyro

    @dataclass(frozen=True)
    class ExperimentConfig:
        # Dataset to run experiment on.
        dataset: Literal["mnist", "imagenet-50"]

        # Model size.
        num_layers: int
        units: int

        # Batch size.
        batch_size: int

        # Total number of training steps.
        train_steps: int

        # Random seed.
        seed: int

        # Not specifiable via the commandline.
        activation: Callable[[], nn.Module]

    # We could also define this library using separate YAML files (similar to
    # `config_path`/`config_name` in Hydra), but staying in Python enables seamless
    # type checking + IDE support.
    default_configs = {
        "small": (
            "Small experiment.",
            ExperimentConfig(
                dataset="mnist",
                batch_size=2048,
                num_layers=4,
                units=64,
                train_steps=30_000,
                seed=0,
                activation=nn.ReLU,
            ),
        ),
        "big": (
            "Big experiment.",
            ExperimentConfig(
                dataset="imagenet-50",
                batch_size=32,
                num_layers=8,
                units=256,
                train_steps=100_000,
                seed=0,
                activation=nn.GELU,
            ),
        ),
    }
    if __name__ == "__main__":
        config = tyro.extras.overridable_config_cli(default_configs)
        print(config)


Overall helptext:

.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./03_choosing_base_configs.py --help</strong>
    <span style="font-weight: bold">usage</span>: 03_choosing_base_configs.py [-h] <span style="font-weight: bold">{small,big}</span>
    
    <span style="font-weight: lighter">╭─</span><span style="font-weight: lighter"> options </span><span style="font-weight: lighter">─────────────────────────────────────────</span><span style="font-weight: lighter">─╮</span>
    <span style="font-weight: lighter">│</span> -h, --help         <span style="font-weight: lighter">show this help message and exit</span> <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">╰────────────────────────────────────────────────────╯</span>
    <span style="font-weight: lighter">╭─</span><span style="font-weight: lighter"> subcommands </span><span style="font-weight: lighter">─────────────────────────────────────</span><span style="font-weight: lighter">─╮</span>
    <span style="font-weight: lighter">│</span> {small,big}                                        <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>     small          <span style="font-weight: lighter">Small experiment.</span>               <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>     big            <span style="font-weight: lighter">Big experiment.</span>                 <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">╰────────────────────────────────────────────────────╯</span>
    </pre>

The "small" subcommand:

.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./03_choosing_base_configs.py small --help</strong>
    <span style="font-weight: bold">usage</span>: 03_choosing_base_configs.py small [-h] [SMALL OPTIONS]
    
    Small experiment.
    
    <span style="font-weight: lighter">╭─</span><span style="font-weight: lighter"> options </span><span style="font-weight: lighter">─────────────────────────────────────────────────────────────────</span><span style="font-weight: lighter">─╮</span>
    <span style="font-weight: lighter">│</span> -h, --help              <span style="font-weight: lighter">show this help message and exit</span>                    <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --dataset <span style="font-weight: bold">{mnist,imagenet-50}</span>                                              <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>                         <span style="font-weight: lighter">Dataset to run experiment on.</span> <span style="color: #008080">(default: mnist)</span>     <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --num-layers <span style="font-weight: bold">INT</span>        <span style="font-weight: lighter">Model size.</span> <span style="color: #008080">(default: 4)</span>                           <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --units <span style="font-weight: bold">INT</span>             <span style="font-weight: lighter">Model size.</span> <span style="color: #008080">(default: 64)</span>                          <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --batch-size <span style="font-weight: bold">INT</span>        <span style="font-weight: lighter">Batch size.</span> <span style="color: #008080">(default: 2048)</span>                        <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --train-steps <span style="font-weight: bold">INT</span>       <span style="font-weight: lighter">Total number of training steps.</span> <span style="color: #008080">(default: 30000)</span>   <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --seed <span style="font-weight: bold">INT</span>              <span style="font-weight: lighter">Random seed.</span> <span style="color: #008080">(default: 0)</span>                          <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --activation <span style="font-weight: bold; color: #800000">{fixed}</span>    <span style="font-weight: lighter">Not specifiable via the commandline.</span> <span style="color: #008080">(fixed to: </span>   <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>                         <span style="color: #008080">&lt;class 'torch.nn.modules.activation.ReLU'&gt;)</span>        <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">╰────────────────────────────────────────────────────────────────────────────╯</span>
    </pre>



.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./03_choosing_base_configs.py small --seed 94720</strong>
    ExperimentConfig(dataset='mnist', num_layers=4, units=64, batch_size=2048, train_steps=30000, seed=94720, activation=&lt;class 'torch.nn.modules.activation.ReLU'&gt;)
    </pre>

The "big" subcommand:

.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./03_choosing_base_configs.py big --help</strong>
    <span style="font-weight: bold">usage</span>: 03_choosing_base_configs.py big [-h] [BIG OPTIONS]
    
    Big experiment.
    
    <span style="font-weight: lighter">╭─</span><span style="font-weight: lighter"> options </span><span style="font-weight: lighter">─────────────────────────────────────────────────────────────────</span><span style="font-weight: lighter">─╮</span>
    <span style="font-weight: lighter">│</span> -h, --help              <span style="font-weight: lighter">show this help message and exit</span>                    <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --dataset <span style="font-weight: bold">{mnist,imagenet-50}</span>                                              <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>                         <span style="font-weight: lighter">Dataset to run experiment on.</span> <span style="color: #008080">(default: </span>           <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>                         <span style="color: #008080">imagenet-50)</span>                                       <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --num-layers <span style="font-weight: bold">INT</span>        <span style="font-weight: lighter">Model size.</span> <span style="color: #008080">(default: 8)</span>                           <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --units <span style="font-weight: bold">INT</span>             <span style="font-weight: lighter">Model size.</span> <span style="color: #008080">(default: 256)</span>                         <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --batch-size <span style="font-weight: bold">INT</span>        <span style="font-weight: lighter">Batch size.</span> <span style="color: #008080">(default: 32)</span>                          <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --train-steps <span style="font-weight: bold">INT</span>       <span style="font-weight: lighter">Total number of training steps.</span> <span style="color: #008080">(default: 100000)</span>  <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --seed <span style="font-weight: bold">INT</span>              <span style="font-weight: lighter">Random seed.</span> <span style="color: #008080">(default: 0)</span>                          <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span> --activation <span style="font-weight: bold; color: #800000">{fixed}</span>    <span style="font-weight: lighter">Not specifiable via the commandline.</span> <span style="color: #008080">(fixed to: </span>   <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">│</span>                         <span style="color: #008080">&lt;class 'torch.nn.modules.activation.GELU'&gt;)</span>        <span style="font-weight: lighter">│</span>
    <span style="font-weight: lighter">╰────────────────────────────────────────────────────────────────────────────╯</span>
    </pre>



.. raw:: html

    <pre class="highlight" style="padding: 1em; box-sizing: border-box; font-size: 0.85em; line-height: 1.2em;">
    <strong style="opacity: 0.7; padding-bottom: 0.5em; display: inline-block"><span style="user-select: none">$ </span>python ./03_choosing_base_configs.py big --seed 94720</strong>
    ExperimentConfig(dataset='imagenet-50', num_layers=8, units=256, batch_size=32, train_steps=100000, seed=94720, activation=&lt;class 'torch.nn.modules.activation.GELU'&gt;)
    </pre>