Commits

Anonymous committed cdad978

[soc2009/http-wsgi-improvements] Expects content to be iterable throughout ``HttpResponse``, with regression tests. HttpResponse.close() is now a no-op. Thanks daonb and stugots!

Passes the test suite.

Comments (0)

Files changed (5)

     Matt Dennenbaum
     deric@monowerks.com
     Max Derkachev <mderk@yandex.ru>
+    John DeRosa <stugots@qwest.net>
     Rajesh Dhawan <rajesh.dhawan@gmail.com>
     Sander Dijkhuis <sander.dijkhuis@gmail.com>
     Jordan Dimov <s3x3y1@gmail.com>

django/http/__init__.py

     _charset = settings.DEFAULT_CHARSET
 
     def __init__(self, content='', mimetype=None, status=None,
-            content_type=None, request=None):
+                 content_type=None, request=None):
         from django.conf import settings
         accept_charset = None
         if mimetype:
         if not content_type:
             content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE,
                     self._charset)
-        if not isinstance(content, basestring) and hasattr(content, '__iter__'):
-            self._container = content
-            self._is_string = False
-        else:
-            self._container = [content]
-            self._is_string = True
+        self._container = [''.join(content)]
+        if hasattr(content, 'close'):
+            content.close()
         self.cookies = SimpleCookie()
         if status:
             self.status_code = status
-
         # _headers is a mapping of the lower-case name to the original case of
         # the header (required for working with legacy systems) and the header
         # value.
 
     def __str__(self):
         """Full HTTP message, including headers."""
-        return '\n'.join(['%s: %s' % (key, value)
-            for key, value in self._headers.values()]) \
-            + '\n\n' + self.content
+        headers = ['%s: %s' % (k, v) for k, v in self._headers.values()]
+        return '\n'.join(headers) + '\n\n' + self.content
 
     def _convert_to_ascii(self, *values):
         """Converts all values to ascii strings."""
         return smart_str(''.join(self._container), self._codec.name)
 
     def _set_content(self, value):
-        self._container = [value]
-        self._is_string = True
+        self._container = [''.join(value)]
 
     content = property(_get_content, _set_content)
 
         return str(chunk)
 
     def close(self):
-        if hasattr(self._container, 'close'):
-            self._container.close()
+        "No-op that remains for backwards compatibility. Ref #6527"
+        pass
 
     # The remaining methods partially implement the file-like object interface.
     # See http://docs.python.org/lib/bltin-file-objects.html
     def write(self, content):
-        if not self._is_string:
-            raise Exception("This %s instance is not writable" % self.__class__)
         self._container.append(content)
 
     def flush(self):
         pass
 
     def tell(self):
-        if not self._is_string:
-            raise Exception("This %s instance cannot tell its position" % self.__class__)
         return sum([len(chunk) for chunk in self._container])
 
 class HttpResponseSendFile(HttpResponse): 

docs/ref/request-response.txt

 ~~~~~~~~~~~~~~~~~
 
 Finally, you can pass ``HttpResponse`` an iterator rather than passing it
-hard-coded strings. If you use this technique, follow these guidelines:
+hard-coded strings. If you use this technique, note the following:
 
     * The iterator should return strings.
-    * If an :class:`HttpResponse` has been initialized with an iterator as its
-      content, you can't use the class:`HttpResponse` instance as a file-like
-      object. Doing so will raise ``Exception``.
+    * ``HttpResponse.__init__()`` will read and store the iterator's contents.
 
 Setting headers
 ~~~~~~~~~~~~~~~

tests/regressiontests/httpwrappers/helloworld.txt

+Hello world.

tests/regressiontests/httpwrappers/tests.py

 >>> x.update(y)
 >>> x.getlist('a')
 [u'1', u'2', u'3', u'4']
+
+######################################
+# HttpResponse with iterable content #
+######################################
+
+>>> from django.http import HttpResponse
+>>> response = HttpResponse(file('regressiontests/httpwrappers/helloworld.txt','r'))
+>>> print response
+Content-Type: text/html; charset=utf-8
+<BLANKLINE>
+Hello world.
+<BLANKLINE>
+
+>>> print response
+Content-Type: text/html; charset=utf-8
+<BLANKLINE>
+Hello world.
+<BLANKLINE>
+
+>>> print response
+Content-Type: text/html; charset=utf-8
+<BLANKLINE>
+Hello world.
+<BLANKLINE>
+
+>>> response = HttpResponse("abc")
+>>> print response
+Content-Type: text/html; charset=utf-8
+<BLANKLINE>
+abc
+>>> print response
+Content-Type: text/html; charset=utf-8
+<BLANKLINE>
+abc
+>>> print response
+Content-Type: text/html; charset=utf-8
+<BLANKLINE>
+abc
+
 """
 
 from django.http import QueryDict, HttpResponse