New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TransformWrapper pickling fixes #4915
Conversation
Actually, now that I think about it, is there any reason to override |
@pelson you have any insight into this? |
This is a really heavy-handed solution to this problem. I think it would be better to pull the re-usable stuff out into a private function rather than add an extra kwarg. Adding a private function is not an API change, where as adding a kwarg is (granted a back-compatible one). More importantly, removing a private function is not an API where as removing a kwarg definitely is a breaking change. |
You're probably right but I'm still wondering why |
In cases like this it is usually worth doing the forensics to sort out when that change came into the code base. |
Normally a good idea, but unfortunately, the blame shows it was added to |
87d46c8
to
167d196
Compare
OK, I see it's a Python 2 thing; I'll go with your suggestion then. |
167d196
to
353d8f1
Compare
I also noticed that since from __future__ import print_function
import pickle
import matplotlib.transforms as mtransforms
class TestTransform(object):
def __init__(self):
self.identity = mtransforms.IdentityTransform()
self.identity2 = mtransforms.IdentityTransform()
self.composite = self.identity + self.identity2
self.wrapper = mtransforms.TransformWrapper(self.composite)
self.wrapper2 = mtransforms.TransformWrapper(self.wrapper)
c = TestTransform()
print(c.wrapper2._child, list(c.wrapper2._child._parents.items()))
print(c.wrapper._child, list(c.wrapper._child._parents.items()))
pkl = pickle.dumps(c)
del c
ret = pickle.loads(pkl)
print(ret.wrapper2._child, list(ret.wrapper2._child._parents.items()))
print(ret.wrapper._child, list(ret.wrapper._child._parents.items())) |
I suspect that is why the set child is there. Why would setting the parents do any better that setting children if the On Fri, Aug 14, 2015, 12:01 AM Elliott Sales de Andrade <
|
The pickling failed because of setting parents on the child. The additional commit here sets the parents for itself. |
self.__init__(state['child']) | ||
self._init(state['child']) | ||
# turn the normal dictionary back into a WeakValueDictionary | ||
self._parents = WeakValueDictionary(state['parents']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not clear that this is going to work, are there going to be other refs to these instances of the objects will be held so they won't get immediately gc'd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same method used in the grandparent TransformNode
, so if it were going to fail, it would have done so a while ago.
There should be a strong reference from parent -> child assuming the transform's implemented correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair enough.
This seems reasonable and the tests pass, but this is a bit of the code that I know very little about |
Unfortunately, I think @pelson is on vacation at the moment. |
@QuLogic - would you mind adding a unit test? If nothing else, it will make reviewing the change easier. |
In writing the test, I'm wondering if it matters what the key is in the |
Calling set_children may or may not work if the child has been unpickled yet, and it actually causes duplicate parents to be set in the times when it does appear to work.
Pickling would lose track of the parents for a TransformWrapper because of the override of grandparent's pickling methods.
353d8f1
to
2047c3a
Compare
I added the test, but like I said, I'm not sure whether the unpickling is as consistent as it could be. It hasn't really lead to any problems though, so if @pelson's okay with it, this PR could be accepted as is. |
@pelson Can you please review this again? |
back ported as cba1283 |
Calling set_children may or may not work if the child has been unpickled yet, and it actually causes duplicate parents to be set in the times when it does appear to work.
Using the example from #4908 with some additional prints:
If it succeeds, the result is:
You can see that the unpickled child transform has a second fictitious parent.
So the simple fix appears to be to avoid calling
set_children
...Fixes #4908.