1
0
mirror of https://github.com/django/django.git synced 2025-07-04 01:39:20 +00:00

[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.

git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/http-wsgi-improvements@11262 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Chris Cahoon 2009-07-17 11:48:08 +00:00
parent 3e5ab0b8ec
commit 88b1183425
5 changed files with 52 additions and 23 deletions

View File

@ -121,6 +121,7 @@ answer newbie questions, and generally made Django that much better:
Matt Dennenbaum Matt Dennenbaum
deric@monowerks.com deric@monowerks.com
Max Derkachev <mderk@yandex.ru> Max Derkachev <mderk@yandex.ru>
John DeRosa <stugots@qwest.net>
Rajesh Dhawan <rajesh.dhawan@gmail.com> Rajesh Dhawan <rajesh.dhawan@gmail.com>
Sander Dijkhuis <sander.dijkhuis@gmail.com> Sander Dijkhuis <sander.dijkhuis@gmail.com>
Jordan Dimov <s3x3y1@gmail.com> Jordan Dimov <s3x3y1@gmail.com>

View File

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

View File

@ -430,12 +430,10 @@ Passing iterators
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
Finally, you can pass ``HttpResponse`` an iterator rather than passing it 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. * The iterator should return strings.
* If an :class:`HttpResponse` has been initialized with an iterator as its * ``HttpResponse.__init__()`` will read and store the iterator's contents.
content, you can't use the class:`HttpResponse` instance as a file-like
object. Doing so will raise ``Exception``.
Setting headers Setting headers
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~

View File

@ -0,0 +1 @@
Hello world.

View File

@ -463,6 +463,45 @@ BadHeaderError: Header values can't contain newlines (got 'test\\nstr')
>>> x.update(y) >>> x.update(y)
>>> x.getlist('a') >>> x.getlist('a')
[u'1', u'2', u'3', u'4'] [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 from django.http import QueryDict, HttpResponse