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

attr.evolve no longer supports setting an attr object as attribute #804

Closed
progval opened this issue May 6, 2021 · 3 comments · Fixed by #806
Closed

attr.evolve no longer supports setting an attr object as attribute #804

progval opened this issue May 6, 2021 · 3 comments · Fixed by #806

Comments

@progval
Copy link

progval commented May 6, 2021

Hi,

I don't know if this is an intentional side-effect of #759, but attr.evolve no longer works in the non-recursive recursive case if the argument is an attr class.

Here is a snippet to reproduce it:

import attr

@attr.s
class Cls1:
    param1 = attr.ib()


@attr.s
class Cls2:
    param2 = attr.ib()


obj2a = Cls2(param2="a")
obj2b = Cls2(param2="b")

obj1a = Cls1(param1=obj2a)
obj1b = attr.evolve(obj1a, param1=obj2b)

print(obj1b)

Before fe6eb31, it printed this: Cls1(param1=Cls2(param2='b'))

But after this commit, it raises this error:

Traceback (most recent call last):
  File "test.py", line 17, in <module>
    obj1b = attr.evolve(obj1a, param1=obj2b)
  File "/home/dev/.local/lib/python3.7/site-packages/attrs-21.2.0.dev0-py3.7.egg/attr/_funcs.py", line 347, in evolve
    changes[init_name] = evolve(value, **changes[init_name])
TypeError: evolve() argument after ** must be a mapping, not Cls2

Thanks!

@progval progval changed the title attr.evolve no longer supports setting an attr class as attribute attr.evolve no longer supports setting an attr object as attribute May 6, 2021
@staaam
Copy link

staaam commented May 6, 2021

same here. Issue is in attr._funcs.evolve at:

    for a in attrs:
        ...
        elif has(value):
            # Evolve nested attrs classes
            changes[init_name] = evolve(value, **changes[init_name])

value - is old value (param1 from example above)
changes[init_name] - is new value (obj2b from above)
but for recursive evolve it should be dict
probably the best way to make it backward compatible will be to check
elif has(value) and isinstance(changes[init_name], Mapping):

@hynek
Copy link
Member

hynek commented May 6, 2021

Yeah, we'll have to revert #759 and push out 21.2.

I'm gonna wait a bit with the release to see if there's other breakages that should be fixed.

swhmirror pushed a commit to SoftwareHeritage/swh-model that referenced this issue May 6, 2021
There is a regression that breaks attr.evolve() when updating attributes
that contain an attr class; which we use (eg. for Person or TimestampWithTimezone).

v21.2.0 is expected to fix the issue, but won't be released immediately:
python-attrs/attrs#804 (comment)
@hynek hynek closed this as completed in #806 May 6, 2021
@hynek
Copy link
Member

hynek commented May 7, 2021

21.2 with the fix is on PyPI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants