sendgrid / python-http-client

Twilio SendGrid's Python HTTP Client for calling APIs
https://sendgrid.com
MIT License
126 stars 101 forks source link

Client can be pickled and unpickled #22

Closed jussih closed 7 years ago

jussih commented 7 years ago

Implements #18

SendGridDX commented 7 years ago

CLA assistant check
All committers have signed the CLA.

jussih commented 7 years ago

Checking up on this. Are there any issues that would block this from being merged? Any requests for further changes?

logannc commented 7 years ago

This is incomplete without also exposing __reduce__ and __reduce_ex__.

A more complete fix here would be, in addition to exposing __getstate__ and __setstate__, to add something like below to the top of the implementation of __getattr__:

try:
    return super(Client, self).__getattr__(name)
except AttributeError as e:
    pass

This will be sure to allow the user to access anything defined on the python object (including __reduce__ and __reduce_ex__, etc). You still need to add the functions you've added as they don't have default implementations on object so pickling utilities will break when they check hasattr(o, '__getstate__') and assume it is what it normally is, rather than a new object, etc.

An even MORE complete fix is to NOT return a new object when it looks like a double underscore function - I think it is a reasonable limitation to the user experience to require special care / disallowing the shortcut syntax when your API happens to look like special Python functions (much like the explanation states in the docstring of Client._(self, name).

try:
    return super(Client, self).__getattr__(name)
except AttributeError as e:
    if name.startswith('__') and name.endswith('__'):
        raise e
jussih commented 7 years ago

__reduce__ and __reduce_ex__ are not necessary here, since the instance contains only data types Pickle can handle with the higher level interface of __getstate__ and __setstate__. A test case provided in the PR demonstrates a successful pickling and unpickling of an instance.

You are correct about the potential problems in __getattr__ and it merits an issue of it's own, but I still maintain this PR resolves this issue. Or can you provide an example of a failed pickling?

logannc commented 7 years ago

Huh. I thought I had an example Friday night, but I can't remember what it was. I guess I assumed it was required because it was originally failing on line 495 in pickle.py which implied it was defaulting to __reduce_ex__. I guess it uses __getstate__ and __setstate__ first elsewhere.

I'm still not convinced I didn't have an example. I feel like I'll run into it later. If I do, I'll let you know. Otherwise, carry on! :)

thinkingserious commented 7 years ago

Hello @jussih,

Thanks again for the PR!

We want to show our appreciation by sending you some swag. Could you please fill out this form so we can send it to you? Thanks!

Team SendGrid DX