.. meta:: :description: Adding pydantic parsing to a Hydra app .. admonition:: tl;dr When wrapping your main function with `hydra_zen.zen`, pass in `hydra_zen.third_party.pydantic.pydantic_parser` to the `instantiation_wrapper` argument of `~hydra_zen.zen`. Additionally, for any `hydra_zen.instantiate` calls you make, pass this parser in as the `_target_wrapper_` argument. .. admonition:: Prerequisites Your must install `pydantic `_ in your Python environment in order to complete this How-To guide. .. _pydantic-parsing: ======================================================== Add Pydantic Type Checking and Parsing to Your Hydra App ======================================================== Hydra's runtime type checking is :ref:`limited to only a narrow subset of Python's typing features `. By contrast, `Pydantic `_ provides much more comprehensive type checking capabilities; additionally, it is capable of parsing CLI inputs into complex data structures (e.g., convert a string to a :py:class:`pathlib.Path`). In this how-to guide, we will **add pydantic parsing to all config-instantiation sites in our Hydra-app**. Consider the following simple hydra-zen app: .. code-block:: python :caption: Contents of `my_app.py` from hydra_zen import store from hydra_zen.third_party.pydantic import pydantic_parser from typing import Literal from pydantic import PositiveInt from dataclasses import dataclass @dataclass class Character: age: PositiveInt = 22 name: str = "Bobby" def main( character: Character, gear: tuple[str, ...] = (), mode: Literal["easy", "hard"] = "easy", ): print(f"{character=!r} {gear=!r} {mode=!r}") if __name__ == "__main__": from hydra_zen import zen store(main, hydra_defaults=["_self_", {"character": "base"}]) store(Character, group="character", name="base") store.add_to_hydra_store() zen( main, # This is the key ingredient instantiation_wrapper=pydantic_parser, ).hydra_main( config_name="main", config_path=None, version_base="1.3", ) By specifying `instantiation_wrapper=pydantic_parser` in our `hydra_zen.zen` call, we insure that all config-instantiation sites in our Hydra-app will use pydantic parsing. Because of this, we will benefit from the following features: 1. Annotating `mode` with `Literal` will restrict the permitted values for this parameter. 2. We can configure `gear` with a list of strings at the CLI and - because of the `tuple[str, ...]` annotation - it will be coerced into a tuple of strings before being passed to `main`. 3. We can use a `pydantic.PositiveInt` annotation for the `character.age` nested field; this will ensure that the age is a valid value. Let's check that `mode` is restricted to the values `easy` and `hard`: .. code-block:: console :caption: Running the app with an invalid value for `mode` $ python my_app.py mode='medium' Traceback (most recent call last): ... pydantic_core._pydantic_core.ValidationError: 1 validation error for main mode Input should be 'easy' or 'hard' Next, let's see that `gear` can be passed a list, which will be coerced into a tuple: .. code-block:: console :caption: Running the app with a list of strings for `gear` $ python my_app.py gear='[sword,shield]' character=Character(age=22, name='Bobby') gear=('sword', 'shield') mode='easy' Finally, let's see that `character.age` is correctly parsed as a `PositiveInt`: .. code-block:: console :caption: Running the app with an invalid value for `character.age` $ python my_app.py character.age=-1 Traceback (most recent call last): ... Error in call to target '__main__.Character': 1 validation error for Character age Input should be greater than 0 In this way, we can use Pydantic to add powerful type checking and parsing to our Hydra apps. If your app includes manual calls to `hydra_zen.instantiate`, you can also pass in the `pydantic_parser` as the `_target_wrapper_` argument to ensure that these config-instantiation calls also use Pydantic parsing. .. note:: Keep in mind that this pydantic parsing layer only occurs when we instantiate configs that have `_target_` fields, and that it uses the annotations of the `_target_` objects.