web/lib/django/test/client.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
--- a/web/lib/django/test/client.py	Wed May 19 17:43:59 2010 +0200
+++ b/web/lib/django/test/client.py	Tue May 25 02:43:45 2010 +0200
@@ -66,6 +66,11 @@
         signals.request_started.send(sender=self.__class__)
         try:
             request = WSGIRequest(environ)
+            # sneaky little hack so that we can easily get round
+            # CsrfViewMiddleware.  This makes life easier, and is probably
+            # required for backwards compatibility with external tests against
+            # admin views.
+            request._dont_enforce_csrf_checks = True
             response = self.get_response(request)
 
             # Apply response middleware.
@@ -193,7 +198,7 @@
         using the arguments to the request.
         """
         environ = {
-            'HTTP_COOKIE':      self.cookies,
+            'HTTP_COOKIE':       self.cookies.output(header='', sep='; '),
             'PATH_INFO':         '/',
             'QUERY_STRING':      '',
             'REMOTE_ADDR':       '127.0.0.1',
@@ -216,53 +221,57 @@
         # callback function.
         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.
-        got_request_exception.connect(self.store_exc_info)
-
+        got_request_exception.connect(self.store_exc_info, dispatch_uid="request-exception")
         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
+
+            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]
 
-        # 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
-        response.request = request
+            # Save the client and request that stimulated the response.
+            response.client = self
+            response.request = request
 
-        # Add any rendered template detail to the response.
-        # If there was only one template rendered (the most likely case),
-        # 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]);
+            # Add any rendered template detail to the response.
+            # If there was only one template rendered (the most likely case),
+            # 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:
-                    setattr(response, detail, data[detail])
-            else:
-                setattr(response, detail, None)
+                    setattr(response, detail, None)
+
+            # Update persistent cookie data.
+            if response.cookies:
+                self.cookies.update(response.cookies)
 
-        # Update persistent cookie data.
-        if 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):
         """
@@ -362,12 +371,18 @@
         else:
             post_data = data
 
+        # Make `data` into a querystring only if it's not already a string. If
+        # it is a string, we'll assume that the caller has already encoded it.
+        query_string = None
+        if not isinstance(data, basestring):
+            query_string = urlencode(data, doseq=True)
+
         parsed = urlparse(path)
         r = {
             'CONTENT_LENGTH': len(post_data),
             'CONTENT_TYPE':   content_type,
             'PATH_INFO':      urllib.unquote(parsed[2]),
-            'QUERY_STRING':   urlencode(data, doseq=True) or parsed[4],
+            'QUERY_STRING':   query_string or parsed[4],
             'REQUEST_METHOD': 'PUT',
             'wsgi.input':     FakePayload(post_data),
         }
@@ -417,6 +432,9 @@
                 request.session = engine.SessionStore()
             login(request, user)
 
+            # Save the session values.
+            request.session.save()
+
             # Set the cookie to represent the session.
             session_cookie = settings.SESSION_COOKIE_NAME
             self.cookies[session_cookie] = request.session.session_key
@@ -429,9 +447,6 @@
             }
             self.cookies[session_cookie].update(cookie_data)
 
-            # Save the session values.
-            request.session.save()
-
             return True
         else:
             return False
@@ -459,11 +474,15 @@
             redirect_chain = response.redirect_chain
             redirect_chain.append((url, response.status_code))
 
+            extra = {}
+            if scheme:
+                extra['wsgi.url_scheme'] = scheme
+
             # The test client doesn't handle external links,
             # but since the situation is simulated in test_client,
             # we fake things here by ignoring the netloc portion of the
             # redirected URL.
-            response = self.get(path, QueryDict(query), follow=False)
+            response = self.get(path, QueryDict(query), follow=False, **extra)
             response.redirect_chain = redirect_chain
 
             # Prevent loops