You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In the same manner as attr.asdict(..., recursive=True) exists, I have a use case for a similar option to attr.evolve(). I want all attr instances evolved, but with no need to deepcopy any non-attr attributes. I ended up implementing the code below. Could this be a consideration for addition into python-attrs?
defevolve_recursive(inst, **changes):
""" Recursive attr.evolve() method, where any attr-based attributes will be evolved too. """cls=inst.__class__attrs=attr.fields(cls)
forainattrs:
ifnota.init:
continueattr_name=a.name# To deal with private attributes.init_name=attr_nameifattr_name[0] !="_"elseattr_name[1:]
ifinit_namenotinchanges:
value=getattr(inst, attr_name)
# New codeifattr.has(value.__class__):
value=evolve_recursive(value)
changes[init_name] =valuereturncls(**changes)
I’ve had a similar issue in typed settings when I want to updated nested settings and fixed it by serializing instances to dicts, calling a _set_path function and later converting the dicts back to attrs instances (which only works when using (auto) converters, though).
I guess, it’ll be mostly backward compatible. *mostly, because handling of nested dicts will be different if they map to attributes with attrs classes. ;-)
But the above changes did not break any of the existing tests.
I’ll do a PR once I figure out how to proberly use hypothesis and nested classes for the tests.
Activity
hynek commentedon Oct 19, 2020
Sorry for the late answer. Would you mind showing/elaborating some use cases for this?
sscherfke commentedon Oct 19, 2020
I’ve had a similar issue in typed settings when I want to updated nested settings and fixed it by serializing instances to dicts, calling a _set_path function and later converting the dicts back to attrs instances (which only works when using (auto) converters, though).
hynek commentedon Oct 30, 2020
We have a volunteer! ✨
sscherfke commentedon Oct 30, 2020
Wat? 👀
sscherfke commentedon Dec 13, 2020
attr.evolve()can be adjusted relatively easy to work recursively:I’m not sure whether this is a backwards incompatible change or rather a bug fix that prevents nested classes from being replaced by a dict. 🤷♂️
sscherfke commentedon Dec 19, 2020
@hynek What are your requirements regarding the public API?
Do you prefer a new function or would you rather update the behavior of the existing one as in the diff above?
hynek commentedon Dec 21, 2020
I think if you can do it backward compatible, there's no need for a new function?
sscherfke commentedon Dec 21, 2020
I guess, it’ll be mostly backward compatible. *mostly, because handling of nested dicts will be different if they map to attributes with attrs classes. ;-)
But the above changes did not break any of the existing tests.
I’ll do a PR once I figure out how to proberly use hypothesis and nested classes for the tests.
Recursively evolve nested attrs classes
Recursively evolve nested attrs classes
Recursively evolve nested attrs classes
Recursively evolve nested attrs classes (#759)
hynek commentedon May 6, 2021
Unfortunately we had to revert the changes due to #804. I think we'll have to write a new function to make stuff unequivocal.
Sorry everyone! :(
Allow evolve() to recursively evolve attrs classes
Allow evolve() to recursively evolve attrs classes
Allow evolve() to recursively evolve attrs classes
Allow evolve() to recursively evolve attrs classes