python-attrs / python-attrs/cattrs

attrs 23.1.0 breaks string annotated generics

Open
#427 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

blocked-upstream bug
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.7
  • Operating System: Ubuntu
Description

When working with generic attrs types with cattrs, I updated my version of attrs and it caused failures. Having looked at the changelog in attrs:

https://www.attrs.org/en/stable/changelog.html#id1

This seems likely it was caused by:

attrs.has() and attrs.fields() now handle generic classes correctly. #1079

Changing the behaviour of: (converters.py 976-977)

        attribs = fields(get_origin(cl) or cl if is_generic(cl) else cl)
        if attrs_has(cl) and any(isinstance(a.type, str) for a in attribs):

in which case it probably can't be described as an attrs bug. (But I don't have high confidence in that).

(I confirmed that

            resolve_types(cl)

failed on both versions of attrs, so the difference is somewhere in the if statement)

What I Did
from __future__ import annotations
from typing import TypeVar, Generic

import attrs
import cattrs

T = TypeVar('T')
@attrs.frozen
class A(Generic[T]):
    a: T

converter = cattrs.Converter()
converter.gen_structure_attrs_fromdict(A[int]) # This fails with attrs 23.1.0


#And hence the lower calls won't work

cattrs.structure({'a': 1}, A[int])  # Succeeds with attrs 22.2.0
cattrs.structure({'a': 'one'}, A[int])  # Fails as expected with attrs 22.2.0

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 in converters.py around lines 976-977 and compare the attrs 22.2.0 and 23.1.0 behavior for generic classes with string annotations. Run the supplied A[int] reproduction; done means structuring {'a': 1} succeeds while {'a': 'one'} still fails as expected.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.