omry / omegaconf

Flexible Python configuration system. The last one you will ever need.
BSD 3-Clause "New" or "Revised" License
1.91k stars 104 forks source link

Modifying interpolated dictionary does not stick #1079

Closed jzazo closed 1 year ago

jzazo commented 1 year ago

Describe the bug The following code does not allow modification of a nested interpolated variable:

from dataclasses import dataclass
from omegaconf import OmegaConf

OmegaConf.register_new_resolver("expand", lambda: OmegaConf.create(Expanded()))

@dataclass
class Expanded:
    foo: int = 1
    boo: str = "bar"

@dataclass
class Config:
    bee: Expanded = "${expand:}"

cfg = OmegaConf.structured(Config)
print(cfg.bee.foo)  # prints 1
OmegaConf.resolve(cfg)
cfg.bee.foo = 2  # changes value to 2?
print(cfg.bee.foo)  # should print 2 but prints 1

Expected behavior I would expect that modifying a nested variable even if it comes from an interpolated variable persists.

Additional context

omry commented 1 year ago

Resolvers are running every time you are accessing them. There is mechanism to cache the result, which might give you the behavior you are after.

Try something like:

OmegaConf.register_new_resolver("expand", lambda: OmegaConf.create(Expanded()), use_cache=True)

In any case, what you are describing is not a bug.

jzazo commented 1 year ago

Thanks for the suggested solution, but shouldn't OmegaConf.resolve resolve in-place and then its result be modifyable?

omry commented 1 year ago

It should and looks like it does. This runs smoothly. Double check your example.

from dataclasses import dataclass
from omegaconf import OmegaConf

OmegaConf.register_new_resolver("expand", lambda: OmegaConf.create(Expanded()))

@dataclass
class Expanded:
    foo: int = 1
    boo: str = "bar"

@dataclass
class Config:
    bee: Expanded = "${expand:}"

cfg = OmegaConf.structured(Config)
assert cfg.bee.foo == 1
OmegaConf.resolve(cfg)
cfg.bee.foo = 2
assert cfg.bee.foo == 2
jzazo commented 1 year ago

Ok, thank you, it works. I think I may have added the resolve call later and probably didn't save the file or something like that when I ran it.