Commit 558b5452 authored by Tres Seaver's avatar Tres Seaver

Merge branch 'gweis-2.13' into 2.13

parents b3f2cf76 c0aae342
......@@ -8,6 +8,11 @@ http://docs.zope.org/zope2/
2.13.23 (unreleased)
--------------------
- Issue #27: Fix publishing of ``ZPublisher.Iterators.IStreamIterator`` under
WSGI. This interface does not have ``seek`` or ``tell``. Introduce
``ZPublisher.Iterators.IUnboundStreamIterator`` to support publishing
iterators of unknown length under WSGI.
- Document running Zope as a WSGI application. See
https://github.com/zopefoundation/Zope/issues/30
......
from zope.interface import Interface
from zope.interface import implements
class IStreamIterator(Interface):
class IUnboundStreamIterator(Interface):
"""
An iterator that can be published.
An iterator with unknown length that can be published.
"""
def next():
"""
Return a sequence of bytes out of the bytestream, or raise
StopIeration if we've reached the end of the bytestream.
"""
class IStreamIterator(IUnboundStreamIterator):
"""
An iterator with known length that can be published.
IStreamIterators must not read from the object database.
After the application finishes interpreting a request and
......@@ -15,12 +27,6 @@ class IStreamIterator(Interface):
but it has a chance of going insane if it happens to be loading
or storing something in the other thread at the same time. """
def next():
"""
Return a sequence of bytes out of the bytestream, or raise
StopIeration if we've reached the end of the bytestream.
"""
def __len__():
"""
Return an integer representing the length of the object
......
......@@ -32,7 +32,7 @@ from ZPublisher.Publish import dont_publish_class
from ZPublisher.Publish import get_module_info
from ZPublisher.Publish import missing_name
from ZPublisher.pubevents import PubStart, PubBeforeCommit, PubAfterTraversal
from ZPublisher.Iterators import IStreamIterator
from ZPublisher.Iterators import IUnboundStreamIterator, IStreamIterator
_NOW = None # overwrite for testing
def _now():
......@@ -131,12 +131,19 @@ class WSGIResponse(HTTPResponse):
self.stdout.write(data)
def setBody(self, body, title='', is_error=0):
if isinstance(body, file) or IStreamIterator.providedBy(body):
if isinstance(body, file):
body.seek(0, 2)
length = body.tell()
body.seek(0)
self.setHeader('Content-Length', '%d' % length)
self.body = body
elif IStreamIterator.providedBy(body):
self.body = body
HTTPResponse.setBody(self, '', title, is_error)
elif IUnboundStreamIterator.providedBy(body):
self.body = body
self._streaming = 1
HTTPResponse.setBody(self, '', title, is_error)
else:
HTTPResponse.setBody(self, body, title, is_error)
......
......@@ -136,6 +136,57 @@ class WSGIResponseTests(unittest.TestCase):
time.gmtime(time.mktime(WHEN)))
self.assertTrue(('Date', whenstr) in headers)
def test_setBody_IUnboundStreamIterator(self):
from ZPublisher.Iterators import IUnboundStreamIterator
from zope.interface import implements
class test_streamiterator:
implements(IUnboundStreamIterator)
data = "hello"
done = 0
def next(self):
if not self.done:
self.done = 1
return self.data
raise StopIteration
response = self._makeOne()
response.setStatus(200)
body = test_streamiterator()
response.setBody(body)
response.finalize()
self.assertTrue(body is response.body)
self.assertEqual(response._streaming, 1)
def test_setBody_IStreamIterator(self):
from ZPublisher.Iterators import IStreamIterator
from zope.interface import implements
class test_streamiterator:
implements(IStreamIterator)
data = "hello"
done = 0
def next(self):
if not self.done:
self.done = 1
return self.data
raise StopIteration
def __len__(self):
return len(self.data)
response = self._makeOne()
response.setStatus(200)
body = test_streamiterator()
response.setBody(body)
response.finalize()
self.assertTrue(body is response.body)
self.assertEqual(response._streaming, 0)
self.assertEqual(response.getHeader('Content-Length'),
'%d' % len(test_streamiterator.data))
#def test___str__already_wrote_not_chunking(self):
# response = self._makeOne()
# response._wrote = True
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment