[Checkins] SVN: z3c.zcmlhook/trunk/ Initial implementation
Martin Aspeli
optilude at gmx.net
Sat Jan 2 07:44:27 EST 2010
Log message for revision 107543:
Initial implementation
Changed:
_U z3c.zcmlhook/trunk/
A z3c.zcmlhook/trunk/README.txt
A z3c.zcmlhook/trunk/buildout.cfg
A z3c.zcmlhook/trunk/docs/
A z3c.zcmlhook/trunk/docs/HISTORY.txt
A z3c.zcmlhook/trunk/docs/LICENSE.ZPL
A z3c.zcmlhook/trunk/setup.cfg
A z3c.zcmlhook/trunk/setup.py
A z3c.zcmlhook/trunk/src/
A z3c.zcmlhook/trunk/src/z3c/
A z3c.zcmlhook/trunk/src/z3c/__init__.py
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/__init__.py
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/meta.zcml
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/__init__.py
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test1.zcml
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test2.zcml
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test3.zcml
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test4.zcml
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test_zcml.py
A z3c.zcmlhook/trunk/src/z3c/zcmlhook/zcml.py
-=-
Property changes on: z3c.zcmlhook/trunk
___________________________________________________________________
Added: svn:ignore
+ .installed.cfg
bin
parts
develop-eggs
eggs
Added: z3c.zcmlhook/trunk/README.txt
===================================================================
--- z3c.zcmlhook/trunk/README.txt (rev 0)
+++ z3c.zcmlhook/trunk/README.txt 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,78 @@
+Introduction
+============
+
+This package provides means of hooking into the Zope (ZCML) configuration
+process.
+
+Custom ZCML actions
+-------------------
+
+It is sometimes useful to execute a function during the execution of
+configuration actions, for example to perform one-off configuration that does
+not warrant a new directive. The ``<zcml:customAction />`` directive is
+provided for this purpose.
+
+For example, you may want to call a function called
+``my.package.finalConfiguration()`` "late" in the configuration action
+execution cycle. This can be achieved with the following ZCML statements::
+
+ <configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:zcml="http://namespaces.zope.org/zcml"
+ i18n_domain="my.package">
+
+ <include package="z3c.zcmlhook" file="meta.zcml" />
+
+ <zcml:customAction
+ handler="my.package.finalConfiguration"
+ order="9999"
+ />
+
+ </configure>
+
+The ``handler`` attribute gives the name of a function to execute. The
+function should take no arguments. The ``order`` attribute is optional, and
+can be used to influence when in the configuration cycle the function is
+executed. The default value for this, as for most Zope configuration actions,
+is ``0``.
+
+Overriding custom actions
+-------------------------
+
+If you want to override the invocation of a custom handler in an
+``overrides.zcml``, you need to tell ``zope.configuration`` which handler to
+override. You can do that by setting the *discriminator* explicitly. A
+discriminator is used to uniquely identify a configuration action. In the
+case of the ``<zcml:customAction />`` directive, the discriminator is based
+on the full dotted name to the function by default. Thus, you could override
+the function call above like so::
+
+ <zcml:customAction
+ handler="my.otherpackage.overrideFinalConfiguration"
+ discriminator="my.package.finalConfiguration"
+ order="9999"
+ />
+
+Using a method more than once
+-----------------------------
+
+The ``discriminator`` attribute can also be used to explicitly allow using
+the same handler more than once. If you wanted to call
+``my.package.finalConfiguration`` again, you would normally get a
+configuration conflict. However, with a (unique) custom discriminator, the
+second call is allowed::
+
+ <zcml:customAction
+ handler="my.package.finalConfiguration"
+ discriminator="my.package.finalConfiguration:early"
+ order="-9999"
+ />
+
+ <zcml:customAction
+ handler="my.package.finalConfiguration"
+ discriminator="my.package.finalConfiguration:late"
+ order="9999"
+ />
+
+Here, we are attempting to call our configuration action "very early" as
+well as "very late" in the configuration process.
\ No newline at end of file
Added: z3c.zcmlhook/trunk/buildout.cfg
===================================================================
--- z3c.zcmlhook/trunk/buildout.cfg (rev 0)
+++ z3c.zcmlhook/trunk/buildout.cfg 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,8 @@
+[buildout]
+parts = test
+develop = .
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.zcmlhook
+defaults = ['--exit-with-status', '--auto-progress', '--auto-color']
Added: z3c.zcmlhook/trunk/docs/HISTORY.txt
===================================================================
--- z3c.zcmlhook/trunk/docs/HISTORY.txt (rev 0)
+++ z3c.zcmlhook/trunk/docs/HISTORY.txt 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,8 @@
+Changelog
+=========
+
+1.0b1 - January 2nd, 2010
+-------------------------
+
+* Initial release
+ [optilude]
Added: z3c.zcmlhook/trunk/docs/LICENSE.ZPL
===================================================================
--- z3c.zcmlhook/trunk/docs/LICENSE.ZPL (rev 0)
+++ z3c.zcmlhook/trunk/docs/LICENSE.ZPL 2010-01-02 12:44:27 UTC (rev 107543)
@@ -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: z3c.zcmlhook/trunk/setup.cfg
===================================================================
--- z3c.zcmlhook/trunk/setup.cfg (rev 0)
+++ z3c.zcmlhook/trunk/setup.cfg 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,4 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
+
Added: z3c.zcmlhook/trunk/setup.py
===================================================================
--- z3c.zcmlhook/trunk/setup.py (rev 0)
+++ z3c.zcmlhook/trunk/setup.py 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,38 @@
+from setuptools import setup, find_packages
+import os.path
+
+version = "1.0b1"
+
+setup(name = "z3c.zcmlhook",
+ version = version,
+ description = "Easily hook into the ZCML processing machinery",
+ long_description = open("README.txt").read() + "\n" +
+ open(os.path.join("docs", "HISTORY.txt")).read(),
+ classifiers = [
+ "Environment :: Web Environment",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: Zope Public License",
+ "Programming Language :: Python",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ ],
+ keywords = "zope zcml hook",
+ author = "Martin Aspeli",
+ author_email = "zope-dev at zope.org",
+ url = "",
+ license = "ZPL",
+ namespace_packages = ["z3c"],
+ packages = find_packages("src", exclude=["ez_setup"]),
+ package_dir = {"": "src"},
+ include_package_data = True,
+ zip_safe = False,
+ install_requires = [
+ "setuptools",
+ "zope.component",
+ "zope.interface",
+ "zope.schema",
+ "zope.configuration",
+ ],
+ extras_require = {},
+ tests_require = "nose >=0.10.0b1",
+ test_suite = "nose.collector",
+ )
Property changes on: z3c.zcmlhook/trunk/src
___________________________________________________________________
Added: svn:ignore
+ *.egg-info
Added: z3c.zcmlhook/trunk/src/z3c/__init__.py
===================================================================
--- z3c.zcmlhook/trunk/src/z3c/__init__.py (rev 0)
+++ z3c.zcmlhook/trunk/src/z3c/__init__.py 2010-01-02 12:44:27 UTC (rev 107543)
@@ -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__)
Added: z3c.zcmlhook/trunk/src/z3c/zcmlhook/__init__.py
===================================================================
--- z3c.zcmlhook/trunk/src/z3c/zcmlhook/__init__.py (rev 0)
+++ z3c.zcmlhook/trunk/src/z3c/zcmlhook/__init__.py 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1 @@
+
Added: z3c.zcmlhook/trunk/src/z3c/zcmlhook/meta.zcml
===================================================================
--- z3c.zcmlhook/trunk/src/z3c/zcmlhook/meta.zcml (rev 0)
+++ z3c.zcmlhook/trunk/src/z3c/zcmlhook/meta.zcml 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,15 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:meta="http://namespaces.zope.org/meta">
+
+ <meta:directives namespace="http://namespaces.zope.org/zcml">
+
+ <meta:directive
+ name="customAction"
+ schema=".zcml.ICustomActionDirective"
+ handler=".zcml.customAction"
+ />
+
+ </meta:directives>
+
+</configure>
Added: z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/__init__.py
===================================================================
--- z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/__init__.py (rev 0)
+++ z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/__init__.py 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1 @@
+
Added: z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test1.zcml
===================================================================
--- z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test1.zcml (rev 0)
+++ z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test1.zcml 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,10 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:zcml="http://namespaces.zope.org/zcml">
+
+ <include package="z3c.zcmlhook" file="meta.zcml" />
+
+ <zcml:customAction
+ handler="z3c.zcmlhook.tests.test_zcml.test_fn1"
+ />
+
+</configure>
Added: z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test2.zcml
===================================================================
--- z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test2.zcml (rev 0)
+++ z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test2.zcml 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,16 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:zcml="http://namespaces.zope.org/zcml">
+
+ <include package="z3c.zcmlhook" file="meta.zcml" />
+
+ <zcml:customAction
+ handler="z3c.zcmlhook.tests.test_zcml.test_fn1"
+ order="1"
+ />
+
+ <zcml:customAction
+ handler="z3c.zcmlhook.tests.test_zcml.test_fn2"
+ order="-1"
+ />
+
+</configure>
Added: z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test3.zcml
===================================================================
--- z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test3.zcml (rev 0)
+++ z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test3.zcml 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,14 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:zcml="http://namespaces.zope.org/zcml">
+
+ <include package="z3c.zcmlhook" file="meta.zcml" />
+
+ <zcml:customAction
+ handler="z3c.zcmlhook.tests.test_zcml.test_fn1"
+ />
+
+ <zcml:customAction
+ handler="z3c.zcmlhook.tests.test_zcml.test_fn1"
+ />
+
+</configure>
Added: z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test4.zcml
===================================================================
--- z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test4.zcml (rev 0)
+++ z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test4.zcml 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,15 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:zcml="http://namespaces.zope.org/zcml">
+
+ <include package="z3c.zcmlhook" file="meta.zcml" />
+
+ <zcml:customAction
+ handler="z3c.zcmlhook.tests.test_zcml.test_fn1"
+ discriminator="z3c.zcmlhook.tests.test_zcml.test_fn1:custom"
+ />
+
+ <zcml:customAction
+ handler="z3c.zcmlhook.tests.test_zcml.test_fn1"
+ />
+
+</configure>
Added: z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test_zcml.py
===================================================================
--- z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test_zcml.py (rev 0)
+++ z3c.zcmlhook/trunk/src/z3c/zcmlhook/tests/test_zcml.py 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,51 @@
+from unittest import TestCase
+
+from zope.configuration import xmlconfig
+from zope.configuration.config import ConfigurationConflictError
+
+import zope.component.testing
+import z3c.zcmlhook
+
+import threading
+
+testState = threading.local()
+
+def test_fn1():
+ testState.executions.append('test_fn1')
+
+def test_fn2():
+ testState.executions.append('test_fn2')
+
+class TestZCMLDeclarations(TestCase):
+
+ def setUp(self):
+ global testState
+ testState.executions = []
+
+ def tearDown(self):
+ zope.component.testing.tearDown()
+
+ def test_invoke(self):
+ zcml = xmlconfig.XMLConfig("test1.zcml", z3c.zcmlhook.tests)
+ zcml()
+
+ self.assertEquals(['test_fn1'], testState.executions)
+
+ def test_invoke_order(self):
+ zcml = xmlconfig.XMLConfig("test2.zcml", z3c.zcmlhook.tests)
+ zcml()
+
+ self.assertEquals(['test_fn2', 'test_fn1'], testState.executions)
+
+ def test_invoke_conflict(self):
+ zcml = xmlconfig.XMLConfig("test3.zcml", z3c.zcmlhook.tests)
+ self.assertRaises(ConfigurationConflictError, zcml)
+
+ def test_custom_discriminator(self):
+ zcml = xmlconfig.XMLConfig("test4.zcml", z3c.zcmlhook.tests)
+ zcml()
+ self.assertEquals(['test_fn1', 'test_fn1'], testState.executions)
+
+def test_suite():
+ import unittest
+ return unittest.defaultTestLoader.loadTestsFromName(__name__)
Added: z3c.zcmlhook/trunk/src/z3c/zcmlhook/zcml.py
===================================================================
--- z3c.zcmlhook/trunk/src/z3c/zcmlhook/zcml.py (rev 0)
+++ z3c.zcmlhook/trunk/src/z3c/zcmlhook/zcml.py 2010-01-02 12:44:27 UTC (rev 107543)
@@ -0,0 +1,41 @@
+from zope.interface import Interface
+from zope import schema
+from zope.configuration.fields import GlobalObject
+
+class ICustomActionDirective(Interface):
+
+ handler = GlobalObject(
+ title=u"Function to execute",
+ description=u"This function will be executed during ZCML processing",
+ default=None,
+ required=True,
+ )
+
+ order = schema.Int(
+ title=u"Execution order",
+ description=u"Set to a high number to execute late, or a negative number to execute early",
+ default=0,
+ required=False,
+ )
+
+ discriminator = schema.ASCIILine(
+ title=u"Custom discriminator",
+ description=u"By default, the full dotted name to the handler "
+ u"function is used as the discriminator. If you want "
+ u"to use the same function more than once, or if you "
+ u"want to override a custom action defined elsewhere "
+ u"with an overrides.zcml, you can set the "
+ u"discriminator explicitly.",
+ default=None,
+ required=False,
+ )
+
+def customAction(_context, handler, order=0, discriminator=None):
+ if discriminator is None:
+ discriminator = "%s.%s" % (handler.__module__, handler.__name__,)
+
+ _context.action(
+ discriminator=("executeCustomFunction", discriminator),
+ callable=handler,
+ args=(),
+ order=order)
More information about the checkins
mailing list