This repository has been archived by the owner on Feb 12, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2b44535
Showing
11 changed files
with
320 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Changelog | ||
========= | ||
|
||
1.0rc1 - September 24, 2008 | ||
--------------------------- | ||
|
||
* Initial release | ||
[wichert] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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__) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
|
||
def initialize(context): | ||
from plone.postpublicationhook.hook import InstallHook | ||
|
||
InstallHook() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<configure | ||
xmlns="http://namespaces.zope.org/zope" | ||
xmlns:five="http://namespaces.zope.org/five"> | ||
|
||
<five:registerPackage package="." initialize=".initialize" /> | ||
|
||
</configure> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[egg_info] | ||
tag_build = dev | ||
tag_svn_revision = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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@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', | ||
], | ||
) | ||
|