You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In 0.3.7, attributes in the __dict__ of a class are now deleted by dill if they have the same name and value as an attribute of a superclass. For example:
importdillclassFoo:
x=1classBar(Foo):
x=1# identical value as superclassassert'x'inBar.__dict__# passesdata=dill.dumps(Bar)
Bar2=dill.loads(data)
assert'x'inBar2.__dict__# fails with dill 0.3.7 (works with 0.3.6)
This behavior is caused by the _get_typedict_type function added in #577. Based on its docstring it seems the idea was to exclude inherited methods, but the code actually excludes any attribute whose value is identical to the inherited value. This is not safe (arguably even in the case of methods) because as the code above demonstrates, it changes the behavior of code which inspects the __dict__ directly. Obviously the above code is a toy example, but we have real code which does this (basically to set a non-inherited flag on classes) and which was broken by dill 0.3.7.
In case it matters, I'm using Python 3.11.1 on macOS; we've also seen the problem under Python 3.10.12 on Ubuntu.
The text was updated successfully, but these errors were encountered:
Another way this issue can appear is that the __module__ of a subclass can be restored incorrectly when the class is pickled by value:
File test2.py:
classFoo:
passclassBar(Foo):
passBarAlias=BardelBar# to prevent pickling by reference
File test.py:
importdillfromtest2importBarAliasasBarprint(Bar.__module__) # prints `test2`data=dill.dumps(Bar)
Bar2=dill.loads(data)
print(Bar2.__module__) # prints `dill._dill` under 0.3.7
The underlying problem is the same: the __module__ attribute of Bar doesn't get saved when pickling its __dict__, because the value of the attribute is identical to the value inherited from Foo. Then __module__ isn't included in the dict when creating the new class during unpickling, and so it gets the usual value based on where the class was made (inside dill._dill).
In 0.3.7, attributes in the
__dict__
of a class are now deleted bydill
if they have the same name and value as an attribute of a superclass. For example:This behavior is caused by the
_get_typedict_type
function added in #577. Based on its docstring it seems the idea was to exclude inherited methods, but the code actually excludes any attribute whose value is identical to the inherited value. This is not safe (arguably even in the case of methods) because as the code above demonstrates, it changes the behavior of code which inspects the__dict__
directly. Obviously the above code is a toy example, but we have real code which does this (basically to set a non-inherited flag on classes) and which was broken bydill
0.3.7.In case it matters, I'm using Python 3.11.1 on macOS; we've also seen the problem under Python 3.10.12 on Ubuntu.
The text was updated successfully, but these errors were encountered: