New submission from Michael Foord <mich...@voidspace.org.uk>:

Pickling uses __class__ instead of type(obj) to determine the type to pickle. 
This means that objects which pretend to be other objects (like proxy and mock 
objects) can't be pickled correctly:

>>> class Foo(object):
...  __class__ = property(lambda *a, **k: int)
...  
... 
>>> from pickle import dumps
>>> dumps(Foo())
b'\x80\x03cbuiltins\nint\nq\x00)\x81q\x01}q\x02b.'

Here Foo() is pickled as an int. In Python 2 using type(obj) wouldn't work for 
old style classes, but I don't see a reason not to use type(obj) in Python 3.

Note that also, the pickle protocol methods like __getstate__ etc are looked up 
on the object instance (using getattr) rather than on the object type. This 
means that __getattr__ is invoked to look them up - requiring special casing in 
objects that provide __getattr__ to avoid them (raise  an AttributeError if 
they don't provide these methods). This affects three object types in the 
unittest.mock namespace (_Call, sentinel and the Mock variants).

----------
messages: 158254
nosy: michael.foord
priority: normal
severity: normal
status: open
title: pickling uses __class__ so you can't pickle proxy/mock objects that 
pretend to be other objects

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue14577>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to