omegaconf icon indicating copy to clipboard operation
omegaconf copied to clipboard

`get_attr_data` doesn't handle default factory correctly

Open ssnl opened this issue 3 years ago • 3 comments

If we merge a MISSING field, with an attrs class structured config that uses default factory (e.g., for specifying defaults list in hydra), this expand call https://github.com/omry/omegaconf/blob/6a4fd518d53c7b9996b720458352b1e6a643e769/omegaconf/basecontainer.py#L327-L342 will call node._set_value(attrs_class), which calls get_attr_data(attrs_class). https://github.com/omry/omegaconf/blob/6a4fd518d53c7b9996b720458352b1e6a643e769/omegaconf/_utils.py#L313-L334 and since it is given a class, it will use attrs.Attribute's attribute.default value as the values to set attributes. This normally works, but however, if the attribute uses default factory, the attribute.default is an attrs.Factory object! Then OmegaConf errors out.

To Reproduce

image [skipping long stack frames] image

ssnl avatar May 25 '22 18:05 ssnl

Thanks for the bug report!

Jasha10 avatar May 25 '22 21:05 Jasha10

In a sense this is due to that OmegaConf infers types from values rather than type annotations. I wonder if there can be a way to use type annotations instead (which would also address the structure configs inheritance issue described in https://github.com/facebookresearch/hydra/issues/2227 )

ssnl avatar May 27 '22 15:05 ssnl

I ran into this bug as well just now. However, I have found it does work correctly with the stdlib dataclasses. This can serve as a possible workaround for others who run into this, and may aid in tracking down the source of the problem.

For reference, here's a minimalistic dataclasses example that works correctly for which the equivalent attrs version throws the exception described in the original report:

from dataclasses import dataclass, field

@dataclass
class Config:
  a_list_of_strings: list[str] = field(default_factory=list)

zoni avatar Jun 12 '22 09:06 zoni