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).
|
__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 do setattr(cls, key, value). However, here, key is __dict__, so python thinks we actually want to override the __dict__ attribute of cls, and not a __dict__ field of the __dict__.
- However, including
__dict__ in the type_kwargs only if it is a property 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: {}
After #253 (comment), I started examinating these lines. I think the original use-case was to handle classes like
namedtupleoverloading__dict__.(even though the test suite passes for all python versions if simply drop the
__dict__item out ofclsdict).cloudpickle/cloudpickle/cloudpickle.py
Lines 633 to 635 in 167e163
In more detail:
__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,keyis__dict__, so python thinks we actually want to override the__dict__attribute ofcls, and not a__dict__field of the__dict__.__dict__in thetype_kwargsonly if it is apropertyobject is kind of arbitrary (probably related to namedtuples). Take this example for example, where we loose the__dict__attribute: