[Checkins] SVN: zope.cachedescriptors/tags/3.5.0/ Tag 3.5.0
Dan Korostelev
nadako at gmail.com
Mon Mar 9 18:57:29 EDT 2009
Log message for revision 97738:
Tag 3.5.0
Changed:
A zope.cachedescriptors/tags/3.5.0/
D zope.cachedescriptors/tags/3.5.0/CHANGES.txt
A zope.cachedescriptors/tags/3.5.0/CHANGES.txt
D zope.cachedescriptors/tags/3.5.0/README.txt
A zope.cachedescriptors/tags/3.5.0/README.txt
D zope.cachedescriptors/tags/3.5.0/buildout.cfg
A zope.cachedescriptors/tags/3.5.0/buildout.cfg
D zope.cachedescriptors/tags/3.5.0/setup.py
A zope.cachedescriptors/tags/3.5.0/setup.py
D zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/DEPENDENCIES.cfg
D zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/README.txt
A zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/README.txt
D zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/method.txt
A zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/method.txt
D zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/property.txt
A zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/property.txt
-=-
Deleted: zope.cachedescriptors/tags/3.5.0/CHANGES.txt
===================================================================
--- zope.cachedescriptors/trunk/CHANGES.txt 2009-03-09 20:52:08 UTC (rev 97720)
+++ zope.cachedescriptors/tags/3.5.0/CHANGES.txt 2009-03-09 22:57:29 UTC (rev 97738)
@@ -1,12 +0,0 @@
-Changes for zope.cachedescriptors
-=================================
-
-3.5.0 (unreleased)
-------------------
-
-- Removed dependency on ZODB.
-
-3.4.0 (2007-08-30)
-------------------
-
-Initial release as an independent package
Copied: zope.cachedescriptors/tags/3.5.0/CHANGES.txt (from rev 97737, zope.cachedescriptors/trunk/CHANGES.txt)
===================================================================
--- zope.cachedescriptors/tags/3.5.0/CHANGES.txt (rev 0)
+++ zope.cachedescriptors/tags/3.5.0/CHANGES.txt 2009-03-09 22:57:29 UTC (rev 97738)
@@ -0,0 +1,23 @@
+=======
+CHANGES
+=======
+
+3.5.0 (2009-02-10)
+------------------
+
+- Remove dependency on ZODB by allowing to specify storage factory for
+ ``zope.cachedescriptors.method.cachedIn`` which is now `dict` by default.
+ If you need to use BTree instead, you must pass it as `factory` argument
+ to the ``zope.cachedescriptors.method.cachedIn`` decorator.
+
+- Remove zpkg-related file.
+
+- Clean up package description and documentation a bit.
+
+- Change package mailing list address to zope-dev at zope.org, as
+ zope3-dev at zope.org is now retired.
+
+3.4.0 (2007-08-30)
+------------------
+
+Initial release as an independent package
Deleted: zope.cachedescriptors/tags/3.5.0/README.txt
===================================================================
--- zope.cachedescriptors/trunk/README.txt 2009-03-09 20:52:08 UTC (rev 97720)
+++ zope.cachedescriptors/tags/3.5.0/README.txt 2009-03-09 22:57:29 UTC (rev 97738)
@@ -1,4 +0,0 @@
-Cached Descriptors
-******************
-
-.. contents::
Copied: zope.cachedescriptors/tags/3.5.0/README.txt (from rev 97737, zope.cachedescriptors/trunk/README.txt)
===================================================================
--- zope.cachedescriptors/tags/3.5.0/README.txt (rev 0)
+++ zope.cachedescriptors/tags/3.5.0/README.txt 2009-03-09 22:57:29 UTC (rev 97738)
@@ -0,0 +1 @@
+See src/zope/cachedescriptors/README.txt.
Deleted: zope.cachedescriptors/tags/3.5.0/buildout.cfg
===================================================================
--- zope.cachedescriptors/trunk/buildout.cfg 2009-03-09 20:52:08 UTC (rev 97720)
+++ zope.cachedescriptors/tags/3.5.0/buildout.cfg 2009-03-09 22:57:29 UTC (rev 97738)
@@ -1,9 +0,0 @@
-[buildout]
-develop = .
-parts = test
-
-find-links = http://download.zope.org/distribution/
-
-[test]
-recipe = zc.recipe.testrunner
-eggs = zope.cachedescriptors
Copied: zope.cachedescriptors/tags/3.5.0/buildout.cfg (from rev 97737, zope.cachedescriptors/trunk/buildout.cfg)
===================================================================
--- zope.cachedescriptors/tags/3.5.0/buildout.cfg (rev 0)
+++ zope.cachedescriptors/tags/3.5.0/buildout.cfg 2009-03-09 22:57:29 UTC (rev 97738)
@@ -0,0 +1,7 @@
+[buildout]
+develop = .
+parts = test
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zope.cachedescriptors
Deleted: zope.cachedescriptors/tags/3.5.0/setup.py
===================================================================
--- zope.cachedescriptors/trunk/setup.py 2009-03-09 20:52:08 UTC (rev 97720)
+++ zope.cachedescriptors/tags/3.5.0/setup.py 2009-03-09 22:57:29 UTC (rev 97738)
@@ -1,66 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""Setup for zope.cachedescriptors package
-
-$Id$
-"""
-
-import os
-
-from setuptools import setup, find_packages
-
-def read(*rnames):
- return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
-
-long_description = (
- read('README.txt')
- + '\n' +
- read('CHANGES.txt')
- + '\n' +
- 'Detailed Documentation\n'
- '**********************\n'
- + '\n' +
- read('src', 'zope', 'cachedescriptors', 'README.txt')
- + '\n' +
- read('src', 'zope', 'cachedescriptors', 'property.txt')
- + '\n' +
- read('src', 'zope', 'cachedescriptors', 'method.txt')
- )
-
-setup(
- name='zope.cachedescriptors',
- version='3.5.0dev',
- url='http://pypi.python.org/pypi/zope.cachedescriptors',
- author='Zope Corporation and Contributors',
- author_email='zope3-dev at zope.org',
- license='ZPL 2.1',
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Zope Public License',
- 'Programming Language :: Python',
- 'Operating System :: OS Independent',
- 'Topic :: Internet :: WWW/HTTP',
- 'Topic :: Software Development',
- ],
- description='Zope3 Cached Descriptors',
- long_description=long_description,
-
- packages=find_packages('src'),
- package_dir={'': 'src'},
- namespace_packages=['zope',],
- include_package_data=True,
- install_requires=['setuptools'],
- zip_safe=False,
- )
Copied: zope.cachedescriptors/tags/3.5.0/setup.py (from rev 97737, zope.cachedescriptors/trunk/setup.py)
===================================================================
--- zope.cachedescriptors/tags/3.5.0/setup.py (rev 0)
+++ zope.cachedescriptors/tags/3.5.0/setup.py 2009-03-09 22:57:29 UTC (rev 97738)
@@ -0,0 +1,57 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Setup for zope.cachedescriptors package
+
+$Id$
+"""
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+ return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+setup(
+ name='zope.cachedescriptors',
+ version='3.5.0',
+ url='http://pypi.python.org/pypi/zope.cachedescriptors',
+ author='Zope Corporation and Contributors',
+ author_email='zope-dev at zope.org',
+ license='ZPL 2.1',
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: Zope Public License',
+ 'Programming Language :: Python',
+ 'Operating System :: OS Independent',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Topic :: Software Development',
+ ],
+ description='Method and property caching decorators',
+ long_description=\
+ '.. contents::\n\n' +
+ read('src', 'zope', 'cachedescriptors', 'README.txt')
+ + '\n' +
+ read('src', 'zope', 'cachedescriptors', 'property.txt')
+ + '\n' +
+ read('src', 'zope', 'cachedescriptors', 'method.txt')
+ + '\n' +
+ read('CHANGES.txt'),
+
+ packages=find_packages('src'),
+ package_dir={'': 'src'},
+ namespace_packages=['zope',],
+ include_package_data=True,
+ install_requires=['setuptools'],
+ zip_safe=False,
+ )
Deleted: zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/DEPENDENCIES.cfg
===================================================================
--- zope.cachedescriptors/trunk/src/zope/cachedescriptors/DEPENDENCIES.cfg 2009-03-09 20:52:08 UTC (rev 97720)
+++ zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/DEPENDENCIES.cfg 2009-03-09 22:57:29 UTC (rev 97738)
@@ -1 +0,0 @@
-persistent
Deleted: zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/README.txt
===================================================================
--- zope.cachedescriptors/trunk/src/zope/cachedescriptors/README.txt 2009-03-09 20:52:08 UTC (rev 97720)
+++ zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/README.txt 2009-03-09 22:57:29 UTC (rev 97738)
@@ -1,25 +0,0 @@
-Cached descriptors
-==================
-
-Cached descriptors cache their output. They take into account
-instance attributes that they depend on, so when the instance
-attributes change, the descriptors will change the values they
-return.
-
-Cached descriptors cache their data in _v_ attributes, so they are
-also useful for managing the computation of volatile attributes for
-persistent objects.
-
-Persistent descriptors:
-
- property
-
- A simple computed property. See property.txt.
-
- method
-
- Idempotent method. The return values are cached based on method
- arguments and on any instance attributes that the methods are
- defined to depend on.
-
- **Note**, only a cache based on arguments has been implemented so far.
Copied: zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/README.txt (from rev 97737, zope.cachedescriptors/trunk/src/zope/cachedescriptors/README.txt)
===================================================================
--- zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/README.txt (rev 0)
+++ zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/README.txt 2009-03-09 22:57:29 UTC (rev 97738)
@@ -0,0 +1,28 @@
+==================
+Cached descriptors
+==================
+
+Cached descriptors cache their output. They take into account
+instance attributes that they depend on, so when the instance
+attributes change, the descriptors will change the values they
+return.
+
+Cached descriptors cache their data in _v_ attributes, so they are
+also useful for managing the computation of volatile attributes for
+persistent objects.
+
+Persistent descriptors:
+
+ property
+
+ A simple computed property. See property.txt.
+
+ method
+
+ Idempotent method. The return values are cached based on method
+ arguments and on any instance attributes that the methods are
+ defined to depend on.
+
+ **Note**, only a cache based on arguments has been implemented so far.
+
+ See method.txt.
Deleted: zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/method.txt
===================================================================
--- zope.cachedescriptors/trunk/src/zope/cachedescriptors/method.txt 2009-03-09 20:52:08 UTC (rev 97720)
+++ zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/method.txt 2009-03-09 22:57:29 UTC (rev 97738)
@@ -1,88 +0,0 @@
-Method Cache
-============
-
-cachedIn
---------
-
-The `cachedIn` property allows to specify the attribute where to store the
-computed value:
-
- >>> import math
- >>> from zope.cachedescriptors import method
-
- >>> class Point(object):
- ...
- ... def __init__(self, x, y):
- ... self.x, self.y = x, y
- ...
- ... @method.cachedIn('_cache')
- ... def distance(self, x, y):
- ... print 'computing distance'
- ... return math.sqrt((self.x - x)**2 + (self.y - y)**2)
- ...
- >>> point = Point(1.0, 2.0)
-
-The value is computed once:
-
- >>> point.distance(2, 2)
- computing distance
- 1.0
- >>> point.distance(2, 2)
- 1.0
-
-
-Using different arguments calculates a new distance:
-
- >>> point.distance(5, 2)
- computing distance
- 4.0
- >>> point.distance(5, 2)
- 4.0
-
-
-The data is stored at the given `_cache` attribute:
-
- >>> isinstance(point._cache, dict)
- True
-
- >>> sorted(point._cache.items())
- [(((2, 2), ()), 1.0), (((5, 2), ()), 4.0)]
-
-
-It is possible to exlicitly invalidate the data:
-
- >>> point.distance.invalidate(point, 5, 2)
- >>> point.distance(5, 2)
- computing distance
- 4.0
-
-Invalidating keys which are not in the cache, does not result in an error:
-
- >>> point.distance.invalidate(point, 47, 11)
-
-
-It is possible to pass in a factory for the cache attribute. Create another
-Point class:
-
-
- >>> class MyDict(dict):
- ... pass
- >>> class Point(object):
- ...
- ... def __init__(self, x, y):
- ... self.x, self.y = x, y
- ...
- ... @method.cachedIn('_cache', MyDict)
- ... def distance(self, x, y):
- ... print 'computing distance'
- ... return math.sqrt((self.x - x)**2 + (self.y - y)**2)
- ...
- >>> point = Point(1.0, 2.0)
- >>> point.distance(2, 2)
- computing distance
- 1.0
-
-Now the cache is a MyDict instance:
-
- >>> isinstance(point._cache, MyDict)
- True
Copied: zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/method.txt (from rev 97737, zope.cachedescriptors/trunk/src/zope/cachedescriptors/method.txt)
===================================================================
--- zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/method.txt (rev 0)
+++ zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/method.txt 2009-03-09 22:57:29 UTC (rev 97738)
@@ -0,0 +1,88 @@
+Method Cache
+------------
+
+cachedIn
+~~~~~~~~
+
+The `cachedIn` property allows to specify the attribute where to store the
+computed value:
+
+ >>> import math
+ >>> from zope.cachedescriptors import method
+
+ >>> class Point(object):
+ ...
+ ... def __init__(self, x, y):
+ ... self.x, self.y = x, y
+ ...
+ ... @method.cachedIn('_cache')
+ ... def distance(self, x, y):
+ ... print 'computing distance'
+ ... return math.sqrt((self.x - x)**2 + (self.y - y)**2)
+ ...
+ >>> point = Point(1.0, 2.0)
+
+The value is computed once:
+
+ >>> point.distance(2, 2)
+ computing distance
+ 1.0
+ >>> point.distance(2, 2)
+ 1.0
+
+
+Using different arguments calculates a new distance:
+
+ >>> point.distance(5, 2)
+ computing distance
+ 4.0
+ >>> point.distance(5, 2)
+ 4.0
+
+
+The data is stored at the given `_cache` attribute:
+
+ >>> isinstance(point._cache, dict)
+ True
+
+ >>> sorted(point._cache.items())
+ [(((2, 2), ()), 1.0), (((5, 2), ()), 4.0)]
+
+
+It is possible to exlicitly invalidate the data:
+
+ >>> point.distance.invalidate(point, 5, 2)
+ >>> point.distance(5, 2)
+ computing distance
+ 4.0
+
+Invalidating keys which are not in the cache, does not result in an error:
+
+ >>> point.distance.invalidate(point, 47, 11)
+
+
+It is possible to pass in a factory for the cache attribute. Create another
+Point class:
+
+
+ >>> class MyDict(dict):
+ ... pass
+ >>> class Point(object):
+ ...
+ ... def __init__(self, x, y):
+ ... self.x, self.y = x, y
+ ...
+ ... @method.cachedIn('_cache', MyDict)
+ ... def distance(self, x, y):
+ ... print 'computing distance'
+ ... return math.sqrt((self.x - x)**2 + (self.y - y)**2)
+ ...
+ >>> point = Point(1.0, 2.0)
+ >>> point.distance(2, 2)
+ computing distance
+ 1.0
+
+Now the cache is a MyDict instance:
+
+ >>> isinstance(point._cache, MyDict)
+ True
Deleted: zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/property.txt
===================================================================
--- zope.cachedescriptors/trunk/src/zope/cachedescriptors/property.txt 2009-03-09 20:52:08 UTC (rev 97720)
+++ zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/property.txt 2009-03-09 22:57:29 UTC (rev 97738)
@@ -1,208 +0,0 @@
-Cached Properties
-=================
-
-Cached properties are computed properties that cache their computed
-values. They take into account instance attributes that they depend
-on, so when the instance attributes change, the properties will change
-the values they return.
-
-Cached properties cache their data in _v_ attributes, so they are
-also useful for managing the computation of volatile attributes for
-persistent objects. Let's look at an example::
-
- >>> from zope.cachedescriptors import property
- >>> import math
-
- >>> class Point:
- ...
- ... def __init__(self, x, y):
- ... self.x, self.y = x, y
- ...
- ... def radius(self):
- ... print 'computing radius'
- ... return math.sqrt(self.x**2 + self.y**2)
- ... radius = property.CachedProperty(radius, 'x', 'y')
-
- >>> point = Point(1.0, 2.0)
-
-If we ask for the radius the first time::
-
- >>> '%.2f' % point.radius
- computing radius
- '2.24'
-
-We see that the radius function is called, but if we ask for it again::
-
- >>> '%.2f' % point.radius
- '2.24'
-
-The function isn't called. If we change one of the attribute the
-radius depends on, it will be recomputed::
-
- >>> point.x = 2.0
- >>> '%.2f' % point.radius
- computing radius
- '2.83'
-
-But changing other attributes doesn't cause recomputation::
-
- >>> point.q = 1
- >>> '%.2f' % point.radius
- '2.83'
-
-Note that we don't have any non-volitile attributes added::
-
- >>> names = [name for name in point.__dict__ if not name.startswith('_v_')]
- >>> names.sort()
- >>> names
- ['q', 'x', 'y']
-
-
-Lazy Computed Attributes
-------------------------
-
-The `property` module provides another descriptor that supports a
-slightly different caching model: lazy attributes. Like cached
-proprties, they are computed the first time they are used. however,
-they aren't stored in volatile attributes and they aren't
-automatically updated when other attributes change. Furthermore, the
-store their data using their attribute name, thus overriding
-themselves. This provides much faster attribute access after the
-attribute has been computed. Let's look at the previous example using
-lazy attributes::
-
- >>> class Point:
- ...
- ... def __init__(self, x, y):
- ... self.x, self.y = x, y
- ...
- ... def radius(self):
- ... print 'computing radius'
- ... return math.sqrt(self.x**2 + self.y**2)
- ... radius = property.Lazy(radius)
-
- >>> point = Point(1.0, 2.0)
-
-If we ask for the radius the first time::
-
- >>> '%.2f' % point.radius
- computing radius
- '2.24'
-
-We see that the radius function is called, but if we ask for it again::
-
- >>> '%.2f' % point.radius
- '2.24'
-
-The function isn't called. If we change one of the attribute the
-radius depends on, it still isn't called::
-
- >>> point.x = 2.0
- >>> '%.2f' % point.radius
- '2.24'
-
-If we want the radius to be recomputed, we have to manually delete it::
-
- >>> del point.radius
-
- >>> point.x = 2.0
- >>> '%.2f' % point.radius
- computing radius
- '2.83'
-
-Note that the radius is stored in the instance dictionary::
-
- >>> '%.2f' % point.__dict__['radius']
- '2.83'
-
-The lazy attribute needs to know the attribute name. It normally
-deduces the attribute name from the name of the function passed. If we
-want to use a different name, we need to pass it::
-
- >>> def d(point):
- ... print 'computing diameter'
- ... return 2*point.radius
-
- >>> Point.diameter = property.Lazy(d, 'diameter')
- >>> '%.2f' % point.diameter
- computing diameter
- '5.66'
-
-
-readproperties
-==============
-
-readproperties are like lazy computed attributes except that the
-attribute isn't set by the property::
-
-
- >>> class Point:
- ...
- ... def __init__(self, x, y):
- ... self.x, self.y = x, y
- ...
- ... def radius(self):
- ... print 'computing radius'
- ... return math.sqrt(self.x**2 + self.y**2)
- ... radius = property.readproperty(radius)
-
- >>> point = Point(1.0, 2.0)
-
- >>> '%.2f' % point.radius
- computing radius
- '2.24'
-
- >>> '%.2f' % point.radius
- computing radius
- '2.24'
-
-But you *can* replace the property by setting a value. This is the major
-difference to the builtin `property`::
-
- >>> point.radius = 5
- >>> point.radius
- 5
-
-
-cachedIn
-========
-
-The `cachedIn` property allows to specify the attribute where to store the
-computed value::
-
- >>> class Point:
- ...
- ... def __init__(self, x, y):
- ... self.x, self.y = x, y
- ...
- ... @property.cachedIn('_radius_attribute')
- ... def radius(self):
- ... print 'computing radius'
- ... return math.sqrt(self.x**2 + self.y**2)
-
- >>> point = Point(1.0, 2.0)
-
- >>> '%.2f' % point.radius
- computing radius
- '2.24'
-
- >>> '%.2f' % point.radius
- '2.24'
-
-The radius is cached in the attribute with the given name, `_radius_attribute`
-in this case::
-
- >>> '%.2f' % point._radius_attribute
- '2.24'
-
-When the attribute is removed the radius is re-calculated once. This allows
-invalidation::
-
- >>> del point._radius_attribute
-
- >>> '%.2f' % point.radius
- computing radius
- '2.24'
-
- >>> '%.2f' % point.radius
- '2.24'
Copied: zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/property.txt (from rev 97737, zope.cachedescriptors/trunk/src/zope/cachedescriptors/property.txt)
===================================================================
--- zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/property.txt (rev 0)
+++ zope.cachedescriptors/tags/3.5.0/src/zope/cachedescriptors/property.txt 2009-03-09 22:57:29 UTC (rev 97738)
@@ -0,0 +1,211 @@
+Cached Properties
+-----------------
+
+Cached properties are computed properties that cache their computed
+values. They take into account instance attributes that they depend
+on, so when the instance attributes change, the properties will change
+the values they return.
+
+CachedProperty
+~~~~~~~~~~~~~~
+
+Cached properties cache their data in _v_ attributes, so they are
+also useful for managing the computation of volatile attributes for
+persistent objects. Let's look at an example::
+
+ >>> from zope.cachedescriptors import property
+ >>> import math
+
+ >>> class Point:
+ ...
+ ... def __init__(self, x, y):
+ ... self.x, self.y = x, y
+ ...
+ ... def radius(self):
+ ... print 'computing radius'
+ ... return math.sqrt(self.x**2 + self.y**2)
+ ... radius = property.CachedProperty(radius, 'x', 'y')
+
+ >>> point = Point(1.0, 2.0)
+
+If we ask for the radius the first time::
+
+ >>> '%.2f' % point.radius
+ computing radius
+ '2.24'
+
+We see that the radius function is called, but if we ask for it again::
+
+ >>> '%.2f' % point.radius
+ '2.24'
+
+The function isn't called. If we change one of the attribute the
+radius depends on, it will be recomputed::
+
+ >>> point.x = 2.0
+ >>> '%.2f' % point.radius
+ computing radius
+ '2.83'
+
+But changing other attributes doesn't cause recomputation::
+
+ >>> point.q = 1
+ >>> '%.2f' % point.radius
+ '2.83'
+
+Note that we don't have any non-volitile attributes added::
+
+ >>> names = [name for name in point.__dict__ if not name.startswith('_v_')]
+ >>> names.sort()
+ >>> names
+ ['q', 'x', 'y']
+
+
+Lazy Computed Attributes
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The `property` module provides another descriptor that supports a
+slightly different caching model: lazy attributes. Like cached
+proprties, they are computed the first time they are used. however,
+they aren't stored in volatile attributes and they aren't
+automatically updated when other attributes change. Furthermore, the
+store their data using their attribute name, thus overriding
+themselves. This provides much faster attribute access after the
+attribute has been computed. Let's look at the previous example using
+lazy attributes::
+
+ >>> class Point:
+ ...
+ ... def __init__(self, x, y):
+ ... self.x, self.y = x, y
+ ...
+ ... @property.Lazy
+ ... def radius(self):
+ ... print 'computing radius'
+ ... return math.sqrt(self.x**2 + self.y**2)
+
+ >>> point = Point(1.0, 2.0)
+
+If we ask for the radius the first time::
+
+ >>> '%.2f' % point.radius
+ computing radius
+ '2.24'
+
+We see that the radius function is called, but if we ask for it again::
+
+ >>> '%.2f' % point.radius
+ '2.24'
+
+The function isn't called. If we change one of the attribute the
+radius depends on, it still isn't called::
+
+ >>> point.x = 2.0
+ >>> '%.2f' % point.radius
+ '2.24'
+
+If we want the radius to be recomputed, we have to manually delete it::
+
+ >>> del point.radius
+
+ >>> point.x = 2.0
+ >>> '%.2f' % point.radius
+ computing radius
+ '2.83'
+
+Note that the radius is stored in the instance dictionary::
+
+ >>> '%.2f' % point.__dict__['radius']
+ '2.83'
+
+The lazy attribute needs to know the attribute name. It normally
+deduces the attribute name from the name of the function passed. If we
+want to use a different name, we need to pass it::
+
+ >>> def d(point):
+ ... print 'computing diameter'
+ ... return 2*point.radius
+
+ >>> Point.diameter = property.Lazy(d, 'diameter')
+ >>> '%.2f' % point.diameter
+ computing diameter
+ '5.66'
+
+
+readproperty
+~~~~~~~~~~~~
+
+readproperties are like lazy computed attributes except that the
+attribute isn't set by the property::
+
+
+ >>> class Point:
+ ...
+ ... def __init__(self, x, y):
+ ... self.x, self.y = x, y
+ ...
+ ... @property.readproperty
+ ... def radius(self):
+ ... print 'computing radius'
+ ... return math.sqrt(self.x**2 + self.y**2)
+
+ >>> point = Point(1.0, 2.0)
+
+ >>> '%.2f' % point.radius
+ computing radius
+ '2.24'
+
+ >>> '%.2f' % point.radius
+ computing radius
+ '2.24'
+
+But you *can* replace the property by setting a value. This is the major
+difference to the builtin `property`::
+
+ >>> point.radius = 5
+ >>> point.radius
+ 5
+
+
+cachedIn
+~~~~~~~~
+
+The `cachedIn` property allows to specify the attribute where to store the
+computed value::
+
+ >>> class Point:
+ ...
+ ... def __init__(self, x, y):
+ ... self.x, self.y = x, y
+ ...
+ ... @property.cachedIn('_radius_attribute')
+ ... def radius(self):
+ ... print 'computing radius'
+ ... return math.sqrt(self.x**2 + self.y**2)
+
+ >>> point = Point(1.0, 2.0)
+
+ >>> '%.2f' % point.radius
+ computing radius
+ '2.24'
+
+ >>> '%.2f' % point.radius
+ '2.24'
+
+The radius is cached in the attribute with the given name, `_radius_attribute`
+in this case::
+
+ >>> '%.2f' % point._radius_attribute
+ '2.24'
+
+When the attribute is removed the radius is re-calculated once. This allows
+invalidation::
+
+ >>> del point._radius_attribute
+
+ >>> '%.2f' % point.radius
+ computing radius
+ '2.24'
+
+ >>> '%.2f' % point.radius
+ '2.24'
More information about the Checkins
mailing list