Allow assigning variable interpolation to structured config during merge
Is your feature request related to a problem? Please describe. When merging a DictConfig containing variable interpolation with a compatible structured config, the following error is thrown:
Merge error: str is not a subclass of FooCfg. value: ${elsewhere}
full_key:
object_type=FooCfg
Example code:
@dataclass
class FooCfg:
a: int = 1
b: int = 2
@dataclass
class AppCfg:
foo: FooCfg = field(default_factory=FooCfg)
bar: bool = False
# override.yaml
# this config file will be merged with the default
foo: ${elsewhere}
elsewhere:
a: 3
b: 4
schema = OmegaConf.create(AppCfg)
overrides = OmegaConf.load("override.yaml")
# error is thrown below
cfg = OmegaConf.unsafe_merge(schema, overrides)
Describe alternatives you've considered Currently, my workaround is to convert the Structured Config back to normal to disable runtime validation:
schema = OmegaConf.to_container(schema, structured_config_mode=SCMode.DICT)
On a side note, is there a function or flag to explicitly disable runtime validation?
Describe the solution you'd like
OmegaConf should ignore the incompatibility between str and FooCfg when merging if the value appears to be a variable interpolation. Optionally, it can attempt to check if the node referred to by the interpolation is compatible with FooCfg.
Thanks @Interpause, I can reproduce the error you've described.
A workaround is to call OmegaConf.resolve before merging:
from dataclasses import dataclass, field
from typing import Any
from omegaconf import OmegaConf
@dataclass
class FooCfg:
a: int = 1
b: int = 2
@dataclass
class AppCfg:
elsewhere: Any
foo: FooCfg = field(default_factory=FooCfg)
bar: bool = False
override_yaml = """
# override.yaml
# this config file will be merged with the default
foo: ${elsewhere}
elsewhere:
a: 3
b: 4
"""
schema = OmegaConf.create(AppCfg)
overrides = OmegaConf.create(override_yaml)
OmegaConf.resolve(overrides)
cfg = OmegaConf.unsafe_merge(schema, overrides)
print(OmegaConf.to_yaml(cfg))
$ python tmp.py
elsewhere:
a: 3
b: 4
foo:
a: 3
b: 4
bar: false
Note that for the merge to succeed it's also necessary to add an elsewhere field to the AppCfg dataclass.
What I did was to turn off the struct flag for more flexibility while still enforcing validation on the values used. This is to allow me to "extract" deeply nested options using interpolation. That's my favorite feature of omegaconf. Actually, I would prefer to use Hydra's config groups but my application has to be bundled, and PyInstaller is having problems with it.