python-attrs / python-attrs/cattrs

Better Union resolution

Open
#423 3 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Python
Stars
1.1k
Forks
159
Avg merge
12h 21m
Merged PRs (30d)
6

Description

  • cattrs version: 23.1.2
  • Python version: 3.10.6
  • Operating System: Win 10
Description

Right now I'm looking to migrate from dataclass + dacite to attrs + cattrs, but there's a feature in dacite that I miss in cattrs: consequtive resolution of Unions. What dacite does is that it takes each type in the Union and tries to match it to the data. If nothing is matched - the error is raised. This behavior seemed pretty intuitive for me.
However, if cattrs meets even a really basic Union like Union[str, int, float] and data like '123' it will pretend it doesn't know how to deal with this one, even if the resolution is really straightforward. Yes, you can probably write a hook for that, but manually describing each Union is really undesirable and error-prone. Maybe hook factory solves this, but I'm still figuring this stuff out, and my idea is that this should not be as complicated as it is right now.

What I Did
from attrs import define
from cattrs import structure
from enum import Enum
from typing import Union

c = structure('123', Union[str, int, float])
# Expected behavior: '123'
# Actual behavior: cattrs.errors.StructureHandlerNotFoundError: Unsupported type: typing.Union[str, int, float]. Register a structure hook for it.

@define
class C:
    foo: str

c = structure({'foo': 'bar'}, Union[C, dict])

# Expected behavior: C(foo='bar')
# Actual behavior: cattrs.errors.StructureHandlerNotFoundError: Unsupported type: typing.Union[__main__.C, dict]. Register a structure hook for it.


class Foo(Enum):
    BAR = 'Bar'

c = structure('Bar', Union[Foo, str])

# Expected behavior: Foo.BAR
# Actual behavior: cattrs.errors.StructureHandlerNotFoundError: Unsupported type: typing.Union[__main__.Foo, str]. Register a structure hook for it.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with cattrs.structure and reproduce the three Union examples from the issue using the stated Python and cattrs versions. Compare the results with the expected consecutive resolution for str/int/float, attrs class/dict, and Enum/str inputs. Done means these examples resolve as described and unsupported Union inputs still raise an appropriate error.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.