[Zope-Checkins] SVN: Zope/trunk/ Merge c110187 from 2.12 branch, adding IPubBeforeStreaming event
Martin Aspeli
optilude at gmx.net
Fri Mar 26 09:31:11 EDT 2010
Log message for revision 110189:
Merge c110187 from 2.12 branch, adding IPubBeforeStreaming event
Changed:
U Zope/trunk/doc/CHANGES.rst
U Zope/trunk/src/ZPublisher/HTTPResponse.py
U Zope/trunk/src/ZPublisher/interfaces.py
U Zope/trunk/src/ZPublisher/pubevents.py
U Zope/trunk/src/ZPublisher/tests/testpubevents.py
U Zope/trunk/src/ZServer/HTTPResponse.py
U Zope/trunk/src/ZServer/tests/test_responses.py
-=-
Modified: Zope/trunk/doc/CHANGES.rst
===================================================================
--- Zope/trunk/doc/CHANGES.rst 2010-03-26 13:25:09 UTC (rev 110188)
+++ Zope/trunk/doc/CHANGES.rst 2010-03-26 13:31:10 UTC (rev 110189)
@@ -5,12 +5,92 @@
Change information for previous versions of Zope can be found in the
file HISTORY.txt.
-Zope 2.12.2 (unreleased)
+Zope 2.12.4 (Unreleased)
------------------------
Features Added
++++++++++++++
+- Updated packages:
+
+ - Acquisition = 2.13.1
+ - ExtensionClass = 2.13.0
+ - Persistence = 2.13.0
+
+- There is now an event ZPublisher.interfaces.IPubBeforeStreaming which will
+ be fired just before the first chunk of data is written to the response
+ stream when using the write() method on the response. This is the last
+ possible point at which response headers may be set in this case.
+
+Bugs Fixed
+++++++++++
+
+- Zope 3-style resource directories would throw an Unauthorized error when
+ trying to use restrictedTraverse() to reach a resource in a sub-directory
+ of the resource directory.
+
+- Restore ability to traverse to 'macros' on template-based browser views.
+
+- Protect ZCTextIndex's clear method against storing Acquisition wrappers.
+
+- LP #195761: fixed ZMI XML export / import and restored it to the UI.
+
+- MailHost should fall back to HELO when EHLO fails.
+
+Zope 2.12.3 (2010/01/12)
+------------------------
+
+Bugs Fixed
+++++++++++
+
+- LP #491224: proper escaping of rendered error message
+
+- LP #246983: Enabled unicode conflict resolution on variables inside "string:"
+ expressions in TALES.
+
+- Fixed possible TypeError while sending multipart emails.
+
+- Also look for ZEXP imports within the clienthome directory. This
+ provides a place to put imports that won't be clobbered by buildout
+ in a buildout-based Zope instance.
+
+- Fixed a SyntaxError in utilities/load_site.py script.
+
+Features Added
+++++++++++++++
+
+- Made OFS.Image.File and OFS.Image.Image send IObjectModifiedEvent when
+ created through their factories and modified through the ZMI forms
+ (manage_edit() and manage_upload()).
+
+- Moved zope.formlib / zope.app.form integration into a separate package
+ called five.formlib.
+
+Zope 2.12.2 (2009-12-22)
+------------------------
+
+Features Added
+++++++++++++++
+
+- Updated packages:
+
+ - ZODB3 = 3.9.4
+ - docutils = 0.6
+ - pytz = 2009r
+ - zope.dottedname = 3.4.6
+ - zope.i18n = 3.7.2
+ - zope.interface = 3.5.3
+ - zope.minmax = 1.1.1
+ - zope.security = 3.7.2
+ - zope.session = 3.9.2
+ - zope.tal = 3.5.2
+
+- Enhanced the internals of the DateRangeIndex based on an idea from
+ experimental.daterangeindexoptimisations, thanks to Matt Hamilton.
+
+- Updated the default value for ``management_page_charset`` from iso-8859-1
+ to the nowadays more standard utf-8.
+
- Added IPubBeforeAbort event to mirror IPubBeforeCommit in failure scenarios.
This event is fired just before IPubFailure, but, crucially, while the
transaction is still open.
@@ -24,9 +104,26 @@
Bugs Fixed
++++++++++
+- LP #143444: add labels to checkboxes / radio buttons on import /
+ export form.
+
+- LP #496941: Remove all mention of ``standard_html_header`` and
+ ``standard_html_footer`` from default DTML content.
+
+- Fixed a regression in Products.PageTemplates that meant filesystem templates
+ using Products.Five.browser.pagetemplatefile would treat TALES path
+ expressions (but not python expressions) as protected code and so attempt
+ to apply security. See original issue here:
+ http://codespeak.net/pipermail/z3-five/2007q2/002185.html
+
+- LP #491249: fix tabindex on ZRDB connection test form.
+
+- LP #490514: preserve tainting when calling into DTML from ZPT.
+
- Avoid possible errors on test tear-down in Products.Five.fiveconfigure's
cleanUp() function if Products.meta_types has not been set
+
Zope 2.12.1 (2009/11/02)
------------------------
Modified: Zope/trunk/src/ZPublisher/HTTPResponse.py
===================================================================
--- Zope/trunk/src/ZPublisher/HTTPResponse.py 2010-03-26 13:25:09 UTC (rev 110188)
+++ Zope/trunk/src/ZPublisher/HTTPResponse.py 2010-03-26 13:31:10 UTC (rev 110189)
@@ -18,10 +18,12 @@
import types, os, sys, re
import zlib, struct
from string import translate, maketrans
+from zope.event import notify
from BaseResponse import BaseResponse
from zExceptions import Unauthorized, Redirect
from zExceptions.ExceptionFormatter import format_exception
from ZPublisher import BadRequest, InternalError, NotFound
+from ZPublisher.pubevents import PubBeforeStreaming
from cgi import escape
from urllib import quote
@@ -921,6 +923,9 @@
"""
if not self._wrote:
+
+ notify(PubBeforeStreaming(self))
+
self.outputBody()
self._wrote = 1
self.stdout.flush()
Modified: Zope/trunk/src/ZPublisher/interfaces.py
===================================================================
--- Zope/trunk/src/ZPublisher/interfaces.py 2010-03-26 13:25:09 UTC (rev 110188)
+++ Zope/trunk/src/ZPublisher/interfaces.py 2010-03-26 13:31:10 UTC (rev 110189)
@@ -50,3 +50,11 @@
"""
exc_info = Attribute('''The exception info as returned by 'sys.exc_info()'.''')
retry = Attribute('Whether the request will be retried')
+
+class IPubBeforeStreaming(Interface):
+ """Event fired just before a streaming response is initiated, i.e. when
+ something calls response.write() for the first time. Note that this is
+ carries a reference to the *response*, not the request.
+ """
+
+ response = Attribute(u"The current HTTP response")
Modified: Zope/trunk/src/ZPublisher/pubevents.py
===================================================================
--- Zope/trunk/src/ZPublisher/pubevents.py 2010-03-26 13:25:09 UTC (rev 110188)
+++ Zope/trunk/src/ZPublisher/pubevents.py 2010-03-26 13:31:10 UTC (rev 110189)
@@ -10,7 +10,8 @@
from zope.interface import implements
from interfaces import IPubStart, IPubSuccess, IPubFailure, \
- IPubAfterTraversal, IPubBeforeCommit, IPubBeforeAbort
+ IPubAfterTraversal, IPubBeforeCommit, IPubBeforeAbort, \
+ IPubBeforeStreaming
class _Base(object):
"""PubEvent base class."""
@@ -49,3 +50,11 @@
def __init__(self, request, exc_info, retry):
self.request, self.exc_info, self.retry = request, exc_info, retry
+
+class PubBeforeStreaming(object):
+ """Notified immediately before streaming via response.write() commences
+ """
+ implements(IPubBeforeStreaming)
+
+ def __init__(self, response):
+ self.response = response
Modified: Zope/trunk/src/ZPublisher/tests/testpubevents.py
===================================================================
--- Zope/trunk/src/ZPublisher/tests/testpubevents.py 2010-03-26 13:25:09 UTC (rev 110188)
+++ Zope/trunk/src/ZPublisher/tests/testpubevents.py 2010-03-26 13:31:10 UTC (rev 110189)
@@ -1,3 +1,4 @@
+from StringIO import StringIO
from sys import modules, exc_info
from unittest import TestCase, TestSuite, makeSuite, main
@@ -7,11 +8,14 @@
from ZPublisher.Publish import publish, Retry
from ZPublisher.BaseRequest import BaseRequest
+from ZPublisher.HTTPResponse import HTTPResponse
from ZPublisher.pubevents import PubStart, PubSuccess, PubFailure, \
- PubAfterTraversal, PubBeforeCommit, PubBeforeAbort
+ PubAfterTraversal, PubBeforeCommit, PubBeforeAbort, \
+ PubBeforeStreaming
from ZPublisher.interfaces import \
IPubStart, IPubEnd, IPubSuccess, IPubFailure, \
- IPubAfterTraversal, IPubBeforeCommit
+ IPubAfterTraversal, IPubBeforeCommit, \
+ IPubBeforeStreaming
PUBMODULE = 'TEST_testpubevents'
@@ -41,7 +45,10 @@
def testBeforeCommit(self):
e = PubBeforeCommit(_Request())
verifyObject(IPubBeforeCommit, e)
-
+
+ def testBeforeStreaming(self):
+ e = PubBeforeStreaming(_Response())
+ verifyObject(IPubBeforeStreaming, e)
class TestPubEvents(TestCase):
def setUp(self):
@@ -127,6 +134,21 @@
self.assert_(isinstance(events[5], PubBeforeCommit))
self.assert_(isinstance(events[6], PubSuccess))
+ def testStreaming(self):
+
+ out = StringIO()
+ response = HTTPResponse(stdout=out)
+ response.write('datachunk1')
+ response.write('datachunk2')
+
+ events = self.reporter.events
+ self.assertEqual(len(events), 1)
+ self.assert_(isinstance(events[0], PubBeforeStreaming))
+ self.assertEqual(events[0].response, response)
+
+ self.failUnless('datachunk1datachunk2' in out.getvalue())
+
+
# Auxiliaries
def _succeed():
''' '''
Modified: Zope/trunk/src/ZServer/HTTPResponse.py
===================================================================
--- Zope/trunk/src/ZServer/HTTPResponse.py 2010-03-26 13:25:09 UTC (rev 110188)
+++ Zope/trunk/src/ZServer/HTTPResponse.py 2010-03-26 13:31:10 UTC (rev 110189)
@@ -20,8 +20,10 @@
import time, re, sys, tempfile
from cStringIO import StringIO
import thread
+from zope.event import notify
from ZPublisher.HTTPResponse import HTTPResponse
from ZPublisher.Iterators import IStreamIterator
+from ZPublisher.pubevents import PubBeforeStreaming
from medusa.http_date import build_http_date
from PubCore.ZEvent import Wakeup
from medusa.producers import hooked_producer
@@ -165,6 +167,9 @@
stdout=self.stdout
if not self._wrote:
+
+ notify(PubBeforeStreaming(self))
+
l=self.headers.get('content-length', None)
if l is not None:
try:
Modified: Zope/trunk/src/ZServer/tests/test_responses.py
===================================================================
--- Zope/trunk/src/ZServer/tests/test_responses.py 2010-03-26 13:25:09 UTC (rev 110188)
+++ Zope/trunk/src/ZServer/tests/test_responses.py 2010-03-26 13:31:10 UTC (rev 110189)
@@ -19,17 +19,21 @@
from ZServer.PCGIServer import PCGIResponse
from ZServer.FCGIServer import FCGIResponse
from ZPublisher.Iterators import IStreamIterator
+from ZPublisher.pubevents import PubBeforeStreaming
from zope.interface import implements
import unittest
from cStringIO import StringIO
+from zope.event import subscribers
+
+
class ZServerResponseTestCase(unittest.TestCase):
"""Test ZServer response objects."""
def test_http_response_write_unicode(self):
response = ZServerHTTPResponse()
self.assertRaises(TypeError, response.write, u'bad')
-
+
def test_ftp_response_write_unicode(self):
response = FTPResponse()
self.assertRaises(TypeError, response.write, u'bad')
@@ -57,7 +61,7 @@
one = ZServerHTTPResponse(stdout=DummyChannel())
self.assertRaises(AssertionError,
one.setBody, test_streamiterator())
-
+
class DummyChannel:
def __init__(self):
self.out = StringIO()
@@ -267,12 +271,39 @@
'',
''))
+class _Reporter(object):
+ def __init__(self): self.events = []
+ def __call__(self, event): self.events.append(event)
+class ZServerHTTPResponseEventsTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._saved_subscribers = subscribers[:]
+ self.reporter = r = _Reporter()
+ subscribers[:] = [r]
+
+ def tearDown(self):
+ subscribers[:] = self._saved_subscribers
+
+ def testStreaming(self):
+ out = StringIO()
+ response = ZServerHTTPResponse(stdout=out)
+ response.write('datachunk1')
+ response.write('datachunk2')
+
+ events = self.reporter.events
+ self.assertEqual(len(events), 1)
+ self.assert_(isinstance(events[0], PubBeforeStreaming))
+ self.assertEqual(events[0].response, response)
+
+ self.failUnless('datachunk1datachunk2' in out.getvalue())
+
def test_suite():
suite = unittest.TestSuite()
suite.addTests((
unittest.makeSuite(ZServerResponseTestCase),
- unittest.makeSuite(ZServerHTTPResponseTestCase)
+ unittest.makeSuite(ZServerHTTPResponseTestCase),
+ unittest.makeSuite(ZServerHTTPResponseEventsTestCase)
))
return suite
More information about the Zope-Checkins
mailing list