Skip to content
Browse files

Introduce ``node.behaviors.cache.VolatileStorageInvalidate``.

  • Loading branch information...
1 parent d6f952d commit 97ee741ce91d8139e434bc25cb0278d78875c32f @rnixx rnixx committed Jan 15, 2014
Showing with 122 additions and 25 deletions.
  1. +12 −1 README.rst
  2. +1 −1 setup.py
  3. +1 −0 src/node/behaviors/__init__.py
  4. +19 −0 src/node/behaviors/cache.py
  5. +89 −23 src/node/behaviors/cache.rst
View
13 README.rst
@@ -199,6 +199,10 @@ The ``node`` package provides several plumbing behaviors:
Plumbing part for node invalidation.
See ``node.interfaces.Invalidate``.
+**node.behaviors.VolatileStorageInvalidate**
+ Plumbing part for invalidating nodes using a volatile storage.
+ See ``node.interfaces.Invalidate``.
+
**node.behaviors.Cache**
Plumbing part for caching.
See ``node.interfaces.ICache``.
@@ -252,7 +256,7 @@ Summary of the test coverage report::
11 100% node.behaviors.__init__
107 100% node.behaviors.alias
38 100% node.behaviors.attributes
- 50 100% node.behaviors.cache
+ 60 100% node.behaviors.cache
118 100% node.behaviors.common
49 100% node.behaviors.lifecycle
114 100% node.behaviors.mapping
@@ -285,6 +289,13 @@ Contributors
Changes
=======
+0.9.13dev
+---------
+
+- Introduce ``node.behaviors.cache.VolatileStorageInvalidate``.
+ [rnix, 2014-01-15]
+
+
0.9.12
------
View
2 setup.py
@@ -5,7 +5,7 @@
)
-version = '0.9.12'
+version = '0.9.13dev'
shortdesc = "Building data structures as node trees"
longdesc = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
longdesc += open(os.path.join(os.path.dirname(__file__), 'LICENSE.rst')).read()
View
1 src/node/behaviors/__init__.py
@@ -5,6 +5,7 @@
)
from .cache import (
Invalidate,
+ VolatileStorageInvalidate,
Cache,
)
from .common import (
View
19 src/node/behaviors/cache.py
@@ -31,6 +31,25 @@ def invalidate(self, key=None):
del self[key]
+@implementer(IInvalidate)
+class VolatileStorageInvalidate(Behavior):
+ """Plumbing behavior for invalidating volatile storages like
+ ``DictStorage`` or ``OdictStorage``.
+ """
+
+ @default
+ def invalidate(self, key=None):
+ """Raise KeyError if child does not exist for key if given.
+ """
+ storage = self.storage
+ if key is not None:
+ del storage[key]
+ else:
+ # need to use keys instead of iter here
+ for key in self.keys():
+ del storage[key]
+
+
@implementer(ICache)
class Cache(Behavior):
View
112 src/node/behaviors/cache.rst
@@ -1,7 +1,7 @@
node.behaviors.invalidate
=========================
-::
+Required Imports::
>>> from plumber import plumber
>>> from node.interfaces import (
@@ -12,20 +12,86 @@ node.behaviors.invalidate
... Adopt,
... Cache,
... Invalidate,
+ ... VolatileStorageInvalidate,
... DefaultInit,
... Nodify,
... OdictStorage,
... )
-Build a node with active invalidation functionality::
+
+Default Invalidation
+--------------------
+
+When using default ``Invalidate``, Contents of node just gets deleted.
+Be aware this implementation must not be used on persisting nodes.
+
+Build invalidating node::
+
+ >>> class Node(object):
+ ... __metaclass__ = plumber
+ ... __plumbing__ = (
+ ... Adopt,
+ ... Invalidate,
+ ... DefaultInit,
+ ... Nodify,
+ ... OdictStorage,
+ ... )
+
+Test tree::
+
+ >>> root = Node()
+ >>> root['c1'] = Node()
+ >>> root['c2'] = Node()
+ >>> root['c2']['d1'] = Node()
+ >>> root['c2']['d2'] = Node()
+
+ >>> IInvalidate.providedBy(root)
+ True
+ >>> ICache.providedBy(root)
+ False
+
+ >>> root.printtree()
+ <class 'Node'>: None
+ <class 'Node'>: c1
+ <class 'Node'>: c2
+ <class 'Node'>: d1
+ <class 'Node'>: d2
+
+Active invalidation of child by key::
+
+ >>> root.invalidate(key='c1')
+ >>> root.printtree()
+ <class 'Node'>: None
+ <class 'Node'>: c2
+ <class 'Node'>: d1
+ <class 'Node'>: d2
+
+ >>> root.invalidate(key='c1')
+ Traceback (most recent call last):
+ ...
+ KeyError: 'c1'
+
+Active invalidation of all children::
+
+ >>> root['c2'].invalidate()
+ >>> root.printtree()
+ <class 'Node'>: None
+ <class 'Node'>: c2
+
+
+Volatile Storage Invalidate
+---------------------------
+
+When a node internally uses a volatile storage like ``DictStorage`` or
+``OdictStorage``, some can use ``VolatileStorageInvalidate`` for invalidation::
>>> class Node(object):
... __metaclass__ = plumber
... __plumbing__ = (
- ... Adopt,
- ... Invalidate,
+ ... Adopt,
+ ... VolatileStorageInvalidate,
... DefaultInit,
- ... Nodify,
+ ... Nodify,
... OdictStorage,
... )
@@ -36,12 +102,12 @@ Test tree::
>>> root['c2'] = Node()
>>> root['c2']['d1'] = Node()
>>> root['c2']['d2'] = Node()
-
+
>>> IInvalidate.providedBy(root)
True
>>> ICache.providedBy(root)
False
-
+
>>> root.printtree()
<class 'Node'>: None
<class 'Node'>: c1
@@ -50,14 +116,14 @@ Test tree::
<class 'Node'>: d2
Active invalidation of child by key::
-
+
>>> root.invalidate(key='c1')
>>> root.printtree()
<class 'Node'>: None
<class 'Node'>: c2
<class 'Node'>: d1
<class 'Node'>: d2
-
+
>>> root.invalidate(key='c1')
Traceback (most recent call last):
...
@@ -71,28 +137,28 @@ Active invalidation of all children::
<class 'Node'>: c2
-node.behaviors.cache
-====================
+Caching
+-------
Build a node with active invalidation and cache functionality::
>>> class Node(object):
... __metaclass__ = plumber
... __plumbing__ = (
- ... Adopt,
- ... Cache,
- ... Invalidate,
+ ... Adopt,
+ ... Cache,
+ ... Invalidate,
... DefaultInit,
- ... Nodify,
+ ... Nodify,
... OdictStorage,
... )
-
+
>>> root = Node()
>>> root['c1'] = Node()
>>> root['c2'] = Node()
>>> root['c2']['d1'] = Node()
>>> root['c2']['d2'] = Node()
-
+
>>> IInvalidate.providedBy(root)
True
>>> ICache.providedBy(root)
@@ -102,7 +168,7 @@ We just accessed 'c2' above, only cached value on root at the moment::
>>> root.cache
{'c2': <Node object 'c2' at ...>}
-
+
>>> root['c1']
<Node object 'c1' at ...>
@@ -121,7 +187,7 @@ Invalidate plumbing removes item from cache::
>>> root.invalidate()
>>> root.cache
{}
-
+
>>> root.printtree()
<class 'Node'>: None
@@ -133,19 +199,19 @@ Test invalidation plumbing hook with missing cache values::
<class 'Node'>: None
<class 'Node'>: x1
<class 'Node'>: x2
-
+
>>> root.cache
{'x2': <Node object 'x2' at ...>,
'x1': <Node object 'x1' at ...>}
-
+
>>> del root.cache['x1']
>>> del root.cache['x2']
-
+
>>> root.invalidate(key='x1')
>>> root.printtree()
<class 'Node'>: None
<class 'Node'>: x2
-
+
>>> del root.cache['x2']
>>> root.invalidate()
>>> root.printtree()

0 comments on commit 97ee741

Please sign in to comment.
Something went wrong with that request. Please try again.