From 4023914b10d73c655d78de2bff6471ddb86a23b4 Mon Sep 17 00:00:00 2001 From: Pablo Hoffman Date: Mon, 7 Sep 2009 09:37:46 -0300 Subject: [PATCH] added support for instantiating TextResponse (or any subclass) with unicode urls, improved organization of request/response unittests --- scrapy/http/response/__init__.py | 16 ++- scrapy/http/response/text.py | 11 +++ scrapy/selector/__init__.py | 2 +- scrapy/tests/test_http_request.py | 79 ++++++++------- scrapy/tests/test_http_response.py | 152 ++++++++++++++++++----------- 5 files changed, 163 insertions(+), 97 deletions(-) diff --git a/scrapy/http/response/__init__.py b/scrapy/http/response/__init__.py index cb6b8d776..9e4994642 100644 --- a/scrapy/http/response/__init__.py +++ b/scrapy/http/response/__init__.py @@ -12,14 +12,14 @@ from scrapy.utils.trackref import object_ref class Response(object_ref): - __slots__ = ['url', 'headers', 'status', '_body', 'request', '_meta', \ + __slots__ = ['_url', 'headers', 'status', '_body', 'request', '_meta', \ 'flags', '__weakref__'] def __init__(self, url, status=200, headers=None, body='', meta=None, flags=None): - self.url = url self.headers = Headers(headers or {}) self.status = int(status) self._set_body(body) + self._set_url(url) self.request = None self.flags = [] if flags is None else list(flags) self._meta = dict(meta) if meta else None @@ -30,6 +30,18 @@ class Response(object_ref): self._meta = {} return self._meta + def _get_url(self): + return self._url + + def _set_url(self, url): + if isinstance(url, str): + self._url = url + else: + raise TypeError('%s url must be str, got %s:' % (type(self).__name__, \ + type(url).__name__)) + + url = property(_get_url, _set_url) + def _get_body(self): return self._body diff --git a/scrapy/http/response/text.py b/scrapy/http/response/text.py index 7f0a32a40..ba99fd88e 100644 --- a/scrapy/http/response/text.py +++ b/scrapy/http/response/text.py @@ -24,6 +24,17 @@ class TextResponse(Response): self._body_inferred_encoding = None super(TextResponse, self).__init__(url, status, headers, body, meta, flags) + def _get_url(self): + return self._url + + def _set_url(self, url): + if isinstance(url, unicode): + self._url = url.encode(self.encoding) + else: + super(TextResponse, self)._set_url(url) + + url = property(_get_url, _set_url) + def _set_body(self, body): if isinstance(body, unicode): if self._encoding is None: diff --git a/scrapy/selector/__init__.py b/scrapy/selector/__init__.py index f1028b639..37f86d431 100644 --- a/scrapy/selector/__init__.py +++ b/scrapy/selector/__init__.py @@ -29,7 +29,7 @@ class XPathSelector(object_ref): self.doc = Libxml2Document(response, factory=self._get_libxml2_doc) self.xmlNode = self.doc.xmlDoc elif text: - response = TextResponse(url=None, body=unicode_to_str(text), \ + response = TextResponse(url='about:blank', body=unicode_to_str(text), \ encoding='utf-8') self.doc = Libxml2Document(response, factory=self._get_libxml2_doc) self.xmlNode = self.doc.xmlDoc diff --git a/scrapy/tests/test_http_request.py b/scrapy/tests/test_http_request.py index 6041f3063..bdefa0ec7 100644 --- a/scrapy/tests/test_http_request.py +++ b/scrapy/tests/test_http_request.py @@ -8,15 +8,17 @@ from scrapy.http import Request, FormRequest, XmlRpcRequest, Headers, Response class RequestTest(unittest.TestCase): + request_class = Request + def test_init(self): # Request requires url in the constructor - self.assertRaises(Exception, Request) + self.assertRaises(Exception, self.request_class) # url argument must be basestring - self.assertRaises(TypeError, Request, 123) - r = Request('http://www.example.com') + self.assertRaises(TypeError, self.request_class, 123) + r = self.request_class('http://www.example.com') - r = Request("http://www.example.com") + r = self.request_class("http://www.example.com") assert isinstance(r.url, str) self.assertEqual(r.url, "http://www.example.com") self.assertEqual(r.method, "GET") @@ -30,7 +32,7 @@ class RequestTest(unittest.TestCase): meta = {"lala": "lolo"} headers = {"caca": "coco"} - r = Request("http://www.example.com", meta=meta, headers=headers, body="a body") + r = self.request_class("http://www.example.com", meta=meta, headers=headers, body="a body") assert r.meta is not meta self.assertEqual(r.meta, meta) @@ -41,8 +43,8 @@ class RequestTest(unittest.TestCase): # Different ways of setting headers attribute url = 'http://www.scrapy.org' headers = {'Accept':'gzip', 'Custom-Header':'nothing to tell you'} - r = Request(url=url, headers=headers) - p = Request(url=url, headers=r.headers) + r = self.request_class(url=url, headers=headers) + p = self.request_class(url=url, headers=r.headers) self.assertEqual(r.headers, p.headers) self.assertFalse(r.headers is headers) @@ -58,8 +60,8 @@ class RequestTest(unittest.TestCase): def test_eq(self): url = 'http://www.scrapy.org' - r1 = Request(url=url) - r2 = Request(url=url) + r1 = self.request_class(url=url) + r2 = self.request_class(url=url) self.assertNotEqual(r1, r2) set_ = set() @@ -69,7 +71,7 @@ class RequestTest(unittest.TestCase): def test_url(self): """Request url tests""" - r = Request(url="http://www.scrapy.org/path") + r = self.request_class(url="http://www.scrapy.org/path") self.assertEqual(r.url, "http://www.scrapy.org/path") # url quoting on attribute assign @@ -79,9 +81,9 @@ class RequestTest(unittest.TestCase): self.assertEqual(r.url, "http://www.scrapy.org/blank%20space") # url quoting on creation - r = Request(url="http://www.scrapy.org/blank%20space") + r = self.request_class(url="http://www.scrapy.org/blank%20space") self.assertEqual(r.url, "http://www.scrapy.org/blank%20space") - r = Request(url="http://www.scrapy.org/blank space") + r = self.request_class(url="http://www.scrapy.org/blank space") self.assertEqual(r.url, "http://www.scrapy.org/blank%20space") # url coercion to string @@ -89,24 +91,24 @@ class RequestTest(unittest.TestCase): self.assert_(isinstance(r.url, str)) # url encoding - r1 = Request(url=u"http://www.scrapy.org/price/\xa3", encoding="utf-8") - r2 = Request(url=u"http://www.scrapy.org/price/\xa3", encoding="latin1") + r1 = self.request_class(url=u"http://www.scrapy.org/price/\xa3", encoding="utf-8") + r2 = self.request_class(url=u"http://www.scrapy.org/price/\xa3", encoding="latin1") self.assertEqual(r1.url, "http://www.scrapy.org/price/%C2%A3") self.assertEqual(r2.url, "http://www.scrapy.org/price/%A3") def test_body(self): - r1 = Request(url="http://www.example.com/") + r1 = self.request_class(url="http://www.example.com/") assert r1.body == '' - r2 = Request(url="http://www.example.com/", body="") + r2 = self.request_class(url="http://www.example.com/", body="") assert isinstance(r2.body, str) self.assertEqual(r2.encoding, 'utf-8') # default encoding - r3 = Request(url="http://www.example.com/", body=u"Price: \xa3100", encoding='utf-8') + r3 = self.request_class(url="http://www.example.com/", body=u"Price: \xa3100", encoding='utf-8') assert isinstance(r3.body, str) self.assertEqual(r3.body, "Price: \xc2\xa3100") - r4 = Request(url="http://www.example.com/", body=u"Price: \xa3100", encoding='latin1') + r4 = self.request_class(url="http://www.example.com/", body=u"Price: \xa3100", encoding='latin1') assert isinstance(r4.body, str) self.assertEqual(r4.body, "Price: \xa3100") @@ -116,7 +118,7 @@ class RequestTest(unittest.TestCase): def somecallback(): pass - r1 = Request("http://www.example.com", callback=somecallback) + r1 = self.request_class("http://www.example.com", callback=somecallback) r1.meta['foo'] = 'bar' r2 = r1.copy() @@ -137,7 +139,7 @@ class RequestTest(unittest.TestCase): def test_copy_inherited_classes(self): """Test Request children copies preserve their class""" - class CustomRequest(Request): + class CustomRequest(self.request_class): pass r1 = CustomRequest('example.com', 'http://www.example.com') @@ -148,7 +150,7 @@ class RequestTest(unittest.TestCase): def test_replace(self): """Test Request.replace() method""" hdrs = Headers({"key": "value"}) - r1 = Request("http://www.example.com") + r1 = self.request_class("http://www.example.com") r2 = r1.replace(method="POST", body="New body", headers=hdrs) self.assertEqual(r1.url, r2.url) self.assertEqual((r1.method, r2.method), ("GET", "POST")) @@ -156,7 +158,7 @@ class RequestTest(unittest.TestCase): self.assertEqual((r1.headers, r2.headers), ({}, hdrs)) # Empty attributes (which may fail if not compared properly) - r3 = Request("http://www.example.com", meta={'a': 1}, dont_filter=True) + r3 = self.request_class("http://www.example.com", meta={'a': 1}, dont_filter=True) r4 = r3.replace(url="http://www.example.com/2", body='', meta={}, dont_filter=False) self.assertEqual(r4.url, "http://www.example.com/2") self.assertEqual(r4.body, '') @@ -165,23 +167,24 @@ class RequestTest(unittest.TestCase): def test_weakref_slots(self): """Check that classes are using slots and are weak-referenceable""" - for cls in [Request, FormRequest]: - x = cls('http://www.example.com') - weakref.ref(x) - assert not hasattr(x, '__dict__'), "%s does not use __slots__" % \ - x.__class__.__name__ + x = self.request_class('http://www.example.com') + weakref.ref(x) + assert not hasattr(x, '__dict__'), "%s does not use __slots__" % \ + x.__class__.__name__ -class FormRequestTest(unittest.TestCase): +class FormRequestTest(RequestTest): + + request_class = FormRequest def test_empty_formdata(self): - r1 = FormRequest("http://www.example.com", formdata={}) + r1 = self.request_class("http://www.example.com", formdata={}) self.assertEqual(r1.body, '') def test_default_encoding(self): # using default encoding (utf-8) data = {'one': 'two', 'price': '\xc2\xa3 100'} - r2 = FormRequest("http://www.example.com", formdata=data) + r2 = self.request_class("http://www.example.com", formdata=data) self.assertEqual(r2.method, 'POST') self.assertEqual(r2.encoding, 'utf-8') self.assertEqual(r2.body, 'price=%C2%A3+100&one=two') @@ -189,14 +192,14 @@ class FormRequestTest(unittest.TestCase): def test_custom_encoding(self): data = {'price': u'\xa3 100'} - r3 = FormRequest("http://www.example.com", formdata=data, encoding='latin1') + r3 = self.request_class("http://www.example.com", formdata=data, encoding='latin1') self.assertEqual(r3.encoding, 'latin1') self.assertEqual(r3.body, 'price=%A3+100') def test_multi_key_values(self): # using multiples values for a single key data = {'price': u'\xa3 100', 'colours': ['red', 'blue', 'green']} - r3 = FormRequest("http://www.example.com", formdata=data) + r3 = self.request_class("http://www.example.com", formdata=data) self.assertEqual(r3.body, 'colours=red&colours=blue&colours=green&price=%C2%A3+100') def test_from_response_post(self): @@ -208,7 +211,7 @@ class FormRequestTest(unittest.TestCase): """ response = Response("http://www.example.com/this/list.html", body=respbody) - r1 = FormRequest.from_response(response, formdata={'one': ['two', 'three'], 'six': 'seven'}, callback=lambda x: x) + r1 = self.request_class.from_response(response, formdata={'one': ['two', 'three'], 'six': 'seven'}, callback=lambda x: x) self.assertEqual(r1.method, 'POST') self.assertEqual(r1.headers['Content-type'], 'application/x-www-form-urlencoded') fs = cgi.FieldStorage(StringIO(r1.body), r1.headers, environ={"REQUEST_METHOD": "POST"}) @@ -227,7 +230,7 @@ class FormRequestTest(unittest.TestCase): """ response = Response("http://www.example.com/this/list.html", body=respbody) - r1 = FormRequest.from_response(response, formdata={'one': ['two', 'three'], 'six': 'seven'}) + r1 = self.request_class.from_response(response, formdata={'one': ['two', 'three'], 'six': 'seven'}) self.assertEqual(r1.method, 'GET') self.assertEqual(urlparse(r1.url).hostname, "www.example.com") self.assertEqual(urlparse(r1.url).path, "/this/get.php") @@ -245,7 +248,7 @@ class FormRequestTest(unittest.TestCase): """ response = Response("http://www.example.com/this/list.html", body=respbody) - r1 = FormRequest.from_response(response, formdata={'two': '2'}) + r1 = self.request_class.from_response(response, formdata={'two': '2'}) fs = cgi.FieldStorage(StringIO(r1.body), r1.headers, environ={"REQUEST_METHOD": "POST"}) self.assertEqual(fs['one'].value, '1') self.assertEqual(fs['two'].value, '2') @@ -253,7 +256,7 @@ class FormRequestTest(unittest.TestCase): def test_from_response_errors_noform(self): respbody = """""" response = Response("http://www.example.com/lala.html", body=respbody) - self.assertRaises(ValueError, FormRequest.from_response, response) + self.assertRaises(ValueError, self.request_class.from_response, response) def test_from_response_errors_formnumber(self): respbody = """ @@ -264,7 +267,9 @@ class FormRequestTest(unittest.TestCase): """ response = Response("http://www.example.com/lala.html", body=respbody) - self.assertRaises(IndexError, FormRequest.from_response, response, formnumber=1) + self.assertRaises(IndexError, self.request_class.from_response, response, formnumber=1) + +# XXX: XmlRpcRequest doesn't respect original Request API. is this expected? class XmlRpcRequestTest(unittest.TestCase): diff --git a/scrapy/tests/test_http_response.py b/scrapy/tests/test_http_response.py index e0ca7df43..fb49422d8 100644 --- a/scrapy/tests/test_http_response.py +++ b/scrapy/tests/test_http_response.py @@ -3,19 +3,22 @@ import weakref from scrapy.http import Response, TextResponse, HtmlResponse, XmlResponse, Headers -class ResponseTest(unittest.TestCase): + +class BaseResponseTest(unittest.TestCase): + + response_class = Response def test_init(self): # Response requires url in the consturctor - self.assertRaises(Exception, Response) - self.assertTrue(isinstance(Response('http://example.com/'), Response)) - # body can be str or None but not ResponseBody - self.assertTrue(isinstance(Response('http://example.com/', body=''), Response)) - self.assertTrue(isinstance(Response('http://example.com/', body='body'), Response)) + self.assertRaises(Exception, self.response_class) + self.assertTrue(isinstance(self.response_class('http://example.com/'), self.response_class)) + # body can be str or None + self.assertTrue(isinstance(self.response_class('http://example.com/', body=''), self.response_class)) + self.assertTrue(isinstance(self.response_class('http://example.com/', body='body'), self.response_class)) # test presence of all optional parameters - self.assertTrue(isinstance(Response('http://example.com/', headers={}, status=200, body=''), Response)) + self.assertTrue(isinstance(self.response_class('http://example.com/', headers={}, status=200, body=''), self.response_class)) - r = Response("http://www.example.com") + r = self.response_class("http://www.example.com") assert isinstance(r.url, str) self.assertEqual(r.url, "http://www.example.com") self.assertEqual(r.status, 200) @@ -27,23 +30,23 @@ class ResponseTest(unittest.TestCase): meta = {"lala": "lolo"} headers = {"caca": "coco"} body = "a body" - r = Response("http://www.example.com", meta=meta, headers=headers, body="a body") + r = self.response_class("http://www.example.com", meta=meta, headers=headers, body=body) assert r.meta is not meta self.assertEqual(r.meta, meta) assert r.headers is not headers self.assertEqual(r.headers["caca"], "coco") - r = Response("http://www.example.com", status=301) + r = self.response_class("http://www.example.com", status=301) self.assertEqual(r.status, 301) - r = Response("http://www.example.com", status='301') + r = self.response_class("http://www.example.com", status='301') self.assertEqual(r.status, 301) - self.assertRaises(ValueError, Response, "http://example.com", status='lala200') + self.assertRaises(ValueError, self.response_class, "http://example.com", status='lala200') def test_copy(self): """Test Response copy""" - r1 = Response("http://www.example.com", body="Some body") + r1 = self.response_class("http://www.example.com", body="Some body") r1.meta['foo'] = 'bar' r1.flags.append('cached') r2 = r1.copy() @@ -66,7 +69,7 @@ class ResponseTest(unittest.TestCase): def test_copy_inherited_classes(self): """Test Response children copies preserve their class""" - class CustomResponse(Response): + class CustomResponse(self.response_class): pass r1 = CustomResponse('http://www.example.com') @@ -77,7 +80,7 @@ class ResponseTest(unittest.TestCase): def test_replace(self): """Test Response.replace() method""" hdrs = Headers({"key": "value"}) - r1 = Response("http://www.example.com") + r1 = self.response_class("http://www.example.com") r2 = r1.replace(status=301, body="New body", headers=hdrs) assert r1.body == '' self.assertEqual(r1.url, r2.url) @@ -85,33 +88,19 @@ class ResponseTest(unittest.TestCase): self.assertEqual((r1.body, r2.body), ('', "New body")) self.assertEqual((r1.headers, r2.headers), ({}, hdrs)) - r1 = TextResponse("http://www.example.com", body="hello", encoding="cp852") - r2 = r1.replace(url="http://www.example.com/other") - r3 = r1.replace(url="http://www.example.com/other", encoding="latin1") - - assert isinstance(r2, TextResponse) - self.assertEqual(r2.url, "http://www.example.com/other") - self.assertEqual(r2.encoding, "cp852") - self.assertEqual(r3.url, "http://www.example.com/other") - self.assertEqual(r3.encoding, "latin1") - # Empty attributes (which may fail if not compared properly) - r3 = Response("http://www.example.com", meta={'a': 1}, flags=['cached']) + r3 = self.response_class("http://www.example.com", meta={'a': 1}, flags=['cached']) r4 = r3.replace(body='', meta={}, flags=[]) self.assertEqual(r4.body, '') self.assertEqual(r4.meta, {}) self.assertEqual(r4.flags, []) - def test_encoding(self): - unicode_string = u'\u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442' - self.assertRaises(TypeError, Response, 'http://www.example.com', body=u'unicode body') - - original_string = unicode_string.encode('cp1251') - r1 = TextResponse('http://www.example.com', body=original_string, encoding='cp1251') - - # check body_as_unicode - self.assertTrue(isinstance(r1.body_as_unicode(), unicode)) - self.assertEqual(r1.body_as_unicode(), unicode_string) + def test_weakref_slots(self): + """Check that classes are using slots and are weak-referenceable""" + x = self.response_class('http://www.example.com') + weakref.ref(x) + assert not hasattr(x, '__dict__'), "%s does not use __slots__" % \ + x.__class__.__name__ def _assert_response_values(self, response, encoding, body): if isinstance(body, unicode): @@ -126,11 +115,57 @@ class ResponseTest(unittest.TestCase): self.assertEqual(response.body, body_str) self.assertEqual(response.body_as_unicode(), body_unicode) - def test_text_response(self): - r1 = TextResponse("http://www.example.com", headers={"Content-type": ["text/html; charset=utf-8"]}, body="\xc2\xa3") - r2 = TextResponse("http://www.example.com", encoding='utf-8', body=u"\xa3") - r3 = TextResponse("http://www.example.com", headers={"Content-type": ["text/html; charset=iso-8859-1"]}, body="\xa3") - r4 = TextResponse("http://www.example.com", body="\xa2\xa3") +class ResponseText(BaseResponseTest): + + def test_no_unicode_url(self): + self.assertRaises(TypeError, self.response_class, u'http://www.example.com') + + +class TextResponseTest(BaseResponseTest): + + response_class = TextResponse + + def test_replace(self): + super(TextResponseTest, self).test_replace() + r1 = self.response_class("http://www.example.com", body="hello", encoding="cp852") + r2 = r1.replace(url="http://www.example.com/other") + r3 = r1.replace(url="http://www.example.com/other", encoding="latin1") + + assert isinstance(r2, self.response_class) + self.assertEqual(r2.url, "http://www.example.com/other") + self.assertEqual(r2.encoding, "cp852") + self.assertEqual(r3.url, "http://www.example.com/other") + self.assertEqual(r3.encoding, "latin1") + + def test_unicode_url(self): + resp = self.response_class(url=u"http://www.example.com/price/\xa3", encoding='utf-8') + self.assertEqual(resp.url, 'http://www.example.com/price/\xc2\xa3') + resp = self.response_class(url=u"http://www.example.com/price/\xa3", encoding='latin-1') + self.assertEqual(resp.url, 'http://www.example.com/price/\xa3') + resp = self.response_class(url="http://www.example.com/price/", encoding='utf-8') + resp.url = u'http://www.example.com/price/\xa3' + self.assertEqual(resp.url, 'http://www.example.com/price/\xc2\xa3') + resp = self.response_class(u"http://www.example.com/price/\xa3", headers={"Content-type": ["text/html; charset=utf-8"]}) + self.assertEqual(resp.url, 'http://www.example.com/price/\xc2\xa3') + resp = self.response_class(u"http://www.example.com/price/\xa3", headers={"Content-type": ["text/html; charset=iso-8859-1"]}) + self.assertEqual(resp.url, 'http://www.example.com/price/\xa3') + + def test_unicode_body(self): + unicode_string = u'\u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442' + self.assertRaises(TypeError, self.response_class, 'http://www.example.com', body=u'unicode body') + + original_string = unicode_string.encode('cp1251') + r1 = self.response_class('http://www.example.com', body=original_string, encoding='cp1251') + + # check body_as_unicode + self.assertTrue(isinstance(r1.body_as_unicode(), unicode)) + self.assertEqual(r1.body_as_unicode(), unicode_string) + + def test_encoding(self): + r1 = self.response_class("http://www.example.com", headers={"Content-type": ["text/html; charset=utf-8"]}, body="\xc2\xa3") + r2 = self.response_class("http://www.example.com", encoding='utf-8', body=u"\xa3") + r3 = self.response_class("http://www.example.com", headers={"Content-type": ["text/html; charset=iso-8859-1"]}, body="\xa3") + r4 = self.response_class("http://www.example.com", body="\xa2\xa3") self.assertEqual(r1.headers_encoding(), "utf-8") self.assertEqual(r2.headers_encoding(), None) @@ -144,28 +179,33 @@ class ResponseTest(unittest.TestCase): self._assert_response_values(r3, 'iso-8859-1', u"\xa3") # TextResponse (and subclasses) must be passed a encoding when instantiating with unicode bodies - self.assertRaises(TypeError, TextResponse, "http://www.example.com", body=u"\xa3") + self.assertRaises(TypeError, self.response_class, "http://www.example.com", body=u"\xa3") + + +class HtmlResponseTest(TextResponseTest): + + response_class = HtmlResponse def test_html_encoding(self): body = """Some page Price: \xa3100' """ - r1 = HtmlResponse("http://www.example.com", body=body) + r1 = self.response_class("http://www.example.com", body=body) self._assert_response_values(r1, 'iso-8859-1', body) body = """ Price: \xa3100 """ - r2 = HtmlResponse("http://www.example.com", body=body) + r2 = self.response_class("http://www.example.com", body=body) self._assert_response_values(r2, 'iso-8859-1', body) # for conflicting declarations headers must take precedence body = """Some page Price: \xa3100' """ - r3 = HtmlResponse("http://www.example.com", headers={"Content-type": ["text/html; charset=iso-8859-1"]}, body=body) + r3 = self.response_class("http://www.example.com", headers={"Content-type": ["text/html; charset=iso-8859-1"]}, body=body) self._assert_response_values(r3, 'iso-8859-1', body) # make sure replace() preserves the encoding of the original response @@ -173,40 +213,38 @@ class ResponseTest(unittest.TestCase): r4 = r3.replace(body=body) self._assert_response_values(r4, 'iso-8859-1', body) + + +class XmlResponseTest(TextResponseTest): + + response_class = XmlResponse + def test_xml_encoding(self): body = "" - r1 = XmlResponse("http://www.example.com", body=body) + r1 = self.response_class("http://www.example.com", body=body) # XXX: we may want to swtich default XmlResponse encoding to utf-8 self._assert_response_values(r1, 'ascii', body) body = """""" - r2 = XmlResponse("http://www.example.com", body=body) + r2 = self.response_class("http://www.example.com", body=body) self._assert_response_values(r2, 'iso-8859-1', body) # make sure replace() preserves the explicit encoding passed in the constructor body = """""" - r3 = XmlResponse("http://www.example.com", body=body, encoding='utf-8') + r3 = self.response_class("http://www.example.com", body=body, encoding='utf-8') body2 = "New body" r4 = r3.replace(body=body2) self._assert_response_values(r4, 'utf-8', body2) # make sure replace() rediscovers the encoding (if not given explicitly) when changing the body body = """""" - r5 = XmlResponse("http://www.example.com", body=body) + r5 = self.response_class("http://www.example.com", body=body) body2 = """""" r6 = r5.replace(body=body2) self._assert_response_values(r5, 'iso-8859-1', body) self._assert_response_values(r6, 'utf-8', body2) - def test_weakref_slots(self): - """Check that classes are using slots and are weak-referenceable""" - for cls in [Response, TextResponse, XmlResponse, HtmlResponse]: - x = cls('http://www.example.com') - weakref.ref(x) - assert not hasattr(x, '__dict__'), "%s does not use __slots__" % \ - x.__class__.__name__ - if __name__ == "__main__": unittest.main()