-
Notifications
You must be signed in to change notification settings - Fork 180
Open
Description
After #253 (comment), I started examinating these lines. I think the original use-case was to handle classes like namedtuple
overloading __dict__
.
(even though the test suite passes for all python versions if simply drop the __dict__
item out of clsdict
).
cloudpickle/cloudpickle/cloudpickle.py
Lines 633 to 635 in 167e163
__dict__ = clsdict.pop('__dict__', None) | |
if isinstance(__dict__, property): | |
type_kwargs['__dict__'] = __dict__ |
In more detail:
- The first one line is necessary because updating a
__dict__
field in the__dict__
of a class is simply not possible. Indeed,__dict__
attributes are proxies objects and do not support direct item assigment like__dict__[k] = v
. Instead, the canonical way to update a class__dict__
is to dosetattr(cls, key, value)
. However, here,key
is__dict__
, so python thinks we actually want to override the__dict__
attribute ofcls
, and not a__dict__
field of the__dict__
. - However, including
__dict__
in thetype_kwargs
only if it is aproperty
object is kind of arbitrary (probably related to namedtuples). Take this example for example, where we loose the__dict__
attribute:
In [1]: import gc
...: import cloudpickle
...:
...: class A:
...: __dict__ = {'some_attribute':1}
...: a = A()
...: print(f'calling __dict__ on the original A instance: {a.__dict__}')
...:
...: s = cloudpickle.dumps(a)
...: del A
...: del a
...: gc.collect()
...: depickled_a = cloudpickle.loads(s)
...: print(f'calling __dict__ on the depickled A instance: {depickled_a.__dict__}')
calling __dict__ on the original A instance: {'some_attribute': 1}
calling __dict__ on the depickled A instance: {}
Metadata
Metadata
Assignees
Labels
No labels