[Checkins] SVN: ZPublisherEventsBackport/trunk/s ZPublisher events for Zope 2.10
Laurence Rowe
l at lrowe.co.uk
Fri Oct 23 07:10:59 EDT 2009
Log message for revision 105240:
ZPublisher events for Zope 2.10
Changed:
A ZPublisherEventsBackport/trunk/setup.py
A ZPublisherEventsBackport/trunk/src/
A ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/
A ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/__init__.py
A ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/configure.zcml
A ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/interfaces.py
A ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/patch.py
A ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/pubevents.py
-=-
Added: ZPublisherEventsBackport/trunk/setup.py
===================================================================
--- ZPublisherEventsBackport/trunk/setup.py (rev 0)
+++ ZPublisherEventsBackport/trunk/setup.py 2009-10-23 11:10:58 UTC (rev 105240)
@@ -0,0 +1,30 @@
+from setuptools import setup, find_packages
+import os.path
+
+version = '1.0'
+
+setup(
+ name='ZPublisherEventsBackport',
+ version=version,
+ description="Backport publication events from Zope 2.12 ZPublisher to Zope 2.10",
+ classifiers=[
+ "Programming Language :: Python",
+ "Environment :: Web Environment",
+ "Framework :: Zope2",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: Zope Public License",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ ],
+ keywords='',
+ url='',
+ author='Laurence Rowe',
+ author_email='laurence at lrowe.co.uk',
+ license='ZPL',
+ packages=find_packages('src'),
+ package_dir={'': 'src'},
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ ],
+ )
+
Added: ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/__init__.py
===================================================================
--- ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/__init__.py (rev 0)
+++ ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/__init__.py 2009-10-23 11:10:58 UTC (rev 105240)
@@ -0,0 +1,19 @@
+try:
+ import ZPublisher.interfaces
+except ImportError:
+ import logging
+ import sys
+ import ZPublisher
+ import ZPublisher.Publish
+ from ZPublisherEventsBackport import interfaces
+ sys.modules['ZPublisher.interfaces'] = interfaces
+ ZPublisher.interfaces = interfaces
+ for name, iface in interfaces.__dict__.items():
+ if name.startswith('IPub'):
+ iface.__module__ = 'ZPublisher.interfaces'
+ iface.__identifier__ = "%s.%s" % (iface.__module__, iface.__name__)
+ iface.changed(None)
+
+ from ZPublisherEventsBackport import patch
+ ZPublisher.Publish.publish=patch.publish
+ logging.info("Monkeypatch ZPublisher publish with publication events")
Added: ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/configure.zcml
===================================================================
--- ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/configure.zcml (rev 0)
+++ ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/configure.zcml 2009-10-23 11:10:58 UTC (rev 105240)
@@ -0,0 +1,3 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+ <!-- Stub so configure phase may trigger patch -->
+</configure>
Copied: ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/interfaces.py (from rev 105239, Zope/branches/2.12/src/ZPublisher/interfaces.py)
===================================================================
--- ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/interfaces.py (rev 0)
+++ ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/interfaces.py 2009-10-23 11:10:58 UTC (rev 105240)
@@ -0,0 +1,45 @@
+from zope.interface import Interface, Attribute
+
+#############################################################################
+# Publication events
+# These are events notified in 'ZPublisher.Publish.publish'.
+
+class IPubEvent(Interface):
+ '''Base class for publication events.
+
+ Publication events are notified in 'ZPublisher.Publish.publish' to
+ inform about publications (aka requests) and their fate.
+ '''
+ request = Attribute('The request being affected')
+
+class IPubStart(IPubEvent):
+ '''Event notified at the beginning of 'ZPublisher.Publish.publish'.'''
+
+class IPubEnd(IPubEvent):
+ '''Event notified after request processing.
+
+ Note that a retried request ends before the retrial, the retrial
+ itself is considered a new event.
+ '''
+
+class IPubSuccess(IPubEnd):
+ '''A successful request processing.'''
+
+class IPubFailure(IPubEnd):
+ '''A failed request processing.
+
+ Note: If a subscriber to 'IPubSuccess' raises an exception,
+ then 'IPubFailure' may be notified in addtion to 'IPubSuccess'.
+ '''
+ exc_info = Attribute('''The exception info as returned by 'sys.exc_info()'.''')
+ retry = Attribute('Whether the request will be retried')
+
+
+class IPubAfterTraversal(IPubEvent):
+ """notified after traversal and an (optional) authentication."""
+
+
+class IPubBeforeCommit(IPubEvent):
+ """notified immediately before the transaction commit (i.e. after the main
+ request processing is finished.
+ """
Copied: ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/patch.py (from rev 105239, Zope/branches/2.12/src/ZPublisher/Publish.py)
===================================================================
--- ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/patch.py (rev 0)
+++ ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/patch.py 2009-10-23 11:10:58 UTC (rev 105240)
@@ -0,0 +1,157 @@
+import logging
+import sys
+from ZPublisher.Publish import call_object
+from ZPublisher.Publish import missing_name
+from ZPublisher.Publish import dont_publish_class
+from ZPublisher.Publish import get_module_info
+from ZPublisher.Publish import Retry
+from ZPublisher.mapply import mapply
+from zExceptions import Redirect
+# XXX change from ZPublisher 2.12
+# from zope.publisher.interfaces import ISkinnable
+from zope.publisher.browser import setDefaultSkin
+from zope.security.management import newInteraction, endInteraction
+from zope.event import notify
+
+from pubevents import PubStart, PubSuccess, PubFailure, \
+ PubBeforeCommit, PubAfterTraversal
+
+
+def publish(request, module_name, after_list, debug=0,
+ # Optimize:
+ call_object=call_object,
+ missing_name=missing_name,
+ dont_publish_class=dont_publish_class,
+ mapply=mapply,
+ ):
+
+ (bobo_before, bobo_after, object, realm, debug_mode, err_hook,
+ validated_hook, transactions_manager)= get_module_info(module_name)
+
+ parents=None
+ response=None
+
+ try:
+ notify(PubStart(request))
+ # TODO pass request here once BaseRequest implements IParticipation
+ newInteraction()
+
+ request.processInputs()
+
+ request_get=request.get
+ response=request.response
+
+ # First check for "cancel" redirect:
+ if request_get('SUBMIT','').strip().lower()=='cancel':
+ cancel=request_get('CANCEL_ACTION','')
+ if cancel:
+ raise Redirect, cancel
+
+ after_list[0]=bobo_after
+ if debug_mode:
+ response.debug_mode=debug_mode
+ if realm and not request.get('REMOTE_USER',None):
+ response.realm=realm
+
+ if bobo_before is not None:
+ bobo_before()
+
+ # Get the path list.
+ # According to RFC1738 a trailing space in the path is valid.
+ path=request_get('PATH_INFO')
+
+ request['PARENTS']=parents=[object]
+
+ if transactions_manager:
+ transactions_manager.begin()
+
+ object=request.traverse(path, validated_hook=validated_hook)
+
+ notify(PubAfterTraversal(request))
+
+ if transactions_manager:
+ transactions_manager.recordMetaData(object, request)
+
+ result=mapply(object, request.args, request,
+ call_object,1,
+ missing_name,
+ dont_publish_class,
+ request, bind=1)
+
+ if result is not response:
+ response.setBody(result)
+
+ notify(PubBeforeCommit(request))
+
+ if transactions_manager:
+ transactions_manager.commit()
+ endInteraction()
+
+ notify(PubSuccess(request))
+
+ return response
+ except:
+ # save in order to give 'PubFailure' the original exception info
+ exc_info = sys.exc_info()
+ # DM: provide nicer error message for FTP
+ sm = None
+ if response is not None:
+ sm = getattr(response, "setMessage", None)
+
+ if sm is not None:
+ from asyncore import compact_traceback
+ cl,val= sys.exc_info()[:2]
+ sm('%s: %s %s' % (
+ getattr(cl,'__name__',cl), val,
+ debug_mode and compact_traceback()[-1] or ''))
+
+ if err_hook is not None:
+ retry = False
+ if parents:
+ parents=parents[0]
+ try:
+ try:
+ return err_hook(parents, request,
+ sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2],
+ )
+ except Retry:
+ if not request.supports_retry():
+ return err_hook(parents, request,
+ sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2],
+ )
+ retry = True
+ finally:
+ # Note: 'abort's can fail. Nevertheless, we want end request handling
+ try:
+ if transactions_manager:
+ transactions_manager.abort()
+ finally:
+ endInteraction()
+ notify(PubFailure(request, exc_info, retry))
+
+ # Only reachable if Retry is raised and request supports retry.
+ newrequest=request.retry()
+ request.close() # Free resources held by the request.
+
+ # Set the default layer/skin on the newly generated request
+ # XXX change from ZPublisher 2.12
+ # if ISkinnable.providedBy(newrequest):
+ setDefaultSkin(newrequest)
+ try:
+ return publish(newrequest, module_name, after_list, debug)
+ finally:
+ newrequest.close()
+
+ else:
+ # Note: 'abort's can fail. Nevertheless, we want end request handling
+ try:
+ if transactions_manager:
+ transactions_manager.abort()
+ finally:
+ endInteraction()
+ notify(PubFailure(request, exc_info, False))
+ raise
Copied: ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/pubevents.py (from rev 105239, Zope/branches/2.12/src/ZPublisher/pubevents.py)
===================================================================
--- ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/pubevents.py (rev 0)
+++ ZPublisherEventsBackport/trunk/src/ZPublisherEventsBackport/pubevents.py 2009-10-23 11:10:58 UTC (rev 105240)
@@ -0,0 +1,44 @@
+'''Publication events.
+
+They are notified in 'ZPublisher.Publish.publish' and
+inform about publications and their fate.
+
+Subscriptions can be used for all kinds of request supervision,
+e.g. request and error rate determination, writing high resolution logfiles
+for detailed time related analysis, inline request monitoring.
+'''
+from zope.interface import implements
+
+from interfaces import IPubStart, IPubSuccess, IPubFailure, \
+ IPubAfterTraversal, IPubBeforeCommit
+
+class _Base(object):
+ """PubEvent base class."""
+
+ def __init__(self, request):
+ self.request = request
+
+class PubStart(_Base):
+ '''notified at the beginning of 'ZPublisher.Publish.publish'.'''
+ implements(IPubStart)
+
+class PubSuccess(_Base):
+ '''notified at successful request end.'''
+ implements(IPubSuccess)
+
+class PubFailure(object):
+ '''notified at failed request end.'''
+ implements(IPubFailure)
+
+ def __init__(self, request, exc_info, retry):
+ self.request, self.exc_info, self.retry = request, exc_info, retry
+
+
+class PubAfterTraversal(_Base):
+ """notified after traversal and an (optional) authentication."""
+ implements(IPubAfterTraversal)
+
+
+class PubBeforeCommit(_Base):
+ """notified immediately before the commit."""
+ implements(IPubBeforeCommit)
More information about the checkins
mailing list