Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ValidationError for Unions in nested Dicts using merge with structured config #1166

Open
4 tasks done
denialofsandwich opened this issue Mar 13, 2024 · 2 comments
Open
4 tasks done
Labels
bug Something isn't working structured config

Comments

@denialofsandwich
Copy link

denialofsandwich commented Mar 13, 2024

Describe the bug
The validation of unions, which are nested in a dict seems to be broken and throws a ValidationError during a merge, even if the types should be correct.

To Reproduce
The last line is throwing the ValidationError:

from dataclasses import dataclass, field
from typing import Union

from omegaconf import OmegaConf


@dataclass
# Default is z.a.b = 1
class HasUnion:
    z: dict[str, dict[str, Union[str, int]]] = field(
        default_factory=lambda: {"a": {"b": 1}}
    )

# z.a.b = 1 (This works)
# z.c.b = 1 (This doesn't work)
cfg = OmegaConf.merge(  # <-- Oh, no!
    OmegaConf.structured(HasUnion),
    OmegaConf.create("""
z:
    c:
        b: 1
""")
)

This is the exception thwown at the last line:

ValidationError: Value 1 (int) is incompatible with type hint 'typing.Union[int, str]'
    full_key: z.c
    reference_type=Dict[str, Dict[str, Union[int, str]]]
    object_type=dict

Expected behavior
I expect z.c.b = 1 not to fail, since 1 is a valid type of Union[str, int] and if the Union is not nested inside a dict.

Additional context

  • OmegaConf version: 2.3.0
  • Python version: 3.11.6
  • Operating system: Kubuntu 23.10
  • The example above is enough to replicate the error
@denialofsandwich denialofsandwich added the bug Something isn't working label Mar 13, 2024
@denialofsandwich
Copy link
Author

denialofsandwich commented Mar 14, 2024

I found another few examples. Here with a dict[str, list[union]] type:

from dataclasses import dataclass, field
from typing import Union

from omegaconf import OmegaConf


@dataclass
# Default is z.a.b = 1
class HasUnion:
    z: dict[str, list[Union[str, int]]] = field(
        default_factory=lambda: {"a": [1,2]}
    )

# z.a = [1] (This works)
# z.c = [1] (This doesn't work)
cfg = OmegaConf.merge(
    OmegaConf.structured(HasUnion),
    OmegaConf.create("""
z:
    c:
        - 1
""")
)

And here with a dict[str, list[dataclass]] type. The validation doesn't work, if the parent key wasn't part of the default value before:

from dataclasses import dataclass, field

from omegaconf import OmegaConf


@dataclass
class Foo:
    exist1: int
    exist2: str

@dataclass
class BaseStructure:
    z: dict[str, list[Foo]] = field(
        default_factory=lambda: {"a": [Foo(1, "lol")]}
    )

cfg = OmegaConf.merge(
    OmegaConf.structured(BaseStructure),
    OmegaConf.create("""
z:
    c:
        - exist1: 1
          dontexist2: lol
""")
)

EDIT: I accidentally clicked on close, sry.

@Jasha10
Copy link
Collaborator

Jasha10 commented Mar 14, 2024

Thanks for the bug report, @denialofsandwich.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working structured config
Projects
None yet
Development

No branches or pull requests

2 participants