Merge ~nansari/django-piston:fix-for-SN-1445 into django-piston:master

Proposed by Najam Ahmed Ansari
Status: Rejected
Rejected by: Najam Ahmed Ansari
Proposed branch: ~nansari/django-piston:fix-for-SN-1445
Merge into: django-piston:master
Diff against target: 95 lines (+8/-41)
3 files modified
piston/__init__.py (+1/-1)
piston/tests.py (+6/-3)
piston/utils.py (+1/-37)
Reviewer Review Type Date Requested Status
Ubuntu One hackers Pending
Review via email: mp+446033@code.launchpad.net

Commit message

Fix for SN-1445

Description of the change

This fixes the bug in SCA wherein the SCA resource error handler the clobbers original exception message.

To post a comment you must log in.
Revision history for this message
Przemysław Suliga (suligap) wrote :

Hi, skimming the django-piston and Django code, I suspect a potential cleaner fix might be the removal of django-piston's HttpResponseWrapper (or not using the wrapper when on new enough Django). Have you tried that?

Because there are other places in django piston that set response.content as a string it looks like. Django's HttpResponse handles conversion and the wrapper doesn't. It's possible the wrapper is not needed for the django version we use?

Revision history for this message
Przemysław Suliga (suligap) wrote :

But that might be going against the "just apply a minimal fix to piston" approach. So if this works for SCA, then it should be fine.

Revision history for this message
Maximiliano Bertacchini (maxiberta) wrote :

I think I agree with Przemek here: piston's HttpResponseWrapper is apparently just trying to workaround an issue in django's HttpResponse, according to a comment in HttpResponseWrapper's code. But the issue http://code.djangoproject.com/ticket/9403 was fixed 11 years ago!!! :D:D:D

Maybe we can just drop HttpResponseWrapper and update piston's rc_factory.__getattr__() to return a plain HttpResponse? Afaict, the fix shipped in Django 1.4 (see https://github.com/django/django/commit/50255e3305 which is linked from the main issue). Based on piston's tox tests, we support Django >=1.4 which sounds like a really great coincidence and in which case we can just drop it and forget about django versions.

09f52da... by Najam Ahmed Ansari <email address hidden>

Removing piston's custom HttpResponseWrapper

The wrapper class was attempting to work around a bug in Django which has since
been fixed, rendering the wrapper unnecessary. Removing the wrapper also fixes
SN-1445.

Unmerged commits

09f52da... by Najam Ahmed Ansari <email address hidden>

Removing piston's custom HttpResponseWrapper

The wrapper class was attempting to work around a bug in Django which has since
been fixed, rendering the wrapper unnecessary. Removing the wrapper also fixes
SN-1445.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/piston/__init__.py b/piston/__init__.py
index ffdf661..7be60e2 100644
--- a/piston/__init__.py
+++ b/piston/__init__.py
@@ -1,4 +1,4 @@
1__version__ = '2.2.6'1__version__ = '2.2.7'
22
33
4def get_version():4def get_version():
diff --git a/piston/tests.py b/piston/tests.py
index aacce0b..f82460d 100644
--- a/piston/tests.py
+++ b/piston/tests.py
@@ -99,7 +99,7 @@ class CustomResponseWithStatusCodeTest(TestCase):
9999
100 def create(self, request):100 def create(self, request):
101 resp = rc.CREATED101 resp = rc.CREATED
102 resp.content = response_data102 resp.content = json.dumps(response_data)
103 return resp103 return resp
104104
105 resource = Resource(MyHandler)105 resource = Resource(MyHandler)
@@ -146,11 +146,11 @@ class ErrorHandlerTest(TestCase):
146 # formatted as json146 # formatted as json
147 if isinstance(error, GoAwayError):147 if isinstance(error, GoAwayError):
148 response = rc.FORBIDDEN148 response = rc.FORBIDDEN
149 response.content = dict(error=dict(149 response.content = json.dumps(dict(error=dict(
150 name=error.name,150 name=error.name,
151 message="Get out of here and dont come back",151 message="Get out of here and dont come back",
152 reason=error.reason152 reason=error.reason
153 ))153 )))
154154
155 return response155 return response
156156
@@ -187,6 +187,9 @@ class ErrorHandlerTest(TestCase):
187187
188 self.assertTrue(isinstance(response, HttpResponse), "Expected a response, not: %s"188 self.assertTrue(isinstance(response, HttpResponse), "Expected a response, not: %s"
189 % response)189 % response)
190 error_str = response.content.decode('utf-8')
191 self.assertTrue(error_str.find('Method signature does not match'),
192 'Expected underlying exception to be handled')
190193
191194
192 def test_other_error(self):195 def test_other_error(self):
diff --git a/piston/utils.py b/piston/utils.py
index 8e76718..a48c201 100644
--- a/piston/utils.py
+++ b/piston/utils.py
@@ -51,43 +51,7 @@ class rc_factory(object):
51 except TypeError:51 except TypeError:
52 raise AttributeError(attr)52 raise AttributeError(attr)
5353
54 class HttpResponseWrapper(HttpResponse):54 return HttpResponse(r, content_type='text/plain', status=c)
55 """
56 Wrap HttpResponse and make sure that the internal
57 _is_string/_base_content_is_iter flag is updated when the
58 _set_content method (via the content property) is called
59 """
60 def _set_content(self, content):
61 """
62 Set the _container and _base_content_is_iter properties based
63 on the type of the value parameter. This logic is in the
64 construtor for HttpResponse, but doesn't get repeated when
65 setting HttpResponse.content although this bug report
66 (feature request) suggests that it should:
67 http://code.djangoproject.com/ticket/9403
68 """
69 if not isinstance(content, basestring) and hasattr(content, '__iter__'):
70 self._container = content
71 self._use_emitter = True
72 else:
73 self._container = [content]
74 self._use_emitter = False
75 # Django 1.7 and above does not have any custom internals to
76 # define the type of the content
77 if django.VERSION < (1, 7):
78 self._base_content_is_iter = self._use_emitter
79
80 if django.VERSION >= (1, 5):
81 # HttpResponse._get_content does not exists in Django >= 1.5
82
83 @HttpResponse.content.setter
84 def content(self, content):
85 self._set_content(content)
86
87 else:
88 content = property(HttpResponse._get_content, _set_content)
89
90 return HttpResponseWrapper(r, content_type='text/plain', status=c)
9155
92rc = rc_factory()56rc = rc_factory()
9357

Subscribers

People subscribed via source and target branches