Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #13332 -- Corrected the cleanup code in the test client to avoi…

…d a refcounting problem with signal handlers. This is a fix for the benefit of PyPy's hybrid GC. Thanks to Alex Gaynor for the report and patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12964 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 35f41507343e1ef60bf37be9f2d46606c4a0e1a3 1 parent b7b38a4
Russell Keith-Magee authored April 13, 2010

Showing 1 changed file with 46 additions and 42 deletions. Show diff stats Hide diff stats

  1. 88  django/test/client.py
88  django/test/client.py
@@ -221,53 +221,57 @@ def request(self, **request):
221 221
         # callback function.
222 222
         data = {}
223 223
         on_template_render = curry(store_rendered_templates, data)
224  
-        signals.template_rendered.connect(on_template_render)
225  
-
  224
+        signals.template_rendered.connect(on_template_render, dispatch_uid="template-render")
226 225
         # Capture exceptions created by the handler.
227  
-        got_request_exception.connect(self.store_exc_info)
228  
-
  226
+        got_request_exception.connect(self.store_exc_info, dispatch_uid="request-exception")
229 227
         try:
230  
-            response = self.handler(environ)
231  
-        except TemplateDoesNotExist, e:
232  
-            # If the view raises an exception, Django will attempt to show
233  
-            # the 500.html template. If that template is not available,
234  
-            # we should ignore the error in favor of re-raising the
235  
-            # underlying exception that caused the 500 error. Any other
236  
-            # template found to be missing during view error handling
237  
-            # should be reported as-is.
238  
-            if e.args != ('500.html',):
239  
-                raise
240  
-
241  
-        # Look for a signalled exception, clear the current context
242  
-        # exception data, then re-raise the signalled exception.
243  
-        # Also make sure that the signalled exception is cleared from
244  
-        # the local cache!
245  
-        if self.exc_info:
246  
-            exc_info = self.exc_info
247  
-            self.exc_info = None
248  
-            raise exc_info[1], None, exc_info[2]
249  
-
250  
-        # Save the client and request that stimulated the response.
251  
-        response.client = self
252  
-        response.request = request
253  
-
254  
-        # Add any rendered template detail to the response.
255  
-        # If there was only one template rendered (the most likely case),
256  
-        # flatten the list to a single element.
257  
-        for detail in ('template', 'context'):
258  
-            if data.get(detail):
259  
-                if len(data[detail]) == 1:
260  
-                    setattr(response, detail, data[detail][0]);
  228
+
  229
+            try:
  230
+                response = self.handler(environ)
  231
+            except TemplateDoesNotExist, e:
  232
+                # If the view raises an exception, Django will attempt to show
  233
+                # the 500.html template. If that template is not available,
  234
+                # we should ignore the error in favor of re-raising the
  235
+                # underlying exception that caused the 500 error. Any other
  236
+                # template found to be missing during view error handling
  237
+                # should be reported as-is.
  238
+                if e.args != ('500.html',):
  239
+                    raise
  240
+
  241
+            # Look for a signalled exception, clear the current context
  242
+            # exception data, then re-raise the signalled exception.
  243
+            # Also make sure that the signalled exception is cleared from
  244
+            # the local cache!
  245
+            if self.exc_info:
  246
+                exc_info = self.exc_info
  247
+                self.exc_info = None
  248
+                raise exc_info[1], None, exc_info[2]
  249
+
  250
+            # Save the client and request that stimulated the response.
  251
+            response.client = self
  252
+            response.request = request
  253
+
  254
+            # Add any rendered template detail to the response.
  255
+            # If there was only one template rendered (the most likely case),
  256
+            # flatten the list to a single element.
  257
+            for detail in ('template', 'context'):
  258
+                if data.get(detail):
  259
+                    if len(data[detail]) == 1:
  260
+                        setattr(response, detail, data[detail][0]);
  261
+                    else:
  262
+                        setattr(response, detail, data[detail])
261 263
                 else:
262  
-                    setattr(response, detail, data[detail])
263  
-            else:
264  
-                setattr(response, detail, None)
  264
+                    setattr(response, detail, None)
265 265
 
266  
-        # Update persistent cookie data.
267  
-        if response.cookies:
268  
-            self.cookies.update(response.cookies)
  266
+            # Update persistent cookie data.
  267
+            if response.cookies:
  268
+                self.cookies.update(response.cookies)
  269
+
  270
+            return response
  271
+        finally:
  272
+            signals.template_rendered.disconnect(dispatch_uid="template-render")
  273
+            got_request_exception.disconnect(dispatch_uid="request-exception")
269 274
 
270  
-        return response
271 275
 
272 276
     def get(self, path, data={}, follow=False, **extra):
273 277
         """

0 notes on commit 35f4150

Please sign in to comment.
Something went wrong with that request. Please try again.