Skip to content

With strict_unions_match, KeyError is raised instead of UnionMatchError #234

@object-Object

Description

@object-Object

Describe the bug
If strict_unions_match=True is present and a union type containing at least one non-primitive type fails to match, the following exception is raised:

Traceback (most recent call last):
  File "[redacted]\foo.py", line 57, in <module>
    from_dict(Class, {"value": True}, Config(strict_unions_match=True))
  File "[redacted]\venv\Lib\site-packages\dacite\core.py", line 69, in from_dict
    value = _build_value(type_=field.type, data=transformed_value, config=config)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "[redacted]\venv\Lib\site-packages\dacite\core.py", line 94, in _build_value
    return _build_value_for_union(union=type_, data=data, config=config)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "[redacted]\venv\Lib\site-packages\dacite\core.py", line 127, in _build_value_for_union     
    return union_matches.popitem()[1]
           ^^^^^^^^^^^^^^^^^^^^^^^
KeyError: 'popitem(): dictionary is empty'

To Reproduce

@dataclass
class Class:
    value: list | dict

from_dict(Class, {"value": True}, Config(strict_unions_match=True))

Expected behavior
UnionMatchError should be raised, like what happens if strict_unions_match is removed from the Config.

Environment

  • Python version: 3.11.0
  • dacite version: 1.7.0

Additional context
Here's the responsible code. The issue seems to be that there are two different cases when this code is reached: when strict_unions_match is enabled, and when none of the union types were matched. It could probably be fixed by adding something like and union_matches to line 129.

dacite/dacite/core.py

Lines 129 to 135 in 10a9ec4

if config.strict_unions_match:
if len(union_matches) > 1:
raise StrictUnionMatchError(union_matches)
return union_matches.popitem()[1]
if not config.check_types:
return data
raise UnionMatchError(field_type=union, value=data)

Also, I'm on 1.7.0 instead of 1.8.1 because of #217. I haven't tested this on 1.8.1, but from looking at the code I'm pretty sure the issue should still be present.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions