Skip to content

Commit 0b86507

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 5e4fff4 commit 0b86507

File tree

2 files changed

+4
-5
lines changed

2 files changed

+4
-5
lines changed

tornado/httpclient.py

Lines changed: 0 additions & 1 deletion
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)

tornado/web.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2520,21 +2520,21 @@ def __init__(
25202520
) -> None:
25212521
self.status_code = status_code
25222522
self._log_message = log_message
2523-
self.args = args
2523+
self.log_args = args
25242524
self.reason = kwargs.get("reason", None)
25252525

25262526
@property
25272527
def log_message(self) -> Optional[str]:
25282528
"""
25292529
A backwards compatible way of accessing log_message.
25302530
"""
2531-
if self._log_message and not self.args:
2531+
if self._log_message and not self.log_args:
25322532
return self._log_message.replace("%", "%%")
25332533
return self._log_message
25342534

25352535
def get_message(self) -> Optional[str]:
2536-
if self._log_message and self.args:
2537-
return self._log_message % self.args
2536+
if self._log_message and self.log_args:
2537+
return self._log_message % self.log_args
25382538
return self._log_message
25392539

25402540
def __str__(self) -> str:

0 commit comments

Comments
 (0)