-
Notifications
You must be signed in to change notification settings - Fork 438
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
Fix unpickling in Python 3 #353
Conversation
stripe/resource.py
Outdated
def __setstate__(self, state): | ||
self.update(state) | ||
|
||
def __reduce__(self): |
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.
Can we do comments on both __setstate__
and __reduce__
that follow roughly exactly what you said in the PR description?
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.
(Someone reading this who didn't see the original PR might wonder what exactly is going on here.)
obj.refresh_from( | ||
{ | ||
'fala': 'lalala', | ||
'emptystring': '', |
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.
Can we put a comment here explaining that emptystring
is trying to uncover a specific Python 3 unpickling issue?
Thanks for tracking this down OB!
Yeah, the dict subclass thing is so brutal. We should definitely consider squashing that at some point. |
Added some comments as requested. |
Excellent. Thanks! |
r? @brandur-stripe
cc @stripe/api-libraries
Fixes #352.
This was annoying :/
Basically, the issue is that when unpickling
StripeObject
s, Python 3 calls our custom__setitem__
method which forbids empty strings.In order to directly reset the dict values, it is necessary to create a custom
__setstate__
method that will useupdate
instead.However, because
StripeObject
is a subclass ofdict
,__setstate__
is not called automatically when unpickling the instance, and I had to define a__reduce__
method to force the pickler to treat the instance as a custom class and not as a normal dict.I'm not super happy with this fix as it's relatively brittle (
__reduce__
needs to be consistent with the class constructor) but it's an unfortunate consequence of havingStripeObject
directly subclassdict
. I wish we had gone with composition over inheritance here, but that's another discussion...