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

With strict_unions_match, KeyError is raised instead of UnionMatchError #234

Open
object-Object opened this issue Jun 16, 2023 · 3 comments
Labels
bug Something isn't working

Comments

@object-Object
Copy link

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.

@object-Object object-Object added the bug Something isn't working label Jun 16, 2023
@object-Object
Copy link
Author

Ah, #233 should fix this I think. Missed that.

@kkg4theweb
Copy link

Can someone review #233 and merge it if it looks ok ? It is a simple fix.

@object-Object
Copy link
Author

object-Object commented Apr 2, 2024

I will note that I ended up switching from Dacite to Pydantic for my use case for this and other reasons, and I haven't encountered any real issues. It also happens to be far more actively maintained.

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

No branches or pull requests

2 participants