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.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12964 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2010-04-13 02:41:37 +00:00
parent b7b38a41b0
commit 35f4150734
1 changed files with 43 additions and 39 deletions

View File

@ -221,53 +221,57 @@ class Client(object):
# callback function. # callback function.
data = {} data = {}
on_template_render = curry(store_rendered_templates, data) on_template_render = curry(store_rendered_templates, data)
signals.template_rendered.connect(on_template_render) signals.template_rendered.connect(on_template_render, dispatch_uid="template-render")
# Capture exceptions created by the handler. # Capture exceptions created by the handler.
got_request_exception.connect(self.store_exc_info) got_request_exception.connect(self.store_exc_info, dispatch_uid="request-exception")
try: try:
response = self.handler(environ)
except TemplateDoesNotExist, e:
# If the view raises an exception, Django will attempt to show
# the 500.html template. If that template is not available,
# we should ignore the error in favor of re-raising the
# underlying exception that caused the 500 error. Any other
# template found to be missing during view error handling
# should be reported as-is.
if e.args != ('500.html',):
raise
# Look for a signalled exception, clear the current context try:
# exception data, then re-raise the signalled exception. response = self.handler(environ)
# Also make sure that the signalled exception is cleared from except TemplateDoesNotExist, e:
# the local cache! # If the view raises an exception, Django will attempt to show
if self.exc_info: # the 500.html template. If that template is not available,
exc_info = self.exc_info # we should ignore the error in favor of re-raising the
self.exc_info = None # underlying exception that caused the 500 error. Any other
raise exc_info[1], None, exc_info[2] # template found to be missing during view error handling
# should be reported as-is.
if e.args != ('500.html',):
raise
# Save the client and request that stimulated the response. # Look for a signalled exception, clear the current context
response.client = self # exception data, then re-raise the signalled exception.
response.request = request # Also make sure that the signalled exception is cleared from
# the local cache!
if self.exc_info:
exc_info = self.exc_info
self.exc_info = None
raise exc_info[1], None, exc_info[2]
# Add any rendered template detail to the response. # Save the client and request that stimulated the response.
# If there was only one template rendered (the most likely case), response.client = self
# flatten the list to a single element. response.request = request
for detail in ('template', 'context'):
if data.get(detail): # Add any rendered template detail to the response.
if len(data[detail]) == 1: # If there was only one template rendered (the most likely case),
setattr(response, detail, data[detail][0]); # flatten the list to a single element.
for detail in ('template', 'context'):
if data.get(detail):
if len(data[detail]) == 1:
setattr(response, detail, data[detail][0]);
else:
setattr(response, detail, data[detail])
else: else:
setattr(response, detail, data[detail]) setattr(response, detail, None)
else:
setattr(response, detail, None)
# Update persistent cookie data. # Update persistent cookie data.
if response.cookies: if response.cookies:
self.cookies.update(response.cookies) self.cookies.update(response.cookies)
return response
finally:
signals.template_rendered.disconnect(dispatch_uid="template-render")
got_request_exception.disconnect(dispatch_uid="request-exception")
return response
def get(self, path, data={}, follow=False, **extra): def get(self, path, data={}, follow=False, **extra):
""" """