Search code examples
pythonpython-attrsfb-hydra

Attribute Converter in attr.s-based hydra Structured Configs


Is it possible to use converters in attr.s-based hydra-structured configs.

I tried it with this minimal example:

import hydra
from hydra.core.config_store import ConfigStore
import attr

@attr.s
class Times10Config:
    num: int = attr.ib(default=42, converter=lambda x: x*10)

cs = ConfigStore.instance()
# Registering the Config class with the name 'config'.
cs.store(name="config", node=Times10Config)

@hydra.main(version_base=None, config_name="config")
def my_app(cfg: Times10Config) -> None:
    print(cfg)

if __name__ == "__main__":
    my_app()

But running

python -m my_app num=1

results in the output:

{'num': 1}

While directly instantiating a Times10Config in a python interpreter does result in the expected behaviour:

In [5]: Times10Config(num=1)
Out[5]: Times10Config(num=10)

Solution

  • OmegaConf does not instantiate the underlying objects - it's just using them a descriptors for runtime validation purposes. Any logic defined in the dataclass/attr class is not running normally.

    You can convert your config structure to native objects using OmegaConf.to_object(). Be sure to read the docs for OmegaConf.to_container() as well.

    In the context of an Hydra application, you could convert your config at the beginning of the run:

    @hydra.main(version_base=None, config_name="config")
    def my_app(cfg: Times10Config) -> None:
        cfg = OmegaConf.to_object(cfg)
        print(cfg)