Skip to content

cloudpickle drops __dict__ attribute of classes. #282

@pierreglaser

Description

@pierreglaser

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: {}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions