[Checkins] SVN: z3c.caching/ New package
Wichert Akkerman
wichert at wiggy.net
Wed Oct 15 07:03:30 EDT 2008
Log message for revision 92212:
New package
Changed:
A z3c.caching/
A z3c.caching/branches/
A z3c.caching/tags/
A z3c.caching/trunk/
A z3c.caching/trunk/README.txt
A z3c.caching/trunk/docs/
A z3c.caching/trunk/docs/LICENSE.ZPL
A z3c.caching/trunk/setup.py
A z3c.caching/trunk/z3c/
A z3c.caching/trunk/z3c/__init__.py
A z3c.caching/trunk/z3c/caching/
A z3c.caching/trunk/z3c/caching/__init__.py
A z3c.caching/trunk/z3c/caching/meta.zcml
A z3c.caching/trunk/z3c/caching/modified.py
A z3c.caching/trunk/z3c/caching/registry.py
A z3c.caching/trunk/z3c/caching/tests/
A z3c.caching/trunk/z3c/caching/tests/__init__.py
A z3c.caching/trunk/z3c/caching/tests/test_registry.py
A z3c.caching/trunk/z3c/caching/zcml.py
-=-
Added: z3c.caching/trunk/README.txt
===================================================================
--- z3c.caching/trunk/README.txt (rev 0)
+++ z3c.caching/trunk/README.txt 2008-10-15 11:03:29 UTC (rev 92212)
@@ -0,0 +1,71 @@
+Introduction
+============
+
+Caching of web pages is a complicated process: there are many possible
+policies to choose from, and the right policy can depend on factors such as
+who is making the request, the URL is being retrieved and resource
+negotiation settings such as accepted languages and encodings,
+
+Hardcoding caching logic in an application is not desirable, especially for
+reusable code. It is also not possible to allow an administrator to manually
+configure the caching headers for every resource in an application. This
+packages tries to address this problem by providing a cache ruleset
+framework: it allows implementors to specify a ruleset for every component.
+Administrators can then define a policy which dictates the correct caching
+behaviour for each ruleset.
+
+
+Depending on your environment there are different options for turning
+the ruleset into HTTP caching headers. If you are using Plone_
+you can use `five.caching`_ to integrate with CacheSetup. In a WSGI
+environment you could set the ruleset in `environ` or a response header
+and add a piece of middleware which acts on those hints.
+
+
+Usage
+=====
+
+You can register rulesets using either zcml or direct python. If you
+use zcml you can use the ``cache:ruleset`` directive::
+
+ <configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ xmlns:cache="http://namespaces.zope.org/cache"/>
+
+ <cache:ruleset
+ for=".frontpage.FrontpageView"
+ ruleset="plone-content-types"
+ />
+
+ <browser:page
+ for="..interfaces.IFrontpage"
+ class=".frontpage.FrontpageView"
+ name="frontpage_view"
+ template="templates/frontpage_view.pt"
+ permission="zope2.View" />
+ </configure>
+
+
+This example sets up a browser view called ``frontpage_view`` and
+associates it with the ``plone-content-types`` ruleset.
+
+If you prefer to use python directly you can do so::
+
+ from z3c.caching.registry import register
+ from frontpage import FrontpageView
+
+ register(FrontpageView, "plone-content-types")
+
+You can register a ruleset for objects, their interfaces or a base class.
+
+To find the ruleset for an object use the ``lookup`` method::
+
+ from z3c.caching.registry import lookup
+
+ lookup(FrontpageView)
+
+
+.. _Plone: http://plone.org/
+.. _five.caching: http://pypi.python.org/pypi/five.caching
+
Property changes on: z3c.caching/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.caching/trunk/docs/LICENSE.ZPL
===================================================================
--- z3c.caching/trunk/docs/LICENSE.ZPL (rev 0)
+++ z3c.caching/trunk/docs/LICENSE.ZPL 2008-10-15 11:03:29 UTC (rev 92212)
@@ -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.caching/trunk/setup.py
===================================================================
--- z3c.caching/trunk/setup.py (rev 0)
+++ z3c.caching/trunk/setup.py 2008-10-15 11:03:29 UTC (rev 92212)
@@ -0,0 +1,32 @@
+from setuptools import setup, find_packages
+
+version = "1.0dev"
+
+setup(name = "z3c.caching",
+ version = version,
+ description = "Caching infrastructure for web apps",
+ long_description = open("README.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 = "",
+ author = "Wichert Akkerman",
+ author_email = "zope-dev at zope.org",
+ url = "",
+ license = "ZPL",
+ namespace_packages = ["z3c"],
+ packages = find_packages(exclude=["ez_setup"]),
+ include_package_data = True,
+ zip_safe = False,
+ install_requires = [
+ "setuptools",
+ "zope.interface",
+ "zope.component",
+ ],
+ tests_require = "nose >=0.10.0b1",
+ test_suite = "nose.collector",
+ )
Property changes on: z3c.caching/trunk/setup.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.caching/trunk/z3c/__init__.py
===================================================================
--- z3c.caching/trunk/z3c/__init__.py (rev 0)
+++ z3c.caching/trunk/z3c/__init__.py 2008-10-15 11:03:29 UTC (rev 92212)
@@ -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: z3c.caching/trunk/z3c/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.caching/trunk/z3c/caching/__init__.py
===================================================================
--- z3c.caching/trunk/z3c/caching/__init__.py (rev 0)
+++ z3c.caching/trunk/z3c/caching/__init__.py 2008-10-15 11:03:29 UTC (rev 92212)
@@ -0,0 +1 @@
+
Property changes on: z3c.caching/trunk/z3c/caching/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.caching/trunk/z3c/caching/meta.zcml
===================================================================
--- z3c.caching/trunk/z3c/caching/meta.zcml (rev 0)
+++ z3c.caching/trunk/z3c/caching/meta.zcml 2008-10-15 11:03:29 UTC (rev 92212)
@@ -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/cache">
+
+ <meta:directive
+ name="ruleset"
+ schema=".zcml.IRuleset"
+ handler=".zcml.ruleset"
+ />
+
+ </meta:directives>
+
+</configure>
Property changes on: z3c.caching/trunk/z3c/caching/meta.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.caching/trunk/z3c/caching/modified.py
===================================================================
--- z3c.caching/trunk/z3c/caching/modified.py (rev 0)
+++ z3c.caching/trunk/z3c/caching/modified.py 2008-10-15 11:03:29 UTC (rev 92212)
@@ -0,0 +1,34 @@
+from zope.dublincore.interfaces import IDCTimes
+from Products.CMFCore.interfaces import ICatalogableDublinCore
+
+
+class ILastModified(Interface):
+ def __call__(context):
+ """Return the last modification date for an object."""
+
+
+ at adapter(ICatalogableDublinCore)
+ at implementer(ILastModified)
+def CatalogableDublinCoreLastModified(obj):
+ return obj.modified()
+
+
+ at adapter(IDCTimes)
+ at implementer(ILastModified)
+def DCTimesLastModified(obj):
+ return obj.modified()
+
+
+ at adapter(IBrowserView)
+ at implementer(ILastModified)
+def BrowserViewLastModified(obj):
+ if not has_attr(aq_base(self.context, "context")):
+ return None
+
+ context=aq_base(self.context.context)
+ lm=ILastModified(context, None)
+ if lm is not None:
+ return lm(context)
+
+ return None
+
Property changes on: z3c.caching/trunk/z3c/caching/modified.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.caching/trunk/z3c/caching/registry.py
===================================================================
--- z3c.caching/trunk/z3c/caching/registry.py (rev 0)
+++ z3c.caching/trunk/z3c/caching/registry.py 2008-10-15 11:03:29 UTC (rev 92212)
@@ -0,0 +1,84 @@
+# Rulesets are registered for entities, which can be a type, an interface or even
+# even a specific interface. This means the lookup mechanism needs to be aware
+# of all of those and deal with things like derived classes as well. Luckily
+# we have a framework which already implements that: zope.component.
+#
+# We will (ab)use the zope.component registries by registering a dummy adapter
+# for the entity to a special ICacheRule interface and which will always
+# return the ruleset id.
+
+from zope.interface import Interface
+from zope.component import getGlobalSiteManager
+
+
+class _ICacheRule(Interface):
+ pass
+
+
+class RulesetRegistry(object):
+ def __init__(self):
+ self._rules=set()
+
+
+ def register(self, obj, rule):
+ if obj in self._rules:
+ return
+
+ gsm=getGlobalSiteManager()
+ def r(context):
+ return lambda r=rule:r
+ gsm.registerAdapter(r, provided=_ICacheRule, required=(obj,))
+
+ self._rules.add(obj)
+
+
+ def unregister(self, obj, rule):
+ if obj not in self._rules:
+ return
+
+ gsm=getGlobalSiteManager()
+ gsm.unregisterAdapter(provided=_ICacheRule, required=(obj,))
+ self._rules.remove(obj)
+
+
+ def clear(self):
+ gsm=getGlobalSiteManager()
+ for obj in self._rules:
+ gsm.unregisterAdapter(provided=_ICacheRule, required=(obj,))
+ self._rules.clear()
+
+
+ def lookup(self, obj):
+ ruler=_ICacheRule(obj, None)
+ if ruler is not None:
+ return ruler()
+ return None
+
+
+ __getitem__ = lookup
+
+
+_registry = RulesetRegistry()
+
+unregister = _registry.unregister
+register = _registry.register
+lookup = _registry.lookup
+
+
+def cleanupCacheRulesets():
+ global _registry
+
+ _registry.clear()
+
+try:
+ from zope.testing.cleanup import addCleanUp
+except ImportError:
+ # don't have that part of Zope
+ pass
+else:
+ addCleanUp(cleanupCacheRulesets)
+ del addCleanUp
+
+
+__all__ = [ "register", "unregister" ]
+
Property changes on: z3c.caching/trunk/z3c/caching/registry.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.caching/trunk/z3c/caching/tests/__init__.py
===================================================================
--- z3c.caching/trunk/z3c/caching/tests/__init__.py (rev 0)
+++ z3c.caching/trunk/z3c/caching/tests/__init__.py 2008-10-15 11:03:29 UTC (rev 92212)
@@ -0,0 +1 @@
+
Property changes on: z3c.caching/trunk/z3c/caching/tests/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.caching/trunk/z3c/caching/tests/test_registry.py
===================================================================
--- z3c.caching/trunk/z3c/caching/tests/test_registry.py (rev 0)
+++ z3c.caching/trunk/z3c/caching/tests/test_registry.py 2008-10-15 11:03:29 UTC (rev 92212)
@@ -0,0 +1,42 @@
+from zope.interface import Interface
+from zope.interface import implements
+from unittest import TestCase
+from z3c.caching.registry import cleanupCacheRulesets
+from z3c.caching.registry import _registry
+
+class ITestView(Interface):
+ pass
+
+
+class TestView(object):
+ implements(ITestView)
+
+
+
+class TestRulesetRegistry(TestCase):
+ def tearDown(self):
+ cleanupCacheRulesets()
+
+
+ def testRulesetForInstance(self):
+ _registry.register(TestView, "frop")
+ i=TestView()
+ self.assertEqual(_registry[i], "frop")
+
+
+ def testRulesetViaInterface(self):
+ _registry.register(ITestView, "frop")
+ i=TestView()
+ self.assertEqual(_registry[i], "frop")
+
+
+ def testUnknownRulesetReturnsNone(self):
+ self.failUnless(_registry[None] is None)
+
+
+ def testUnregister(self):
+ _registry.register(TestView, "frop")
+ _registry.unregister(TestView, "frop")
+ self.failUnless(_registry[TestView] is None)
+
+
Property changes on: z3c.caching/trunk/z3c/caching/tests/test_registry.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.caching/trunk/z3c/caching/zcml.py
===================================================================
--- z3c.caching/trunk/z3c/caching/zcml.py (rev 0)
+++ z3c.caching/trunk/z3c/caching/zcml.py 2008-10-15 11:03:29 UTC (rev 92212)
@@ -0,0 +1,26 @@
+from zope.interface import Interface
+from zope.configuration.fields import GlobalObject
+from zope.configuration.fields import PythonIdentifier
+from z3c.caching.registry import register
+
+class IRuleset(Interface):
+ for_ = GlobalObject(
+ title=u"Object to be configured",
+ description=u"The object for which the cache ruleset is to be defined",
+ default=None,
+ required=True)
+
+ ruleset = PythonIdentifier(
+ title=u"ruleset",
+ description=u"The id of the cache ruleset to use",
+ default=None,
+ required=True)
+
+
+def ruleset(_context, for_, ruleset):
+ _context.action(
+ discriminator=("registerCacheRule", for_),
+ callable = register,
+ args = (for_, ruleset))
+
+
Property changes on: z3c.caching/trunk/z3c/caching/zcml.py
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the Checkins
mailing list