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

`getattr` cannot be used on `DictConfig` #1098

Closed Zacharias030 closed 9 months ago

Zacharias030 commented 1 year ago

Describe the bug

if getattr(config, "eval_output_dir", None) is None:
    ...

does not return None if config: DictConfig doesn't have the attribute, because it raises an omegaconf.errors.ConfigAttributeError.

File "/usr/local/lib/python3.10/dist-packages/omegaconf/dictconfig.py", line 355, in __getattr__
    self._format_and_raise(
  File "/usr/local/lib/python3.10/dist-packages/omegaconf/base.py", line 231, in _format_and_raise
    format_and_raise(
  File "/usr/local/lib/python3.10/dist-packages/omegaconf/_utils.py", line 899, in format_and_raise
    _raise(ex, cause)
  File "/usr/local/lib/python3.10/dist-packages/omegaconf/_utils.py", line 797, in _raise
    raise ex.with_traceback(sys.exc_info()[2])  # set env var OC_CAUSE=1 for full trace
  File "/usr/local/lib/python3.10/dist-packages/omegaconf/dictconfig.py", line 351, in __getattr__
    return self._get_impl(
  File "/usr/local/lib/python3.10/dist-packages/omegaconf/dictconfig.py", line 442, in _get_impl
    node = self._get_child(
  File "/usr/local/lib/python3.10/dist-packages/omegaconf/basecontainer.py", line 73, in _get_child
    child = self._get_node(
  File "/usr/local/lib/python3.10/dist-packages/omegaconf/dictconfig.py", line 480, in _get_node
    raise ConfigKeyError(f"Missing key {key!s}")
omegaconf.errors.ConfigAttributeError: Missing key eval_output_dir
    full_key: eval_output_dir
    object_type=dict

To Reproduce Please provide a minimal repro. This can include a small Python file, and potentially a few small config files. If you have more than one file you can attach a zip file with everything to the issue.

Expected behavior I understand that custom errors are useful sometimes, but I expect that attributes behave like attributes and that getattr(...) returns without raising.

Jasha10 commented 1 year ago

Maybe changing the omegaconf.errors.ConfigAttributeError to inherit from python's built in AttributeError would solve this. @Zacharias030, can you confirm this?

omry commented 1 year ago

It's already extending AttribuiteError.

class ConfigAttributeError(OmegaConfBaseException, AttributeError):
omry commented 1 year ago

Please provide a minimum runnable repro. This runs success fly for me:

from omegaconf import OmegaConf

cfg = OmegaConf.create()

if getattr(cfg , "aaa", None) is None:
    print("Missing field aaa")

OmegaConf.set_struct(cfg, True)
if getattr(cfg , "aaa", None) is None:
    print("Missing field aaa")

And outputs

Missing field aaa
Missing field aaa