From: Ben Darnell Date: Mon, 28 Sep 2015 00:55:09 +0000 (-0400) Subject: Make HTTPError (both of them) copyable. X-Git-Tag: v4.3.0b1~27^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f075f2e9002eff539bb5b56742ee341b89940211;p=thirdparty%2Ftornado.git Make HTTPError (both of them) copyable. `Exception.__reduce__` causes copy.copy() to create a new argument with the arguments from `Exception.__init__`, then overwrite attributes from the original `__dict__`. This means that copying fails if there are mandatory arguments that are not passed to `__init__`. Fixes #1485 --- diff --git a/tornado/httpclient.py b/tornado/httpclient.py index c2e686236..9179227b1 100644 --- a/tornado/httpclient.py +++ b/tornado/httpclient.py @@ -603,9 +603,12 @@ class HTTPError(Exception): """ def __init__(self, code, message=None, response=None): self.code = code - message = message or httputil.responses.get(code, "Unknown") + self.message = message or httputil.responses.get(code, "Unknown") self.response = response - Exception.__init__(self, "HTTP %d: %s" % (self.code, message)) + super(HTTPError, self).__init__(code, message, response) + + def __str__(self): + return "HTTP %d: %s" % (self.code, self.message) class _RequestProxy(object): diff --git a/tornado/test/httpclient_test.py b/tornado/test/httpclient_test.py index ecc63e4a4..c5738f27f 100644 --- a/tornado/test/httpclient_test.py +++ b/tornado/test/httpclient_test.py @@ -5,6 +5,7 @@ from __future__ import absolute_import, division, print_function, with_statement import base64 import binascii from contextlib import closing +import copy import functools import sys import threading @@ -605,3 +606,15 @@ class HTTPRequestTestCase(unittest.TestCase): request = HTTPRequest('http://example.com', if_modified_since=http_date) self.assertEqual(request.headers, {'If-Modified-Since': format_timestamp(http_date)}) + + +class HTTPErrorTestCase(unittest.TestCase): + def test_copy(self): + e = HTTPError(403) + e2 = copy.copy(e) + self.assertIsNot(e, e2) + self.assertEqual(e.code, e2.code) + + def test_str(self): + e = HTTPError(403) + self.assertEqual(str(e), "HTTP 403: Forbidden") diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py index 829dfe483..89a54cfab 100644 --- a/tornado/test/web_test.py +++ b/tornado/test/web_test.py @@ -15,6 +15,7 @@ from tornado.web import RequestHandler, authenticated, Application, asynchronous import binascii import contextlib +import copy import datetime import email.utils import itertools @@ -2670,3 +2671,12 @@ class RequestSummaryTest(SimpleHandlerTestCase): def test_missing_remote_ip(self): resp = self.fetch("/") self.assertEqual(resp.body, b"GET / (None)") + + +class HTTPErrorTest(unittest.TestCase): + def test_copy(self): + e = HTTPError(403, reason="Go away") + e2 = copy.copy(e) + self.assertIsNot(e, e2) + self.assertEqual(e.status_code, e2.status_code) + self.assertEqual(e.reason, e2.reason) diff --git a/tornado/web.py b/tornado/web.py index dd0df5efd..b33ddbb48 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -2063,7 +2063,7 @@ class HTTPError(Exception): determined automatically from ``status_code``, but can be used to use a non-standard numeric code. """ - def __init__(self, status_code, log_message=None, *args, **kwargs): + def __init__(self, status_code=500, log_message=None, *args, **kwargs): self.status_code = status_code self.log_message = log_message self.args = args