attrs icon indicating copy to clipboard operation
attrs copied to clipboard

`asdict` does not work with `field(init=False)`

Open lmmentel opened this issue 3 years ago • 3 comments

I'm not sure if this is intended behavior or not but it definitely confused me, so maybe someone can help me understand it better.

Here's a simple example

from attrs import define, asdict

@define
class Coords:
    x = attr.ib(type=int)
    y = attr.ib(type=int, init=False)

asdict(Coords(x=1))

and it results with and attribute error

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [67], in <cell line: 6>()
      3     x = attr.ib(type=int)
      4     y = attr.ib(type=int, init=False)
----> 6 asdict(Coords(x=1))

File ~/anaconda3/lib/python3.9/site-packages/attr/_next_gen.py:198, in asdict(inst, recurse, filter, value_serializer)
    191 def asdict(inst, *, recurse=True, filter=None, value_serializer=None):
    192     """
    193     Same as `attr.asdict`, except that collections types are always retained
    194     and dict is always used as *dict_factory*.
    195 
    196     .. versionadded:: 21.3.0
    197     """
--> 198     return _asdict(
    199         inst=inst,
    200         recurse=recurse,
    201         filter=filter,
    202         value_serializer=value_serializer,
    203         retain_collection_types=True,
    204     )

File ~/anaconda3/lib/python3.9/site-packages/attr/_funcs.py:57, in asdict(inst, recurse, filter, dict_factory, retain_collection_types, value_serializer)
     55 rv = dict_factory()
     56 for a in attrs:
---> 57     v = getattr(inst, a.name)
     58     if filter is not None and not filter(a, v):
     59         continue

AttributeError: y

however I would expect to a dict with {"x": 1}. I appreciate some input on this.

lmmentel avatar Jul 16 '22 15:07 lmmentel

As far as attrs is concerned, the y attribute does exist – it's just not our job to initialize it.

hynek avatar Aug 03 '22 11:08 hynek

Thanks @hynek, would it be interesting to update asdict to return only initialized parameters by default or add a flag to expose an option to get all or init parameters only?

I'm thinking about sth like

addict(instance, init_only=True)

I'm happy to put in a PR if you're open to that.

lmmentel avatar Aug 03 '22 20:08 lmmentel

The real question here is why would you declare a field that doesn't exist? This is a very special case and goes into serialization-framework territory.

hynek avatar Aug 04 '22 03:08 hynek