[Checkins] SVN: lovely.responsecache/ imported from Lovely Systems private repository

Jodok Batlogg jodok.batlogg at lovelysystems.com
Thu Jun 7 13:58:22 EDT 2007


Log message for revision 76468:
  imported from Lovely Systems private repository

Changed:
  A   lovely.responsecache/
  A   lovely.responsecache/trunk/
  A   lovely.responsecache/trunk/CHANGES.txt
  A   lovely.responsecache/trunk/buildout.cfg
  A   lovely.responsecache/trunk/setup.py
  A   lovely.responsecache/trunk/src/
  A   lovely.responsecache/trunk/src/lovely/
  A   lovely.responsecache/trunk/src/lovely/__init__.py
  A   lovely.responsecache/trunk/src/lovely/responsecache/
  A   lovely.responsecache/trunk/src/lovely/responsecache/BROWSER.txt
  A   lovely.responsecache/trunk/src/lovely/responsecache/LICENSE.txt
  A   lovely.responsecache/trunk/src/lovely/responsecache/README.txt
  A   lovely.responsecache/trunk/src/lovely/responsecache/__init__.py
  A   lovely.responsecache/trunk/src/lovely/responsecache/configure.zcml
  A   lovely.responsecache/trunk/src/lovely/responsecache/event.py
  A   lovely.responsecache/trunk/src/lovely/responsecache/ftesting.zcml
  A   lovely.responsecache/trunk/src/lovely/responsecache/interfaces.py
  A   lovely.responsecache/trunk/src/lovely/responsecache/lovely.responsecache-configure.zcml
  A   lovely.responsecache/trunk/src/lovely/responsecache/lovely.responsecache-meta.zcml
  A   lovely.responsecache/trunk/src/lovely/responsecache/meta.zcml
  A   lovely.responsecache/trunk/src/lovely/responsecache/namespace.py
  A   lovely.responsecache/trunk/src/lovely/responsecache/testing/
  A   lovely.responsecache/trunk/src/lovely/responsecache/testing/__init__.py
  A   lovely.responsecache/trunk/src/lovely/responsecache/testing/configure.zcml
  A   lovely.responsecache/trunk/src/lovely/responsecache/testing/test.pt
  A   lovely.responsecache/trunk/src/lovely/responsecache/testing/viewlet.pt
  A   lovely.responsecache/trunk/src/lovely/responsecache/testing/views.py
  A   lovely.responsecache/trunk/src/lovely/responsecache/tests.py
  A   lovely.responsecache/trunk/src/lovely/responsecache/view.py
  A   lovely.responsecache/trunk/src/lovely/responsecache/zcml.py
  A   lovely.responsecache/trunk/src/lovely/responsecache/zcml.txt

-=-
Added: lovely.responsecache/trunk/CHANGES.txt
===================================================================
--- lovely.responsecache/trunk/CHANGES.txt	                        (rev 0)
+++ lovely.responsecache/trunk/CHANGES.txt	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,22 @@
+================================
+Changes for lovely.responsecache
+================================
+
+2007/06/07 0.2.2
+================
+
+- moved to svn.zope.org
+- ZPL license
+
+2007/06/03 0.2.1
+================
+
+- bugfix: fix discriminators in zcml directive
+
+2007/06/03 0.2.0
+================
+
+- we now only cache contentproviders on beforeupdateevent this is much
+  cleaner, also we can cache viewletmanagers and viewlets without
+  traversing them.
+


Property changes on: lovely.responsecache/trunk/CHANGES.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/buildout.cfg
===================================================================
--- lovely.responsecache/trunk/buildout.cfg	                        (rev 0)
+++ lovely.responsecache/trunk/buildout.cfg	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,10 @@
+[buildout]
+develop = .
+parts = test
+find-links = http://download.zope.org/distribution/
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = lovely.responsecache [test]
+
+

Added: lovely.responsecache/trunk/setup.py
===================================================================
--- lovely.responsecache/trunk/setup.py	                        (rev 0)
+++ lovely.responsecache/trunk/setup.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,57 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+
+__docformat__ = "reStructuredText"
+
+
+from setuptools import setup, find_packages
+
+setup(
+    name = 'lovely.responsecache',
+    version = '0.2.2',
+    author = "Lovely Systems",
+    author_email = "office at lovelysystems.com",
+    description = "Cache results of ContentProviders",
+    license = "ZPL 2.1",
+    keywords = "responsecache zope zope3",
+    url = 'http://svn.zope.org/lovely.responsecache',
+    zip_safe = False,
+    packages = find_packages('src'),
+    include_package_data = True,
+    package_dir = {'':'src'},
+    namespace_packages = ['lovely',],
+    install_requires = ['setuptools',
+                        'lovely.memcached',
+                        'zope.app.publication',
+                        'zope.app.security',
+                        'zope.contentprovider',
+                        'zope.publisher',
+                        'zope.schema',
+                        'zope.security',
+                        'zope.traversing'],
+    extras_require = dict(
+        test = ['z3c.configurator',
+                'z3c.testing',
+                'zope.testbrowser',
+                'zope.viewlet',
+                'zope.pagetemplate',
+                'zope.app.securitypolicy',
+                'zope.app.zcmlfiles',
+                'zope.app.testing',
+                'zope.testing',]),
+    )


Property changes on: lovely.responsecache/trunk/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/__init__.py
===================================================================
--- lovely.responsecache/trunk/src/lovely/__init__.py	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/__init__.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,25 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+
+__docformat__ = "reStructuredText"
+
+
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    pass


Property changes on: lovely.responsecache/trunk/src/lovely/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/BROWSER.txt
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/BROWSER.txt	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/BROWSER.txt	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,91 @@
+============
+Cached Views
+============
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+At first we have misses
+
+  >>> browser.open('http://localhost/test.html')
+  >>> print browser.headers
+  Status: 200 Ok
+  ...
+  X-Memcached-Miss: /test.html /test.html/IContent /test.html/MyViewlet
+  ...
+  >>> uncachedContent = browser.contents
+
+
+The second request is cached. Note that due to the reason we cached
+the whole view, the viewletmanager and the viewlet are not even
+getting called, so not miss/hit is in the header.
+
+  >>> browser.open('http://localhost/test.html')
+  >>> print browser.headers
+  Status: 200 Ok
+  ...
+  X-Memcached-Hit: /test.html
+  ...
+  >>> uncachedContent == browser.contents
+  True
+
+
+Authentication Information
+==========================
+
+Sometimes it is useful for frontend servers (the ones that do the
+calls to our server) have information about if the user is
+authenticated, to rewrite caching urls. So we have defined a handler for
+endrequest, that sets a cookie with authentication information.
+
+  >>> browser.headers.get('set-cookie')
+  'z3.authenticated=False;'
+
+Let us log in.
+
+  >>> browser = Browser()
+  >>> browser.addHeader('Authorization','Basic mgr:mgrpw')
+  >>> browser.handleErrors = False
+  >>> browser.open('http://localhost/')
+  >>> browser.headers.get('set-cookie')
+  'z3.authenticated=True;'
+
+Caching Key namespace
+=====================
+
+The ckey namespace allows to set arbitrary keys for differentiate on
+specific keys for frontent url rewriting which would otherwise be not
+visible in the bare url. For example we could have different cache
+entries for authenticated or unauthenticated requests.
+
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open('http://localhost/++ckey++anonymous/test.html')
+  >>> browser.url
+  'http://localhost/++ckey++anonymous/test.html'
+  >>> print browser.headers.get('x-memcached-miss')
+  /++ckey++anonymous/test.html
+  /++ckey++anonymous/test.html/IContent
+  /++ckey++anonymous/test.html/MyViewlet
+
+  >>> browser.open('http://localhost/++ckey++authenticated/test.html')
+  >>> print browser.headers.get('x-memcached-miss')
+  /++ckey++authenticated/test.html
+  /++ckey++authenticated/test.html/IContent
+  /++ckey++authenticated/test.html/MyViewlet
+  
+We can also cascade such keys.
+
+  >>> browser.open('http://localhost/++ckey++anonymous/'
+  ...              '++ckey++aSessionId/test.html')
+  >>> print browser.headers.get('x-memcached-miss')
+  /++ckey++anonymous/++ckey++aSessionId/test.html
+  /++ckey++anonymous/++ckey++aSessionId/test.html/IContent
+  /++ckey++anonymous/++ckey++aSessionId/test.html/MyViewlet
+  
+  >>> browser.open('http://localhost/++ckey++anonymous/'
+  ...              '++ckey++aSessionId/test.html')
+  >>> print browser.headers.get('x-memcached-hit')
+  /++ckey++anonymous/++ckey++aSessionId/test.html
+  


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/BROWSER.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/LICENSE.txt
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/LICENSE.txt	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/LICENSE.txt	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,54 @@
+Zope Public License (ZPL) Version 2.1
+-------------------------------------
+
+A copyright notice accompanies this license document that
+identifies the copyright holders.
+
+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:
+
+1. Redistributions in source code must retain the
+   accompanying copyright notice, this list of conditions,
+   and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying
+   copyright notice, this list of conditions, and the
+   following disclaimer in the documentation and/or other
+   materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to
+   endorse or promote products derived from this software
+   without prior written permission from the copyright
+   holders.
+
+4. 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 the copyright
+   holders. Use of them is covered by separate agreement
+   with the copyright holders.
+
+5. 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT HOLDERS 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.
\ No newline at end of file


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/LICENSE.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/README.txt
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/README.txt	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/README.txt	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,103 @@
+=================
+Respsonse Caching
+=================
+
+This package allows to cache results of ContentProviders. Note that
+normal zope BrowserViews do not implement the IContentProvider
+interface, so in order to cache views, they have to implement the
+update and render methods. For a base class see
+z3c.viewtemplate.baseview.BaseView.
+
+IResponseCacheSettings Views
+============================
+
+In oder to be cached, a view implementing IResponseCacheSettings has
+to be registered for the provider and the beforupdate handler also.
+
+    >>> from zope import component
+    >>> from lovely.responsecache.event import setCache
+    >>> component.provideHandler(setCache)
+
+There is a base class which can be used to create cache settings views.
+
+    >>> from lovely.responsecache import view
+
+Let us define a dedicated memcached client for our responsecache.
+
+    >>> from lovely.memcached.utility import MemcachedClient
+    >>> from lovely.memcached.interfaces import IMemcachedClient
+    >>> util = MemcachedClient()
+    >>> util.invalidateAll()
+    >>> component.provideUtility(util, IMemcachedClient,
+    ...     name='responsecache')
+
+Let us create a simple view and settings view. We have to have a view
+that implements IContentProvider.
+
+    >>> from zope.publisher.browser import BrowserView
+    >>> from zope.publisher.interfaces.browser import IBrowserRequest
+    >>> from zope import interface
+    >>> from zope.contentprovider.interfaces import IContentProvider
+    >>> from zope.contentprovider.interfaces import BeforeUpdateEvent
+    >>> from zope.event import notify
+    >>> class MyView(BrowserView):
+    ...     interface.implements(IContentProvider)
+    ...     __name__ = u'test.html'
+    ...     __parent__ = root
+    ...     def update(self):
+    ...         pass
+    ...     def render(self):
+    ...         return 'my view content'
+    ...     def __call__(self):
+    ...         notify(BeforeUpdateEvent(self, self.request))
+    ...         self.update()
+    ...         return self.render()
+
+If we call the view without having cache settings nothing is
+cached. We can evaluate this by looking at the responseheaders.
+
+    >>> from zope.publisher.browser import TestRequest
+    >>> request = TestRequest()
+    >>> myView = MyView(root, request)
+    >>> myView()
+    'my view content'
+    >>> request.response.getHeaders()
+    [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)')]
+
+Let us now implement cache setttings.
+
+    >>> class MyDefaultCacheSettings(view.ResponseCacheSettings):
+    ...     component.adapts(IContentProvider, IBrowserRequest)
+    ...     lifetime=3600
+    ...     cacheName = 'responsecache'
+    >>> component.provideAdapter(MyDefaultCacheSettings)
+    >>> myView()
+    'my view content'
+
+We now have a cache miss.
+
+    >>> request.response.getHeaders()
+    [...('X-Memcached-Miss', '/test.html')]
+
+Note that the render method gets rewritten.
+
+    >>> myView.render
+    <lovely.responsecache.event.RenderWrapper object at ...>
+
+But if we now try again we have a hit.
+
+    >>> request = TestRequest(PATH_INFO='test.html')
+    >>> myView = MyView(object(), request)
+    >>> myView()
+    u'my view content'
+    >>> request.response.getHeaders()
+    [...('X-Memcached-Hit', '/test.html')]
+
+
+Note that the render and update methods are rewritten.
+
+    >>> myView.render
+    <lovely.responsecache.event.RenderWrapper object at ...>
+    >>> myView.update
+    <lovely.responsecache.event.UpdateWrapper object at ...>
+    


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/__init__.py
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/__init__.py	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/__init__.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1 @@
+# package


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/configure.zcml
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/configure.zcml	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/configure.zcml	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,21 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:browser="http://namespaces.zope.org/browser"
+           i18n_domain="zope">
+
+  <class class=".event.RenderWrapper">
+    <allow attributes="__call__"/>
+  </class>
+  <class class=".event.UpdateWrapper">
+    <allow attributes="__call__"/>
+  </class>
+
+  <subscriber handler=".event.setCache"/>
+  <subscriber handler=".event.setAuthInfoCookie"/>
+
+  <view
+      name="ckey" type="*"
+      provides="zope.traversing.interfaces.ITraversable" for="*"
+      factory=".namespace.ckey"
+      />
+
+</configure>


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/event.py
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/event.py	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/event.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,103 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+from zope.app.publication.interfaces import IEndRequestEvent
+from zope import component
+from zope.app.publication.interfaces import IBeforeTraverseEvent
+from interfaces import IResponseCacheSettings
+from zope.app.security.interfaces import IUnauthenticatedPrincipal
+from zope.contentprovider.interfaces import IBeforeUpdateEvent
+from zope.contentprovider.interfaces import IContentProvider
+from zope.publisher.interfaces.browser import IBrowserRequest
+from types import UnicodeType
+from zope.publisher.http import getCharsetUsingRequest
+from zope.security.proxy import removeSecurityProxy
+
+class RenderWrapper(object):
+
+    def __init__(self, provider, settings, request):
+        self.render = provider.render
+        self.settings = settings
+        self.provider = provider
+        self.request = request
+
+    def __call__(self):
+        cached = getattr(self.provider, '_UpdateWrapper__cached_result', None)
+        encoding = getCharsetUsingRequest(self.request) or 'utf-8'
+        if cached is not None:
+            return cached.decode(encoding)
+        res = body = self.render()
+        if type(body) is UnicodeType:
+            encoding = getCharsetUsingRequest(self.request) or 'utf-8'
+            body = body.encode(encoding)
+
+        self.settings.cache.set(body, self.settings.key,
+                                dependencies=self.settings.dependencies,
+                                lifetime=self.settings.lifetime,
+                                raw=True)
+
+        return res
+
+
+class UpdateWrapper(object):
+
+    def __init__(self, provider, settings, request):
+        self.provider = provider
+        self.update = provider.update
+        self.settings = settings
+        self.request = request
+
+    def __call__(self):
+        cached = self.settings.cache.query(self.settings.key, raw=True)
+        if cached:
+            hit = self.request.response.getHeader('X-Memcached-Hit')
+            if hit:
+                hit += ' %s' % self.settings.key
+            else:
+                hit = self.settings.key
+            self.request.response.setHeader('X-Memcached-Hit', hit)
+            self.provider.__cached_result = cached
+            return
+        miss = self.request.response.getHeader('X-Memcached-Miss')
+        if miss:
+            miss += ' %s' % self.settings.key
+        else:
+            miss = self.settings.key
+        self.request.response.setHeader('X-Memcached-Miss', miss)
+        return self.update()
+
+
+ at component.adapter(IContentProvider, IBeforeUpdateEvent)
+def setCache(provider, ev):
+    settings = component.queryMultiAdapter(
+        (provider, ev.request), IResponseCacheSettings)
+    if settings is None or settings.cache is None:
+        return
+    provider = removeSecurityProxy(provider)
+    provider.update = UpdateWrapper(provider, settings, ev.request)
+    provider.render = RenderWrapper(provider, settings, ev.request)
+
+ at component.adapter(IEndRequestEvent)
+def setAuthInfoCookie(ev):
+    """sets a cookie that tells if the user authenticated or not.
+    This is not used for authentication. This is just usefull for
+    frontend caching servers to rewrite urls for caching."""
+    if IBrowserRequest.providedBy(ev.request):
+        auth = not IUnauthenticatedPrincipal.providedBy(ev.request.principal)
+        ev.request.response.setCookie('z3.authenticated', str(auth))
+


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/event.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/ftesting.zcml
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/ftesting.zcml	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/ftesting.zcml	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,77 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:browser="http://namespaces.zope.org/browser"
+           xmlns:zcml="http://namespaces.zope.org/zcml"
+           xmlns:meta="http://namespaces.zope.org/meta"
+           i18n_domain="zope">
+
+  
+  <include package="zope.app.securitypolicy" file="meta.zcml" />
+
+  <include
+      zcml:condition="installed zope.app.zcmlfiles"
+      package="zope.app.zcmlfiles"
+      />
+  <include
+      zcml:condition="not-installed zope.app.zcmlfiles"
+      package="zope.app"
+      />
+
+  <include package="zope.viewlet" file="meta.zcml" />
+  
+  <include package="zope.app.authentication" />
+  <securityPolicy
+      component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+
+  <include package="zope.app.securitypolicy" />
+
+  <role id="zope.Anonymous" title="Everybody"
+        description="All users have this role implicitly" />
+
+  <role id="zope.Manager" title="Site Manager" />
+
+  
+  <principal
+      id="zope.manager"
+      title="Administrator"
+      login="mgr"
+      password="mgrpw" />
+  
+  <grant
+      role="zope.Manager"
+      principal="zope.manager"
+      />
+  
+  <unauthenticatedPrincipal
+      id="zope.anybody"
+      title="Unauthenticated User" />
+
+  <unauthenticatedGroup
+      id="zope.Anybody"
+      title="Unauthenticated Users" 
+      />
+  
+
+  <authenticatedGroup
+      id="zope.Authenticated"
+      title="Authenticated Users" 
+      />
+  
+  <everybodyGroup
+      id="zope.Everybody"
+      title="All Users" 
+      />
+
+  <include package="zope.contentprovider"/>
+  <include package="zope.viewlet"/>
+  <include package="lovely.memcached" />
+  <include package="lovely.responsecache" />
+  <include package="lovely.responsecache.testing" />
+
+
+  <grant permission="zope.View"
+         principal="zope.Everybody"/>
+      
+  
+  <grantAll role="zope.Manager" />
+  
+</configure>


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/ftesting.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/interfaces.py
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/interfaces.py	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/interfaces.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,37 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+from zope import interface
+from zope import schema
+
+class IResponseCacheSettings(interface.Interface):
+
+    key = schema.BytesLine(title=u'Cachekey', required=True)
+
+    cacheName = schema.TextLine(title=u'Cachename',
+                                required=False,
+                                default=u'')
+
+    lifetime = schema.Int(title = u'Lifetime',
+                          required = False,
+                          )
+
+    dependencies = schema.List(title=u'Dependencies',
+                               required=False,
+                               default=[])
+


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/lovely.responsecache-configure.zcml
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/lovely.responsecache-configure.zcml	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/lovely.responsecache-configure.zcml	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1 @@
+<include package="lovely.responsecache"/>


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/lovely.responsecache-configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/lovely.responsecache-meta.zcml
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/lovely.responsecache-meta.zcml	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/lovely.responsecache-meta.zcml	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,6 @@
+<configure
+    xmlns:zcml="http://namespaces.zope.org/zcml">
+
+  <include package="lovely.responsecache" file="meta.zcml" />
+
+</configure>


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/lovely.responsecache-meta.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/meta.zcml
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/meta.zcml	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/meta.zcml	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,16 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:meta="http://namespaces.zope.org/meta">
+
+  <meta:directives namespace="http://namespaces.zope.org/browser">
+
+    <meta:directive
+        name="cacheSettings"
+        schema=".zcml.ICacheSettingsDirective"
+        handler=".zcml.cacheSettingsDirective"
+        />
+
+  </meta:directives>
+
+</configure>
+


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/meta.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/namespace.py
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/namespace.py	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/namespace.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,26 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+from zope.traversing.namespace import view
+
+class ckey(view):
+
+    """a namespace that does nothing, just for changing urls"""
+
+    def traverse(self, name, ignored):
+        return self.context


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/namespace.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/testing/__init__.py
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/testing/__init__.py	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/testing/__init__.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1 @@
+# testing package


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/testing/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/testing/configure.zcml
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/testing/configure.zcml	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/testing/configure.zcml	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,29 @@
+<configure xmlns:zope="http://namespaces.zope.org/zope"
+           xmlns="http://namespaces.zope.org/browser"
+           i18n_domain="zope">
+
+  <zope:view
+      for="zope.contentprovider.interfaces.IContentProvider"
+      factory=".views.HourCacheSettings"
+      type="zope.publisher.interfaces.http.IHTTPRequest"
+      permission="zope.Public"
+      provides="..interfaces.IResponseCacheSettings"
+      />
+  
+  <page
+      for="*"
+      name="test.html"
+      class=".views.TestPage"
+      permission="zope.Public"/>
+
+  <viewletManager
+      name="IContent"
+      permission="zope.Public"/>
+
+  <viewlet
+      name="MyViewlet"
+      template="viewlet.pt"
+      permission="zope.Public"/>
+  
+</configure>
+


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/testing/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/testing/test.pt
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/testing/test.pt	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/testing/test.pt	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,8 @@
+<html>
+  <body>
+    <div>
+      x = <div tal:replace="view/x"/>
+    </div>
+    <div tal:replace="structure provider:IContent"/>
+  </body>
+</html>


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/testing/test.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/testing/viewlet.pt
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/testing/viewlet.pt	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/testing/viewlet.pt	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,3 @@
+<div>
+  content of viewlet
+</div>


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/testing/viewlet.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/testing/views.py
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/testing/views.py	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/testing/views.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,32 @@
+from zope.contentprovider.interfaces import IContentProvider, UpdateNotCalled
+from zope.contentprovider.interfaces import BeforeUpdateEvent
+from zope.event import notify
+from zope import interface
+from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
+
+from lovely.responsecache import view
+
+class HourCacheSettings(view.ResponseCacheSettings):
+    lifetime=3600
+
+
+class TestPage(object):
+    interface.implements(IContentProvider)
+
+    template = ViewPageTemplateFile('test.pt')
+    __updated = False
+
+    def update(self):
+        # make sure that our update is called before each render
+        self.__updated = True
+        self.x = 1
+        
+    def render(self):
+        if not self.__updated:
+            raise UpdateNotCalled
+        return self.template()
+    
+    def __call__(self):
+        notify(BeforeUpdateEvent(self, self.request))
+        self.update()
+        return self.render()


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/testing/views.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/tests.py
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/tests.py	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/tests.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,82 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import unittest
+
+from zope import interface
+from zope import component
+
+from zope.testing import doctest
+from zope.testing.doctestunit import DocFileSuite
+from zope.app.testing import functional
+from zope.app.testing import setup
+from z3c.configurator import configurator
+from z3c.testing import layer
+from lovely.memcached.interfaces import IMemcachedClient
+
+from view import ResponseCacheSettings
+
+class IMyView(interface.Interface):
+    pass
+
+class MyCacheSettings(ResponseCacheSettings):
+    pass
+
+
+def appSetUp(app):
+    
+    configurator.configure(app, {},
+                           names = ['lovely.memcachedclient'])
+    cache = component.getUtility(IMemcachedClient,
+                                 context=app)
+    cache.invalidateAll()
+    
+layer.defineLayer('ResponseCacheLayer', zcml='ftesting.zcml',
+                  appSetUp=appSetUp,
+                  clean=True)
+
+def setUp(test):
+    root = setup.placefulSetUp(True)
+    test.globs['root'] = root
+    test.globs['IMyView'] = IMyView
+
+def tearDown(test):
+    setup.placefulTearDown()
+
+def test_suite():
+    level1Suites = (
+        DocFileSuite(
+        'zcml.txt', setUp=setUp, tearDown=tearDown,
+        optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+        ),
+        )
+    fsuite = functional.FunctionalDocFileSuite('BROWSER.txt')
+    fsuite.layer=ResponseCacheLayer
+    level2Suites = (
+        DocFileSuite(
+        'README.txt', setUp=setUp, tearDown=tearDown,
+        optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+        ),
+        fsuite,
+        )
+    for suite in level2Suites:
+        suite.level = 2
+    return unittest.TestSuite(level1Suites + level2Suites)
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/tests.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/view.py
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/view.py	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/view.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,64 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+from interfaces import IResponseCacheSettings
+from zope import interface
+from zope import component
+from zope.schema.fieldproperty import FieldProperty
+from lovely.memcached.interfaces import IMemcachedClient
+from zope.traversing.browser.absoluteurl import absoluteURL
+from zope.app.component.hooks import getSite
+import re
+
+CKEY_PAT = pat = re.compile(r'\+\+ckey\+\+([^\/]*)\/')
+
+class ResponseCacheSettings(object):
+
+    interface.implements(IResponseCacheSettings)
+
+    cacheName = FieldProperty(IResponseCacheSettings['cacheName'])
+    dependencies = FieldProperty(
+                    IResponseCacheSettings['dependencies'])
+    lifetime= FieldProperty(IResponseCacheSettings['lifetime'])
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+        self._key = None
+
+    @apply
+    def key():
+        def get(self):
+            if self._key is not None:
+                return self._key
+            url = absoluteURL(self.context, self.request)
+            siteUrl = absoluteURL(getSite(), self.request)
+            url = url[len(siteUrl):]
+            for key in reversed(CKEY_PAT.findall(self.request.getURL())):
+                url = '/++ckey++%s%s' % (key, url)
+            return url.encode('utf-8')
+        def set(self, value):
+            self._key = value
+        return property(get, set)
+
+    @property
+    def cache(self):
+        return component.queryUtility(IMemcachedClient,
+                                      name=self.cacheName,
+                                      context=self.context)
+


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/view.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/zcml.py
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/zcml.py	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/zcml.py	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,164 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import os
+
+from zope import interface
+from zope import component
+from zope import schema
+
+from zope.component import zcml
+from zope.component.zcml import handler
+from zope.configuration.fields import GlobalObject
+from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+
+from interfaces import IResponseCacheSettings
+from view import ResponseCacheSettings
+
+from zope.i18nmessageid import MessageFactory
+_ = MessageFactory('lovely.responseheader')
+
+
+class ICacheSettingsDirective(interface.Interface):
+    """Parameters for the cache settings directive."""
+
+    for_ = GlobalObject(
+            title = _(u'for'),
+            description = _(u'The interface to register the settings for'),
+            required = True,
+            )
+
+    layer = GlobalObject(
+            title = _(u'Layer'),
+            description = _(u'The layer for which the settings should be used'),
+            required = False,
+            default=IDefaultBrowserLayer,
+            )
+
+    class_ = GlobalObject(
+            title = _(u'class'),
+            description = _(u'The class to use for the settings'),
+            required = False,
+            )
+
+    cacheName = schema.TextLine(
+            title = _(u'Cachename'),
+            required=False,
+            default=u'',
+            )
+
+    key = schema.BytesLine(
+            title = _(u'Cachekey'),
+            required = False,
+            )
+
+    lifetime = schema.TextLine(
+            title = _(u'Lifetime'),
+            description = _(u"""
+                The lifetime of the cache entry in seconds.
+                The content of this filed will be evaluated. It is possible to
+                give the value in the form '11*60*60'.
+                """),
+            required = False,
+            default = None,
+            )
+
+    dependOnContext = schema.Bool(
+            title = _(u'Depend On Context'),
+            description = _("""
+                The dependency will always contain the context of the view.
+                """),
+            required = False,
+            default = False,
+            )
+
+
+class FactoryCacheSettings(ResponseCacheSettings):
+
+    def __init__(self, context, request):
+        super(FactoryCacheSettings, self).__init__(context, request)
+        self.dependOnContext = False
+
+    @property
+    def dependencies(self):
+        if self.dependOnContext:
+            return [self.context.context]
+        return []
+
+
+class CacheSettingsFactory(object):
+
+    def __init__(self,
+            cacheName, key, lifetime, dependOnContext):
+        self.cacheName = cacheName
+        self.key = key
+        self.lifetime = lifetime
+        self.dependOnContext = dependOnContext
+
+    def __call__(self, context, request):
+        settings = FactoryCacheSettings(context, request)
+        if self.cacheName is not None:
+            settings.cacheName = self.cacheName
+        if self.key is not None:
+            settings.key = self.key
+        if self.lifetime is not None:
+            settings.lifetime = self.lifetime
+        settings.dependOnContext = self.dependOnContext
+        return settings
+
+
+def cacheSettingsDirective(_context,
+                           for_,
+                           layer=IDefaultBrowserLayer,
+                           class_=None,
+                           cacheName=None,
+                           key=None,
+                           lifetime=None,
+                           dependOnContext=False,
+                          ):
+    if class_:
+        cdict = {}
+        if lifetime is not None:
+            cdict['lifetime'] = eval(lifetime)
+        if cacheName is not None:
+            cdict['cacheName'] = cacheName
+        if key is not None:
+            cdict['key'] = key
+        if dependOnContext is not None:
+            cdict['dependOnContext'] = dependOnContext
+        new_class = type(class_.__name__, (class_,), cdict)
+    else:
+        if lifetime is not None:
+            lifetime=eval(lifetime)
+        new_class = CacheSettingsFactory(
+                cacheName, key, lifetime, dependOnContext)
+    _context.action(
+        discriminator = (
+            'cacheSettings',
+            layer,
+            for_,
+            ),
+        callable = handler,
+        args = ('registerAdapter',
+                new_class,
+                (for_, layer),
+                IResponseCacheSettings,
+                '',
+                _context.info),
+        )
+


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/zcml.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.responsecache/trunk/src/lovely/responsecache/zcml.txt
===================================================================
--- lovely.responsecache/trunk/src/lovely/responsecache/zcml.txt	                        (rev 0)
+++ lovely.responsecache/trunk/src/lovely/responsecache/zcml.txt	2007-06-07 17:58:22 UTC (rev 76468)
@@ -0,0 +1,139 @@
+==================
+ZCML Configuration
+==================
+
+For a simpler configuration we provide a zcml directive to register cache
+settings.
+
+  >>> baseTemplate = """<configure
+  ...    xmlns='http://namespaces.zope.org/browser'
+  ...    xmlns:test='http://www.zope.org/NS/Zope3/test'
+  ...    i18n_domain='zope'>
+  ...    %s
+  ...   </configure>"""
+
+  >>> from zope.configuration.xmlconfig import xmlconfig, XMLConfig
+
+Do the meta stuff.
+
+  >>> import lovely.responsecache
+  >>> XMLConfig('meta.zcml', lovely.responsecache)()
+
+  >>> from zope import interface
+  >>> class IMyContent(interface.Interface):
+  ...     pass
+  >>> class MyContent(object):
+  ...      interface.implements(IMyContent)
+  >>> content = MyContent()
+
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+
+  >>> class MyView(object):
+  ...     interface.implements(IMyView)
+  ...     def __init__(self, context, request):
+  ...         self.context = context
+  ...         self.request = request
+  >>> myView = MyView(content, request)
+
+Now we register new settings.
+
+  >>> from StringIO import StringIO
+  >>> xmlconfig(StringIO(baseTemplate% (
+  ...      """
+  ...      <cacheSettings
+  ...        for="lovely.responsecache.tests.IMyView"
+  ...        />
+  ...      """
+  ...     )))
+
+  >>> from zope import component
+  >>> from lovely.responsecache.interfaces import IResponseCacheSettings
+  >>> settings = component.getMultiAdapter((myView, request), IResponseCacheSettings)
+  >>> settings
+  <lovely.responsecache.zcml.FactoryCacheSettings object at ...>
+  >>> settings.lifetime is None
+  True
+  >>> settings.cacheName
+  u''
+  >>> settings.dependencies
+  []
+
+  >>> xmlconfig(StringIO(baseTemplate% (
+  ...      """
+  ...      <cacheSettings
+  ...        for="lovely.responsecache.tests.IMyView"
+  ...        lifetime="10"
+  ...        />
+  ...      """
+  ...     )))
+  >>> settings = component.getMultiAdapter((myView, request), IResponseCacheSettings)
+  >>> settings
+  <lovely.responsecache.zcml.FactoryCacheSettings object at ...>
+  >>> settings.lifetime
+  10
+
+  >>> xmlconfig(StringIO(baseTemplate% (
+  ...      """
+  ...      <cacheSettings
+  ...        for="lovely.responsecache.tests.IMyView"
+  ...        cacheName="nginx"
+  ...        key="my key"
+  ...        lifetime="10"
+  ...        />
+  ...      """
+  ...     )))
+  >>> settings = component.getMultiAdapter((myView, request), IResponseCacheSettings)
+  >>> settings
+  <lovely.responsecache.zcml.FactoryCacheSettings object at ...>
+  >>> settings.lifetime
+  10
+  >>> settings.cacheName
+  u'nginx'
+  >>> settings.key
+  'my key'
+
+Now we provide our own cache settings implementation.
+
+  >>> xmlconfig(StringIO(baseTemplate% (
+  ...      """
+  ...      <cacheSettings
+  ...        for="lovely.responsecache.tests.IMyView"
+  ...        class="lovely.responsecache.tests.MyCacheSettings"
+  ...        cacheName="nginx"
+  ...        key="my key"
+  ...        lifetime="10"
+  ...        />
+  ...      """
+  ...     )))
+  >>> settings = component.getMultiAdapter((myView, request), IResponseCacheSettings)
+  >>> settings
+  <lovely.responsecache.zcml.MyCacheSettings object at ...>
+  >>> settings.lifetime
+  10
+  >>> settings.cacheName
+  u'nginx'
+  >>> settings.key
+  'my key'
+
+  >>> xmlconfig(StringIO(baseTemplate% (
+  ...      """
+  ...      <cacheSettings
+  ...        for="lovely.responsecache.tests.IMyView"
+  ...        cacheName="nginx"
+  ...        key="my key"
+  ...        lifetime="10*10"
+  ...        dependOnContext="True"
+  ...        />
+  ...      """
+  ...     )))
+  >>> settings = component.getMultiAdapter((myView, request), IResponseCacheSettings)
+  >>> settings.lifetime
+  100
+  >>> settings.cacheName
+  u'nginx'
+  >>> settings.key
+  'my key'
+  >>> settings.dependencies
+  [<MyContent object at ...>]
+


Property changes on: lovely.responsecache/trunk/src/lovely/responsecache/zcml.txt
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Checkins mailing list