Skip to content

Commit 9cb31f2

Browse files
committed
Fix pickling of httpclient.HTTPError subclasses and web.HTTPError
The `args` member variable is set by `BaseException.__new__` and used by `BaseException.__reduce__` for pickling. To avoid interfering with it, we need to avoid calling `BaseException.__init__` from classes that have subclasses with incompatible constructors, and rename our own `tornado.web.HTTPError.args` member. >>> pickle.loads(pickle.dumps(tornado.simple_httpclient.HTTPTimeoutError("message"))) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: HTTPTimeoutError.__init__() takes 2 positional arguments but 4 were given >>> str(pickle.loads(pickle.dumps(tornado.web.HTTPError(500, "%s", "foo")))) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/anders/python/tornado/tornado/web.py", line 2488, in __str__ return message + " (" + (self.log_message % self.args) + ")" ~~~~~~~~~~~~~~~~~^~~~~~~~~~~ TypeError: not enough arguments for format string Signed-off-by: Anders Kaseorg <[email protected]>
1 parent 2a0e1d1 commit 9cb31f2

File tree

2 files changed

+5
-4
lines changed

2 files changed

+5
-4
lines changed

Diff for: tornado/httpclient.py

-1
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,6 @@ def __init__(
717717
self.code = code
718718
self.message = message or httputil.responses.get(code, "Unknown")
719719
self.response = response
720-
super().__init__(code, message, response)
721720

722721
def __str__(self) -> str:
723722
return "HTTP %d: %s" % (self.code, self.message)

Diff for: tornado/web.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -1869,7 +1869,9 @@ def log_exception(
18691869
if isinstance(value, HTTPError):
18701870
if value.log_message:
18711871
format = "%d %s: " + value.log_message
1872-
args = [value.status_code, self._request_summary()] + list(value.args)
1872+
args = [value.status_code, self._request_summary()] + list(
1873+
value.log_args
1874+
)
18731875
gen_log.warning(format, *args)
18741876
else:
18751877
app_log.error(
@@ -2474,7 +2476,7 @@ def __init__(
24742476
) -> None:
24752477
self.status_code = status_code
24762478
self.log_message = log_message
2477-
self.args = args
2479+
self.log_args = args
24782480
self.reason = kwargs.get("reason", None)
24792481
if log_message and not args:
24802482
self.log_message = log_message.replace("%", "%%")
@@ -2485,7 +2487,7 @@ def __str__(self) -> str:
24852487
self.reason or httputil.responses.get(self.status_code, "Unknown"),
24862488
)
24872489
if self.log_message:
2488-
return message + " (" + (self.log_message % self.args) + ")"
2490+
return message + " (" + (self.log_message % self.log_args) + ")"
24892491
else:
24902492
return message
24912493

0 commit comments

Comments
 (0)