Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[1.1.X] Fixed #13332 -- Corrected the cleanup code in the test client…

… to avoid 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.

Backport of r12964 from trunk.

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

0 notes on commit 65a9d73

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