Skip to content
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

Make HttpStatusError and RequestError pickleable #3108

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions httpx/_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ def request(self) -> Request:
def request(self, request: Request) -> None:
self._request = request

def __reduce__(
self,
) -> typing.Tuple[
typing.Callable[..., Exception], typing.Tuple[typing.Any], dict[str, typing.Any]
]:
return (Exception.__new__, (type(self),) + self.args, self.__dict__)

Comment on lines +106 to +112
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we able to be consistent with how pickle is supported on Request/Response here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the key word only arguments of Request have default values so that's why it's pickleable. Our choices here are:

  1. Give all kwonly arguments defaults. Classes where all kwonly arguments have defaults mostly have the correct pickle behavior without any special support.
  2. Do something like what I have here.

As an aside, this is a bit of a Python wart, ideally simple classes with required kwonly constructor args should be pickleable out of the box. I wonder if there is any discussion on discuss.python.org about it...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay sure thing.
Thanks for the fix. ☺️


class RequestError(HTTPError):
"""
Expand Down
16 changes: 16 additions & 0 deletions tests/test_pickle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pickle

from httpx import HTTPStatusError, RequestError


def test_pickle():
req_err = RequestError("hi!", request="request") # type:ignore[arg-type]
req_err_clone = pickle.loads(pickle.dumps(req_err))
assert req_err.args == req_err_clone.args
assert req_err.request == req_err_clone.request

status_err = HTTPStatusError("hi", request="request", response="response") # type:ignore[arg-type]
status_err_clone = pickle.loads(pickle.dumps(status_err))
assert status_err.args == status_err_clone.args
assert status_err.request == status_err_clone.request
assert status_err.response == status_err_clone.response