﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
8136	Edge case: AttributeError from test client masks underlying exception	Dan Fairs	nobody	"Using Django svn r8223. In brief: if a 404 error occurs during a request using the Django test client, and rendering that 404 itself raises an exception (handled by handle_uncaught_exception in handlers/base.py, line 115), and there's no 500.html file, then signals.got_request_exception is never fired, meaning that exc_info in the Django test client (client.py, line 225) is not populated. This causes an AttributeError when response is referred to a few lines later, masking the actual error.

More detail:

My app has a 404.html defined, with errors, but no 500.html file. I have a 404 error in my app, which is exposed using the Django test client. The project is configured in debug mode. The code path through django.core.handlers.base passes through here (lines 106-115 of base.py):


{{{
        except http.Http404, e:
            if settings.DEBUG:
                from django.views import debug
                return debug.technical_404_response(request, e)
            else:
                try:
                    callback, param_dict = resolver.resolve404()
                    return callback(request, **param_dict)
                except:
                    return self.handle_uncaught_exception(request, resolver, sys.exc_info())

}}}

In this case, callback is a function, page_not_found. This itself ends up raising an exception, due to a syntax error in my 404.html. This is handled by self.handle_uncaught_exception. In my case, this again throws an exception, a TemplateDoesNotExist due to the missing 500.html (so the exception args is set to ('500.html',), and the exception isn't re-raised). The got_request_exception signal is never fired; this means that the handler for this signal set up by the test client to capture the exception information is never executed and, as a side effect of this, the 'response' variable is never assigned, causing an attribute error:


{{{
        # Capture exceptions created by the handler.
        got_request_exception.connect(self.store_exc_info)

        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
        # exception data, then re-raise the signalled exception.
        # 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]

        # Save the client and request that stimulated the response.
        response.client = self


}}}


The shortly-to-be-attached patch (seems to) fix this, but I'm not sure what other consequences it may have.
"		closed	Testing framework	dev		fixed	test client exception signal attributeerror		Accepted	0	0	0	0	0	0
