[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