Status: Accepted
Owner: ----
Labels: Type-Defect Priority-High Core
New issue 3130 by [email protected]: Unpickling a Symbol with protocol 2
corrupts the cache
http://code.google.com/p/sympy/issues/detail?id=3130
Here's a minimal demo of the problem:
In [1]: import pickle
In [2]: pickle.loads(pickle.dumps(Symbol('a', even=True), 2))
Out[2]: a
In [3]: Symbol('a').is_even
Out[3]: True
Let's replay the scene in slow-motion:
* First, while instantiating a1 = Symbol('a', even=True), the cache system
stores something like cache[Symbol, ('a',), {'even': True}] = a1. No
problem here.
* Then, dumps(a1) is effectively equivalent to:
args = a1.__getnewargs__()
state = a1.__getstate__()
Here, args is just (a1.name,) == ('a',) while state is equal to what
a1.__dict__ would be if there were no __slots__ declarations.
* Then, the loads() call does effectively:
a2 = Symbol(*args)
a2.__setstate__(state)
The instantiation of a2 puts cache[Symbol, ('a',), {}] = a2 in the cache,
but then __setstate__ copies over the attributes of a1 into a2, including
its _assumptions dict, which causes a2.is_even == True.
* And finally, the last call to Symbol('a') finds that there is already a
cached entry for cache[Symbol, ('a',), {}] and returns a2 directly.
I don't know how we should fix this mess, but I think that pickling
shouldn't rely on __slots__ (it serialises too much) and that the cache
shouldn't store the name of the Symbol since that doesn't save any
processing.
--
You received this message because you are subscribed to the Google Groups
"sympy-issues" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sympy-issues?hl=en.