[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