From 86fb33d13d9ad2b3f281e66179b342e00ee07286 Mon Sep 17 00:00:00 2001 From: Jamie Lennox Date: Wed, 7 Dec 2016 11:10:14 +1100 Subject: [PATCH] Type check the empty string when creating repsonse When creating a response we type check that the user has passed the correct type to content and text, however we check this based on whether the value is True and not whether it has been passed at all which means that the empty string of the wrong type can incorrectly pass through this check. Fix this check to test the empty string. Anyone relying on this passing will be caught with a more confusing TypeError later and so this should be backwards compatible. Change-Id: I826da9b7fd83bb88af50e4a96a5e6358ee35e4b2 Closes-Bug: #1647880 --- requests_mock/response.py | 12 ++++++------ requests_mock/tests/test_adapter.py | 17 +++++++++++++++++ requests_mock/tests/test_response.py | 5 +++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/requests_mock/response.py b/requests_mock/response.py index 9661ed3..345d190 100644 --- a/requests_mock/response.py +++ b/requests_mock/response.py @@ -147,9 +147,9 @@ def create_response(request, **kwargs): json = kwargs.pop('json', None) encoding = None - if content and not isinstance(content, six.binary_type): + if content is not None and not isinstance(content, six.binary_type): raise TypeError('Content should be binary data') - if text and not isinstance(text, six.string_types): + if text is not None and not isinstance(text, six.string_types): raise TypeError('Text should be string data') if json is not None: @@ -207,12 +207,12 @@ class _MatcherResponse(object): content = self._params.get('content') text = self._params.get('text') - if content and not (callable(content) or - isinstance(content, six.binary_type)): + if content is not None and not (callable(content) or + isinstance(content, six.binary_type)): raise TypeError('Content should be a callback or binary data') - if text and not (callable(text) or - isinstance(text, six.string_types)): + if text is not None and not (callable(text) or + isinstance(text, six.string_types)): raise TypeError('Text should be a callback or string data') def get_response(self, request): diff --git a/requests_mock/tests/test_adapter.py b/requests_mock/tests/test_adapter.py index 3d370d2..0f1dd30 100644 --- a/requests_mock/tests/test_adapter.py +++ b/requests_mock/tests/test_adapter.py @@ -265,6 +265,13 @@ class SessionAdapterTests(base.TestCase): self.url, content=six.u('unicode')) + def test_dont_pass_empty_string_as_content(self): + self.assertRaises(TypeError, + self.adapter.register_uri, + 'GET', + self.url, + content=six.u('')) + def test_dont_pass_bytes_as_text(self): if six.PY2: self.skipTest('Cannot enforce byte behaviour in PY2') @@ -275,6 +282,16 @@ class SessionAdapterTests(base.TestCase): self.url, text=six.b('bytes')) + def test_dont_pass_empty_string_as_text(self): + if six.PY2: + self.skipTest('Cannot enforce byte behaviour in PY2') + + self.assertRaises(TypeError, + self.adapter.register_uri, + 'GET', + self.url, + text=six.b('')) + def test_dont_pass_non_str_as_content(self): self.assertRaises(TypeError, self.adapter.register_uri, diff --git a/requests_mock/tests/test_response.py b/requests_mock/tests/test_response.py index 42e00a5..d31c985 100644 --- a/requests_mock/tests/test_response.py +++ b/requests_mock/tests/test_response.py @@ -46,9 +46,14 @@ class ResponseTests(base.TestCase): self.assertRaises(TypeError, self.create_response, text=55) self.assertRaises(TypeError, self.create_response, text={'a': 1}) + # this only works on python 2 because bytes is a string + if six.PY3: + self.assertRaises(TypeError, self.create_response, text=six.b('')) + def test_text_type(self): self.assertRaises(TypeError, self.create_response, content=six.u('t')) self.assertRaises(TypeError, self.create_response, content={'a': 1}) + self.assertRaises(TypeError, self.create_response, content=six.u('')) def test_json_body(self): data = {'a': 1}