Browse Source

Fixed #20864 -- Made the test client use common method for performing requests.

Krzysztof Jurewicz 11 years ago
parent
commit
4eeb8ec147
2 changed files with 27 additions and 37 deletions
  1. 1 0
      AUTHORS
  2. 26 37
      django/test/client.py

+ 1 - 0
AUTHORS

@@ -317,6 +317,7 @@ answer newbie questions, and generally made Django that much better:
     Michael Josephson <http://www.sdjournal.com/>
     jpellerin@gmail.com
     junzhang.jn@gmail.com
+    Krzysztof Jurewicz <krzysztof.jurewicz@gmail.com>
     Xia Kai <http://blog.xiaket.org/>
     Antti Kaihola <http://djangopeople.net/akaihola/>
     Peter van Kampen

+ 26 - 37
django/test/client.py

@@ -37,6 +37,7 @@ BOUNDARY = 'BoUnDaRyStRiNg'
 MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
 CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')
 
+
 class FakePayload(object):
     """
     A wrapper around BytesIO that restricts what can be read since data from
@@ -123,6 +124,7 @@ class ClientHandler(BaseHandler):
 
         return response
 
+
 def store_rendered_templates(store, signal, sender, template, context, **kwargs):
     """
     Stores templates and contexts that are rendered.
@@ -133,6 +135,7 @@ def store_rendered_templates(store, signal, sender, template, context, **kwargs)
     store.setdefault('templates', []).append(template)
     store.setdefault('context', ContextList()).append(copy(context))
 
+
 def encode_multipart(boundary, data):
     """
     Encodes multipart POST data from a dictionary of form values.
@@ -178,6 +181,7 @@ def encode_multipart(boundary, data):
     ])
     return b'\r\n'.join(lines)
 
+
 def encode_file(boundary, key, file):
     to_bytes = lambda s: force_bytes(s, settings.DEFAULT_CHARSET)
     if hasattr(file, 'content_type'):
@@ -189,8 +193,8 @@ def encode_file(boundary, key, file):
         content_type = 'application/octet-stream'
     return [
         to_bytes('--%s' % boundary),
-        to_bytes('Content-Disposition: form-data; name="%s"; filename="%s"' \
-            % (key, os.path.basename(file.name))),
+        to_bytes('Content-Disposition: form-data; name="%s"; filename="%s"'
+                 % (key, os.path.basename(file.name))),
         to_bytes('Content-Type: %s' % content_type),
         b'',
         file.read()
@@ -274,14 +278,11 @@ class RequestFactory(object):
     def get(self, path, data={}, **extra):
         "Construct a GET request."
 
-        parsed = urlparse(path)
         r = {
-            'PATH_INFO':       self._get_path(parsed),
-            'QUERY_STRING':    urlencode(data, doseq=True) or force_str(parsed[4]),
-            'REQUEST_METHOD':  str('GET'),
+            'QUERY_STRING': urlencode(data, doseq=True),
         }
         r.update(extra)
-        return self.request(**r)
+        return self.generic('GET', path, **r)
 
     def post(self, path, data={}, content_type=MULTIPART_CONTENT,
              **extra):
@@ -289,32 +290,19 @@ class RequestFactory(object):
 
         post_data = self._encode_data(data, content_type)
 
-        parsed = urlparse(path)
-        r = {
-            'CONTENT_LENGTH': len(post_data),
-            'CONTENT_TYPE':   content_type,
-            'PATH_INFO':      self._get_path(parsed),
-            'QUERY_STRING':   force_str(parsed[4]),
-            'REQUEST_METHOD': str('POST'),
-            'wsgi.input':     FakePayload(post_data),
-        }
-        r.update(extra)
-        return self.request(**r)
+        return self.generic('POST', path, post_data, content_type, **extra)
 
     def head(self, path, data={}, **extra):
         "Construct a HEAD request."
 
-        parsed = urlparse(path)
         r = {
-            'PATH_INFO':       self._get_path(parsed),
-            'QUERY_STRING':    urlencode(data, doseq=True) or force_str(parsed[4]),
-            'REQUEST_METHOD':  str('HEAD'),
+            'QUERY_STRING': urlencode(data, doseq=True),
         }
         r.update(extra)
-        return self.request(**r)
+        return self.generic('HEAD', path, **r)
 
     def options(self, path, data='', content_type='application/octet-stream',
-            **extra):
+                **extra):
         "Construct an OPTIONS request."
         return self.generic('OPTIONS', path, data, content_type, **extra)
 
@@ -324,22 +312,22 @@ class RequestFactory(object):
         return self.generic('PUT', path, data, content_type, **extra)
 
     def patch(self, path, data='', content_type='application/octet-stream',
-            **extra):
+              **extra):
         "Construct a PATCH request."
         return self.generic('PATCH', path, data, content_type, **extra)
 
     def delete(self, path, data='', content_type='application/octet-stream',
-            **extra):
+               **extra):
         "Construct a DELETE request."
         return self.generic('DELETE', path, data, content_type, **extra)
 
     def generic(self, method, path,
                 data='', content_type='application/octet-stream', **extra):
+        """Constructs an arbitrary HTTP request."""
         parsed = urlparse(path)
         data = force_bytes(data, settings.DEFAULT_CHARSET)
         r = {
             'PATH_INFO':      self._get_path(parsed),
-            'QUERY_STRING':   force_str(parsed[4]),
             'REQUEST_METHOD': str(method),
         }
         if data:
@@ -349,8 +337,12 @@ class RequestFactory(object):
                 'wsgi.input':     FakePayload(data),
             })
         r.update(extra)
+        # If QUERY_STRING is absent or empty, we want to extract it from the URL.
+        if not r.get('QUERY_STRING'):
+            r['QUERY_STRING'] = force_str(parsed[4])
         return self.request(**r)
 
+
 class Client(RequestFactory):
     """
     A class that can act as a client for testing purposes.
@@ -392,7 +384,6 @@ class Client(RequestFactory):
         return {}
     session = property(_session)
 
-
     def request(self, **request):
         """
         The master request method. Composes the environment dictionary
@@ -485,12 +476,11 @@ class Client(RequestFactory):
         return response
 
     def options(self, path, data='', content_type='application/octet-stream',
-            follow=False, **extra):
+                follow=False, **extra):
         """
         Request a response from the server using OPTIONS.
         """
-        response = super(Client, self).options(path,
-                data=data, content_type=content_type, **extra)
+        response = super(Client, self).options(path, data=data, content_type=content_type, **extra)
         if follow:
             response = self._handle_redirects(response, **extra)
         return response
@@ -500,14 +490,13 @@ class Client(RequestFactory):
         """
         Send a resource to the server using PUT.
         """
-        response = super(Client, self).put(path,
-                data=data, content_type=content_type, **extra)
+        response = super(Client, self).put(path, data=data, content_type=content_type, **extra)
         if follow:
             response = self._handle_redirects(response, **extra)
         return response
 
     def patch(self, path, data='', content_type='application/octet-stream',
-            follow=False, **extra):
+              follow=False, **extra):
         """
         Send a resource to the server using PATCH.
         """
@@ -518,12 +507,12 @@ class Client(RequestFactory):
         return response
 
     def delete(self, path, data='', content_type='application/octet-stream',
-            follow=False, **extra):
+               follow=False, **extra):
         """
         Send a DELETE request to the server.
         """
-        response = super(Client, self).delete(path,
-                data=data, content_type=content_type, **extra)
+        response = super(Client, self).delete(
+            path, data=data, content_type=content_type, **extra)
         if follow:
             response = self._handle_redirects(response, **extra)
         return response