Commits

mtre...@bcc190cf-cafb-0310-a4f2-bffc1f526a37  committed 6419427

Fixed #2560 -- Add close() support to HttpResponse iterators. Thanks, Ivan
Sagalaev.

  • Participants
  • Parent commits e80a6e6

Comments (0)

Files changed (3)

File django/core/handlers/modpython.py

     for c in http_response.cookies.values():
         mod_python_req.headers_out.add('Set-Cookie', c.output(header=''))
     mod_python_req.status = http_response.status_code
-    for chunk in http_response.iterator:
-        mod_python_req.write(chunk)
+    try:
+        for chunk in http_response:
+            mod_python_req.write(chunk)
+    finally:
+        http_response.close()
 
 def handler(req):
     # mod_python hooks into this function.

File django/core/handlers/wsgi.py

         for c in response.cookies.values():
             response_headers.append(('Set-Cookie', c.output(header='')))
         start_response(status, response_headers)
-        return response.iterator
+        return response

File django/http/__init__.py

         if not mimetype:
             mimetype = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE, settings.DEFAULT_CHARSET)
         if hasattr(content, '__iter__'):
-            self._iterator = content
+            self._container = content
             self._is_string = False
         else:
-            self._iterator = [content]
+            self._container = [content]
             self._is_string = True
         self.headers = {'Content-Type': mimetype}
         self.cookies = SimpleCookie()
         self.cookies[key]['max-age'] = 0
 
     def _get_content(self):
-        content = ''.join(self._iterator)
+        content = ''.join(self._container)
         if isinstance(content, unicode):
             content = content.encode(self._charset)
         return content
 
     def _set_content(self, value):
-        self._iterator = [value]
+        self._container = [value]
         self._is_string = True
 
     content = property(_get_content, _set_content)
 
-    def _get_iterator(self):
-        "Output iterator. Converts data into client charset if necessary."
-        for chunk in self._iterator:
-            if isinstance(chunk, unicode):
-                chunk = chunk.encode(self._charset)
-            yield chunk
+    def __iter__(self):
+        self._iterator = self._container.__iter__()
+        return self
 
-    iterator = property(_get_iterator)
+    def next(self):
+        chunk = self._iterator.next()
+        if isinstance(chunk, unicode):
+            chunk = chunk.encode(self._charset)
+        return chunk
+
+    def close(self):
+        if hasattr(self._container, 'close'):
+            self._container.close()
 
     # 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._iterator.append(content)
+        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._iterator])
+        return sum([len(chunk) for chunk in self._container])
 
 class HttpResponseRedirect(HttpResponse):
     def __init__(self, redirect_to):