[Checkins] SVN: lovely.memcached/trunk/ lovely.memcached proj
Bernd Dorn
bernd.dorn at lovelysystems.com
Fri Mar 30 06:28:32 EDT 2007
Log message for revision 73944:
lovely.memcached proj
Changed:
A lovely.memcached/trunk/
A lovely.memcached/trunk/README.txt
A lovely.memcached/trunk/bootstrap.py
A lovely.memcached/trunk/buildout.cfg
A lovely.memcached/trunk/setup.cfg
A lovely.memcached/trunk/setup.py
A lovely.memcached/trunk/src/
A lovely.memcached/trunk/src/lovely/
A lovely.memcached/trunk/src/lovely/__init__.py
A lovely.memcached/trunk/src/lovely/memcached/
A lovely.memcached/trunk/src/lovely/memcached/README.txt
A lovely.memcached/trunk/src/lovely/memcached/__init__.py
A lovely.memcached/trunk/src/lovely/memcached/browser/
A lovely.memcached/trunk/src/lovely/memcached/browser/README.txt
A lovely.memcached/trunk/src/lovely/memcached/browser/__init__.py
A lovely.memcached/trunk/src/lovely/memcached/browser/configure.zcml
A lovely.memcached/trunk/src/lovely/memcached/browser/ftesting.zcml
A lovely.memcached/trunk/src/lovely/memcached/browser/stats.pt
A lovely.memcached/trunk/src/lovely/memcached/browser/tests.py
A lovely.memcached/trunk/src/lovely/memcached/configure.zcml
A lovely.memcached/trunk/src/lovely/memcached/interfaces.py
A lovely.memcached/trunk/src/lovely/memcached/tests.py
A lovely.memcached/trunk/src/lovely/memcached/utility.py
-=-
Added: lovely.memcached/trunk/README.txt
===================================================================
--- lovely.memcached/trunk/README.txt 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/README.txt 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,6 @@
+================
+lovely.memcached
+================
+
+This package provides a zope3 utility that abstracts a client for
+memcached servers see: http://www.danga.com/memcached.
Property changes on: lovely.memcached/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/bootstrap.py
===================================================================
--- lovely.memcached/trunk/bootstrap.py 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/bootstrap.py 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+ ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+ cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+ os.P_WAIT, sys.executable, sys.executable,
+ '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+ dict(os.environ,
+ PYTHONPATH=
+ ws.find(pkg_resources.Requirement.parse('setuptools')).location
+ ),
+ ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)
Property changes on: lovely.memcached/trunk/bootstrap.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/buildout.cfg
===================================================================
--- lovely.memcached/trunk/buildout.cfg 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/buildout.cfg 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,10 @@
+[buildout]
+develop = .
+parts = test
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = lovely.memcached [test]
+
+
+
Property changes on: lovely.memcached/trunk/buildout.cfg
___________________________________________________________________
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/setup.cfg
===================================================================
--- lovely.memcached/trunk/setup.cfg 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/setup.cfg 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,2 @@
+[egg_info]
+tag_svn_revision = 1
Property changes on: lovely.memcached/trunk/setup.cfg
___________________________________________________________________
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/setup.py
===================================================================
--- lovely.memcached/trunk/setup.py 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/setup.py 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,27 @@
+#!python
+from setuptools import setup, find_packages
+
+setup (
+ name='lovely.memcached',
+ version='0.1dev',
+ author = "Lovely Systems",
+ author_email = "office at lovelysystems.com",
+ description = "A memcached client utiltiy for zope 3",
+ license = "ZPL 2.1",
+ keywords = "zope3 zope memcached cache ram",
+ url = 'svn://svn.zope.org/repos/main/lovely.memcached',
+ packages = find_packages('src'),
+ include_package_data = True,
+ package_dir = {'':'src'},
+ namespace_packages = ['lovely'],
+ extras_require = dict(test = ['zope.app.testing',
+ 'zope.app.securitypolicy',
+ 'zope.app.zcmlfiles',
+ 'zope.testbrowser']),
+ install_requires = ['setuptools',
+ 'python-memcached',
+ 'ZODB3',
+ 'zope.schema',
+ ],
+ dependency_links = ['http://download.zope.org/distribution']
+ )
Property changes on: lovely.memcached/trunk/setup.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/__init__.py
===================================================================
--- lovely.memcached/trunk/src/lovely/__init__.py 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/__init__.py 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,5 @@
+# this is a namespace package
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ pass
Property changes on: lovely.memcached/trunk/src/lovely/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/README.txt
===================================================================
--- lovely.memcached/trunk/src/lovely/memcached/README.txt 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/memcached/README.txt 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,94 @@
+================
+lovely.memcached
+================
+
+This package provides a utility that abstracts a client for memcached
+servers see: http://www.danga.com/memcached.
+
+IMPORTANT:
+
+This test expects a memcache server running on local port 11211 which
+is the default port for memcached.
+
+This test runs in level 2 because it needs external resources to work. If you
+want to run this test you need to use --all as parameter to your test.
+
+Start a memcache instance with : memcached <optional options>
+
+ >>> from lovely.memcached.utility import MemcachedClient
+ >>> util = MemcachedClient()
+ >>> util.servers
+ ['127.0.0.1:11211']
+ >>> util.defaultLifetime
+ 3600
+
+To store a new value in the cache we just need to set it.
+
+ >>> util.set('cached value', 'cache_key')
+ >>> util.query('cache_key')
+ 'cached value'
+
+If we no longer need the cached value we can invalidate it.
+
+ >>> util.invalidate('cache_key')
+ >>> util.query('cache_key') is None
+ True
+
+We have extended the original implementation on memcache.py for unicode.
+
+ >>> util.set(u'cached value ä', 'cache_key')
+ >>> util.query('cache_key') == u'cached value ä'
+ True
+
+We can invalidate the hole cache.
+
+ >>> util.invalidateAll()
+ >>> util.query('cache_key') is None
+ True
+
+Namespaces
+==========
+
+The utility provides the facility to use namespaces for keys in order
+to let multiple utilities share the same memcached servers. A default
+namespace can be set on the utility which is then used for any get and
+query methods.
+
+ >>> util1 = MemcachedClient(defaultNS=u'1')
+ >>> util2 = MemcachedClient(defaultNS=u'2')
+ >>> util1.set(1,1)
+ >>> util2.set(2,2)
+ >>> util1.query(1)
+ 1
+ >>> util1.query(2) is None
+ True
+ >>> util1.query(2, ns=u'2')
+ 2
+ >>> util2.query(2)
+ 2
+ >>> util2.query(1) is None
+ True
+
+Note that if invalidatAll is called then all namespaces are deleted.
+
+ >>> util1.invalidateAll()
+ >>> util1.query(1) is util2.query(2) is None
+ True
+
+Statistics
+==========
+
+This returns the stats for each server connected.
+
+ >>> util.getStatistics()
+ [('127.0.0.1:11211 (1)', {'total_items':...]
+
+If we use a server which doesn't exist we can still use the cache but noting
+will be stored. This behaviour allows us to run without a connected memcache
+server. As soon as a server is back online it will immediately used.
+
+ >>> util.servers = ['127.0.0.1:8125']
+ >>> util.set('cached value', 'cache_object')
+ >>> util.query('cache_object') is None
+ True
+
Property changes on: lovely.memcached/trunk/src/lovely/memcached/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/__init__.py
===================================================================
Property changes on: lovely.memcached/trunk/src/lovely/memcached/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/browser/README.txt
===================================================================
--- lovely.memcached/trunk/src/lovely/memcached/browser/README.txt 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/memcached/browser/README.txt 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,32 @@
+==============================
+Memcached utilit browser views
+==============================
+
+Let us add a memcached utility.
+
+ >>> from zope.testbrowser.testing import Browser
+ >>> browser = Browser()
+ >>> browser.addHeader('Authorization','Basic mgr:mgrpw')
+ >>> browser.handleErrors = False
+
+ >>> browser.open('http://localhost/@@contents.html')
+ >>> browser.getLink('Memcached Client').click()
+ >>> browser.getControl(name="new_value").value=u'mc'
+ >>> browser.getControl('Apply').click()
+ >>> browser.open('http://localhost/mc/manage')
+ >>> browser.getLink('Configure').click()
+ >>> browser.url
+ 'http://localhost/mc/@@configure.html'
+
+ >>> browser.getControl('Default Lifetime').value = '5400'
+ >>> browser.getControl('Change').click()
+ >>> browser.getControl('Default Lifetime').value
+ '5400'
+
+Let's look at the stats.
+
+ >>> browser.getLink('Statistics').click()
+ >>> browser.url
+ 'http://localhost/mc/@@stats.html'
+ >>> '<th>127.0.0.1:11211 (1)</th>' in browser.contents
+ True
Property changes on: lovely.memcached/trunk/src/lovely/memcached/browser/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/browser/__init__.py
===================================================================
Property changes on: lovely.memcached/trunk/src/lovely/memcached/browser/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/browser/configure.zcml
===================================================================
--- lovely.memcached/trunk/src/lovely/memcached/browser/configure.zcml 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/memcached/browser/configure.zcml 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,30 @@
+<configure
+ xmlns="http://namespaces.zope.org/browser"
+ i18n_domain="zope"
+ >
+
+ <addMenuItem
+ title="Memcached Client"
+ description="Add a memcached client"
+ class="..utility.MemcachedClient"
+ permission="zope.ManageServices"
+ />
+
+ <editform
+ schema="..interfaces.IMemcachedClient"
+ label="Configure"
+ name="configure.html"
+ menu="zmi_views" title="Configure"
+ permission="zope.ManageServices"
+ />
+
+ <page
+ name="stats.html"
+ menu="zmi_views"
+ title="Statistics"
+ for="..interfaces.IMemcachedClient"
+ permission="zope.ManageServices"
+ template="stats.pt"
+ />
+
+</configure>
\ No newline at end of file
Property changes on: lovely.memcached/trunk/src/lovely/memcached/browser/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/browser/ftesting.zcml
===================================================================
--- lovely.memcached/trunk/src/lovely/memcached/browser/ftesting.zcml 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/memcached/browser/ftesting.zcml 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,65 @@
+<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.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="lovely.memcached" />
+
+ <grantAll role="zope.Manager" />
+
+</configure>
Property changes on: lovely.memcached/trunk/src/lovely/memcached/browser/ftesting.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/browser/stats.pt
===================================================================
--- lovely.memcached/trunk/src/lovely/memcached/browser/stats.pt 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/memcached/browser/stats.pt 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,38 @@
+<html metal:use-macro="context/@@standard_macros/view"
+ i18n:domain="zope">
+<body>
+<div metal:fill-slot="body">
+
+ <p><span tal:replace="context/zope:name"/>
+ <span i18n:translate="">Memcached statistics</span></p>
+
+
+ <div tal:define="stats context/getStatistics"
+ tal:condition="stats">
+
+ <metal:block tal:define="rows python:sorted(stats[0][1].keys());
+ colNames python:map(lambda x: x[0], stats);
+ colData python:map(lambda x: x[1], stats);">
+
+ <table border="1" cellpadding="2">
+ <thead>
+ <th> </th>
+ <th tal:repeat="colName colNames" tal:content="colName"/>
+ </thead>
+ <tbody>
+ <tr tal:repeat="row rows">
+ <th tal:content="row" align="left"/>
+ <td tal:repeat="colName colNames"
+ tal:content="python:colData[repeat['colName'].index()][row]"/>
+ </tr>
+
+ </tbody>
+ </table>
+
+ </metal:block>
+ </div>
+
+</div>
+</body>
+</html>
+
Property changes on: lovely.memcached/trunk/src/lovely/memcached/browser/stats.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/browser/tests.py
===================================================================
--- lovely.memcached/trunk/src/lovely/memcached/browser/tests.py 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/memcached/browser/tests.py 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,32 @@
+##############################################################################
+#
+# Copyright (c) 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.testing import doctest
+from zope.app.testing import functional
+
+functional.defineLayer('MemcachedLayer', 'ftesting.zcml')
+
+def test_suite():
+ suite = functional.FunctionalDocFileSuite('README.txt')
+ suite.layer = MemcachedLayer
+ suite.level = 2
+ return unittest.TestSuite((suite,))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: lovely.memcached/trunk/src/lovely/memcached/browser/tests.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/configure.zcml
===================================================================
--- lovely.memcached/trunk/src/lovely/memcached/configure.zcml 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/memcached/configure.zcml 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,26 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ i18n_domain="zope"
+ >
+
+ <class class=".utility.MemcachedClient">
+ <implements
+ interface="zope.annotation.interfaces.IAttributeAnnotatable"
+ />
+
+ <require
+ permission="zope.View"
+ interface=".interfaces.IMemcachedClient"
+ />
+
+ <require
+ permission="zope.ManageServices"
+ set_schema=".interfaces.IMemcachedClient"
+ />
+ </class>
+
+ <include package=".browser"/>
+
+</configure>
+
Property changes on: lovely.memcached/trunk/src/lovely/memcached/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/interfaces.py
===================================================================
--- lovely.memcached/trunk/src/lovely/memcached/interfaces.py 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/memcached/interfaces.py 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,66 @@
+##############################################################################
+#
+# Copyright (c) 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 IMemcachedClient(interface.Interface):
+
+ """A memcache client utility"""
+
+ defaultNS = schema.TextLine(
+ title=u'Default Namespace',
+ description=u"The default namespace used by this client",
+ required=False,
+ default=None)
+
+ servers = schema.List(
+ title = u'Servers',
+ description = u"Servers defined as <hostname>:<port>",
+ value_type = schema.BytesLine(),
+ required = True,
+ default=['127.0.0.1:11211']
+ )
+
+ defaultLifetime = schema.Int(
+ title = u'Default Lifetime',
+ description = u'The default lifetime of entries',
+ required = True,
+ default = 3600,
+ )
+
+
+ def getStatistics():
+ """returns the memcached stats"""
+
+ def set(data, key, lifetime=None, ns=None):
+ """Sets data with the given key in namespace. Lifetime
+ defaults to defautlLifetime and ns defaults to the
+ default namespace"""
+
+ def query(key, default=None, ns=None):
+ """query the cache for key in namespace, returns default if
+ not found. ns defaults to default namespace."""
+
+ def invalidate(key, ns=None):
+ """invalidates key in namespace which defaults to default
+ namespace, currently we can not invalidate just a namespace"""
+
+ def invalidateAll():
+ """invalidates all data of the memcached servers, not that all
+ namespaces are invalidated"""
Property changes on: lovely.memcached/trunk/src/lovely/memcached/interfaces.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/tests.py
===================================================================
--- lovely.memcached/trunk/src/lovely/memcached/tests.py 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/memcached/tests.py 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,41 @@
+##############################################################################
+#
+# Copyright (c) 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.testing import doctest
+from zope.testing.doctestunit import DocTestSuite, DocFileSuite
+
+def test_suite():
+ level1Suites = (
+ DocTestSuite(
+ 'lovely.memcached.utility',
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+ ),
+ )
+ level2Suites = (
+ DocFileSuite(
+ 'README.txt',
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+ ),
+ )
+ for suite in level2Suites:
+ suite.level = 2
+ return unittest.TestSuite(level2Suites + level1Suites)
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: lovely.memcached/trunk/src/lovely/memcached/tests.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: lovely.memcached/trunk/src/lovely/memcached/utility.py
===================================================================
--- lovely.memcached/trunk/src/lovely/memcached/utility.py 2007-03-30 10:28:05 UTC (rev 73943)
+++ lovely.memcached/trunk/src/lovely/memcached/utility.py 2007-03-30 10:28:31 UTC (rev 73944)
@@ -0,0 +1,146 @@
+##############################################################################
+#
+# Copyright (c) 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 md5
+import logging
+import memcache
+import cPickle
+from threading import local
+import persistent
+
+from zope.schema.fieldproperty import FieldProperty
+from zope import interface
+from interfaces import IMemcachedClient
+
+log = logging.getLogger('lovely.memcached')
+
+class MemcachedClient(persistent.Persistent):
+ interface.implements(IMemcachedClient)
+
+ defaultNS = FieldProperty(IMemcachedClient['defaultNS'])
+ servers = FieldProperty(IMemcachedClient['servers'])
+ defaultLifetime = FieldProperty(IMemcachedClient['defaultLifetime'])
+
+ def __init__(self, servers=None, defaultAge=None,
+ defaultNS=None):
+ if servers is not None:
+ self.servers = servers
+ if defaultAge is not None:
+ self.defaultAge = defaultAge
+ if defaultNS is not None:
+ self.defaultNS = defaultNS
+
+ def getStatistics(self):
+ return self.client.get_stats()
+
+ def set(self, data, key, lifetime=None, ns=None):
+ if lifetime is None:
+ lifetime = self.defaultLifetime
+ ns = ns or self.defaultNS or None
+
+ data = cPickle.dumps(data)
+ log.debug('set: %r, %r, %r, %r' % (key, len(data), ns, lifetime))
+ self.client.set(self._buildKey(key, ns), data, lifetime)
+
+ def query(self, key, default=None, ns=None):
+ ns = ns or self.defaultNS or None
+ res = self.client.get(self._buildKey(key, ns))
+ if res is None:
+ return default
+ return cPickle.loads(res)
+
+ def invalidate(self, key, ns=None):
+ ns = ns or self.defaultNS or None
+ log.debug('invalidate: %r, %r '% (key, ns))
+ self.client.delete(self._buildKey(key, ns))
+
+ def invalidateAll(self):
+ # notice this does not look at namespaces
+ self.client.flush_all()
+
+ def _buildKey(self, key, ns):
+
+ """builds a key for key and ns, if key is a persistent
+ object its oid is used
+
+ >>> vc1 = MemcachedClient()
+ >>> k1 = vc1._buildKey(1, None)
+
+ of course the key is the same for same arguments
+ >>> k1 == vc1._buildKey(1, None)
+ True
+
+ the key is an md5 digest
+ >>> len(k1)
+ 32
+
+ for different namespaces the keys are different
+
+ >>> vc2 = MemcachedClient()
+ >>> k2 = vc2._buildKey(1, u'vc2')
+ >>> k2 != k1
+ True
+
+ if key has an oid this is taken
+
+ >>> class A: pass
+ >>> a = A()
+ >>> b = A()
+ >>> a._p_oid = "oid of a"
+ >>> b._p_oid = "oid of a"
+ >>> ka1 = vc1._buildKey(a, 1)
+ >>> kb1 = vc1._buildKey(b, 1)
+ >>> ka1 == kb1
+ True
+ >>> b._p_oid = "oid of b"
+ >>> kb1 = vc1._buildKey(b, 1)
+ >>> ka1 == kb1
+ False
+
+ """
+ oid = getattr(key, '_p_oid', None)
+ if oid is not None:
+ key = oid
+ if ns is not None:
+ m = md5.new(cPickle.dumps((ns, key)))
+ else:
+ m = md5.new(cPickle.dumps(key))
+ return m.hexdigest()
+
+ @property
+ def client(self):
+ servers = getattr(self.storage, 'servers', None)
+ if servers is not self.servers:
+ # we have a change in the list of servers
+ self.storage.client = None
+ self.storage.servers = self.servers
+ client = getattr(self.storage, 'client', None)
+ if client is None:
+ client = memcache.Client(self.servers, debug=0)
+ self.storage.client = client
+ return client
+
+ @property
+ def storage(self):
+ # we use a thread local storage to have a memcache client for every
+ # thread.
+ if not hasattr(self, '_v_storage'):
+ self._v_storage = local()
+ return self._v_storage
+
Property changes on: lovely.memcached/trunk/src/lovely/memcached/utility.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
More information about the Checkins
mailing list