cloudpipe / cloudpipe/cloudpickle
cloudpickle drops __dict__ attribute of classes.
- Dominant language
- Python
- Stars
- 1.9k
- Forks
- 195
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 1
Description
After https://github.com/cloudpipe/cloudpickle/pull/253#discussion_r291531183, 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`).
https://github.com/cloudpipe/cloudpickle/blob/167e1637141d4f7bddd16c8bb459a6f01ef1cc56/cloudpickle/cloudpickle.py#L633-L635
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:
```python
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: {}
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.