[Checkins] SVN: plone.postpublicationhook/ New package
Wichert Akkerman
wichert at wiggy.net
Wed Sep 24 11:06:11 EDT 2008
Log message for revision 91433:
New package
Changed:
A plone.postpublicationhook/
A plone.postpublicationhook/branches/
A plone.postpublicationhook/tags/
A plone.postpublicationhook/trunk/
A plone.postpublicationhook/trunk/README.txt
A plone.postpublicationhook/trunk/docs/
A plone.postpublicationhook/trunk/docs/HISTORY.txt
A plone.postpublicationhook/trunk/docs/LICENSE.ZPL
A plone.postpublicationhook/trunk/plone/
A plone.postpublicationhook/trunk/plone/__init__.py
A plone.postpublicationhook/trunk/plone/postpublicationhook/
A plone.postpublicationhook/trunk/plone/postpublicationhook/__init__.py
A plone.postpublicationhook/trunk/plone/postpublicationhook/configure.zcml
A plone.postpublicationhook/trunk/plone/postpublicationhook/event.py
A plone.postpublicationhook/trunk/plone/postpublicationhook/hook.py
A plone.postpublicationhook/trunk/plone/postpublicationhook/interfaces.py
A plone.postpublicationhook/trunk/setup.cfg
A plone.postpublicationhook/trunk/setup.py
-=-
Added: plone.postpublicationhook/trunk/README.txt
===================================================================
--- plone.postpublicationhook/trunk/README.txt (rev 0)
+++ plone.postpublicationhook/trunk/README.txt 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,43 @@
+Introduction
+============
+
+This package provides a hook into Zope's ZPublisher that is run after the
+publisher has completed publication, but before the the transaction is commited
+and the response is returned to the requesting browser. This is practical for
+caching purposes: it is the ideal place to determine and insert caching headers
+into the response.
+
+Hooks use `zope.eventz_'s event mechanism using the
+plone.validatehook.interfaces.IPostValidationEvent. This is based on the
+standard ObjectEvent from `zope.component`_.
+
+Example
+=======
+
+As an example we will write a bit of code which logs the path of every published
+object. This is the code for the event handler::
+
+ from zope.interface import Interface
+ from zope.component import adapter
+ from plone.postpublicationhook.interfaces import IAfterPublicationEvent
+ import logging
+
+ logger = logging.getLogger("LogRequest")
+
+ @adapter(Interface, IAfterPublicationEvent)
+ def LogRequest(object, event):
+ if getattr(object, "getPhysicalPath", None) is None:
+ path="Unknown path"
+ else:
+ path="/".join(object.getPhysicalPath()
+
+ logger.info("Request for object %s" % path)
+
+
+To use this code you need to register it in zcml::
+
+ <subscriber handler=".events.LogRequest" />
+
+
+.. _zope.event: http://pypi.python.org/pypi/zope.event
+.. _zope.component: http://pypi.python.org/pypi/zope.component
Property changes on: plone.postpublicationhook/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: plone.postpublicationhook/trunk/docs/HISTORY.txt
===================================================================
--- plone.postpublicationhook/trunk/docs/HISTORY.txt (rev 0)
+++ plone.postpublicationhook/trunk/docs/HISTORY.txt 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,10 @@
+Changelog
+=========
+
+1.0rc1 - September 24, 2008
+---------------------------
+
+* Initial release
+ [wichert]
+
+
Property changes on: plone.postpublicationhook/trunk/docs/HISTORY.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: plone.postpublicationhook/trunk/docs/LICENSE.ZPL
===================================================================
--- plone.postpublicationhook/trunk/docs/LICENSE.ZPL (rev 0)
+++ plone.postpublicationhook/trunk/docs/LICENSE.ZPL 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,43 @@
+Some code carries the Zope Public License (as indicated in the comments):
+
+Zope Public License (ZPL) Version 2.0
+
+This software is Copyright (c) Zope Corporation (tm) and Contributors.
+All rights reserved.
+
+This license has been certified as open source. It has also been designated as
+GPL compatible by the Free Software Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions in source code must retain the above copyright notice, this
+ list of conditions, and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions, and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+* The name Zope Corporation (tm) must not be used to endorse or promote
+ products derived from this software without prior written permission from
+ Zope Corporation.
+* The right to distribute this software or to use it for any purpose does not
+ give you the right to use Servicemarks (sm) or Trademarks (tm) of Zope
+ Corporation. Use of them is covered in a separate agreement
+ (see http://www.zope.com/Marks).
+If any files are modified, you must cause the modified files to carry prominent
+notices stating that you changed the files and the date of any change.
+
+Disclaimer
+THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS'' AND ANY EXPRESSED OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL ZOPE CORPORATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This software consists of contributions made by Zope Corporation and many
+individuals on behalf of Zope Corporation. Specific attributions are listed
+in the accompanying credits file.
Added: plone.postpublicationhook/trunk/plone/__init__.py
===================================================================
--- plone.postpublicationhook/trunk/plone/__init__.py (rev 0)
+++ plone.postpublicationhook/trunk/plone/__init__.py 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
Property changes on: plone.postpublicationhook/trunk/plone/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: plone.postpublicationhook/trunk/plone/postpublicationhook/__init__.py
===================================================================
--- plone.postpublicationhook/trunk/plone/postpublicationhook/__init__.py (rev 0)
+++ plone.postpublicationhook/trunk/plone/postpublicationhook/__init__.py 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,5 @@
+
+def initialize(context):
+ from plone.postpublicationhook.hook import InstallHook
+
+ InstallHook()
Property changes on: plone.postpublicationhook/trunk/plone/postpublicationhook/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: plone.postpublicationhook/trunk/plone/postpublicationhook/configure.zcml
===================================================================
--- plone.postpublicationhook/trunk/plone/postpublicationhook/configure.zcml (rev 0)
+++ plone.postpublicationhook/trunk/plone/postpublicationhook/configure.zcml 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,7 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:five="http://namespaces.zope.org/five">
+
+ <five:registerPackage package="." initialize=".initialize" />
+
+</configure>
Property changes on: plone.postpublicationhook/trunk/plone/postpublicationhook/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: plone.postpublicationhook/trunk/plone/postpublicationhook/event.py
===================================================================
--- plone.postpublicationhook/trunk/plone/postpublicationhook/event.py (rev 0)
+++ plone.postpublicationhook/trunk/plone/postpublicationhook/event.py 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,13 @@
+from zope.interface import implements
+from zope.component.interfaces import ObjectEvent
+from plone.postpublicationhook.interfaces import IAfterPublicationEvent
+
+
+class AfterPublicationEvent(ObjectEvent):
+ implements(IAfterPublicationEvent)
+
+ def __init__(self, context, request):
+ super(AfterPublicationEvent, self).__init__(context)
+ self.request=request
+
+
Property changes on: plone.postpublicationhook/trunk/plone/postpublicationhook/event.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: plone.postpublicationhook/trunk/plone/postpublicationhook/hook.py
===================================================================
--- plone.postpublicationhook/trunk/plone/postpublicationhook/hook.py (rev 0)
+++ plone.postpublicationhook/trunk/plone/postpublicationhook/hook.py 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,147 @@
+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 zope.publisher.browser import setDefaultSkin
+from zope.security.management import newInteraction
+from zope.security.management import endInteraction
+from zExceptions import Redirect
+
+import zope.event
+from plone.postpublicationhook import AfterPublicationEvent
+
+
+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:
+ # 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)
+
+ 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)
+
+ # This is the only change from the canonical publish method
+ zope.event.notify(AfterPublicationEvent(request, object))
+
+ if transactions_manager:
+ transactions_manager.commit()
+ endInteraction()
+
+ return response
+ except:
+ # 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:
+ 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],
+ )
+ finally:
+ if transactions_manager:
+ transactions_manager.abort()
+ endInteraction()
+
+ # 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
+ setDefaultSkin(newrequest)
+ try:
+ return publish(newrequest, module_name, after_list, debug)
+ finally:
+ newrequest.close()
+
+ else:
+ if transactions_manager:
+ transactions_manager.abort()
+ endInteraction()
+ raise
+
+
+
+def InstallHook():
+ """Install our own publish method."""
+ from plone.postpublicationhook import hook
+ import ZPublisher.Publish
+
+ ZPublisher.Publish.publish=hook.publish
+ logging.info("Monkeypatch ZPublisher publish method to send AfterPublicationEvent")
+
Property changes on: plone.postpublicationhook/trunk/plone/postpublicationhook/hook.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: plone.postpublicationhook/trunk/plone/postpublicationhook/interfaces.py
===================================================================
--- plone.postpublicationhook/trunk/plone/postpublicationhook/interfaces.py (rev 0)
+++ plone.postpublicationhook/trunk/plone/postpublicationhook/interfaces.py 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,8 @@
+from zope.component.interfaces import IObjectEvent
+from zope.interface import Attribute
+
+class IAfterPublicationEvent(IObjectEvent):
+ """An event which is fired after publication, but before the transaction is
+ commited."""
+
+ request = Attribute("The request")
Property changes on: plone.postpublicationhook/trunk/plone/postpublicationhook/interfaces.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: plone.postpublicationhook/trunk/setup.cfg
===================================================================
--- plone.postpublicationhook/trunk/setup.cfg (rev 0)
+++ plone.postpublicationhook/trunk/setup.cfg 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
Added: plone.postpublicationhook/trunk/setup.py
===================================================================
--- plone.postpublicationhook/trunk/setup.py (rev 0)
+++ plone.postpublicationhook/trunk/setup.py 2008-09-24 15:06:10 UTC (rev 91433)
@@ -0,0 +1,35 @@
+from setuptools import setup, find_packages
+import os.path
+
+version = '1.0'
+
+setup(name='plone.postpublicationhook',
+ version=version,
+ description="Zope 2 post-publication hook",
+ long_description=open("README.txt").read() + "\n" +
+ open(os.path.join("docs", "HISTORY.txt")).read(),
+ 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='',
+ author='Wichert Akkerman',
+ author_email='wichert at wiggy.net',
+ url='',
+ license='ZPL',
+ packages=find_packages(exclude=['ez_setup']),
+ namespace_packages=['plone'],
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ 'setuptools',
+ 'zope.event',
+ 'zope.interface',
+ 'zope.security',
+ ],
+ )
+
Property changes on: plone.postpublicationhook/trunk/setup.py
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the Checkins
mailing list