def test_FactoryNode(self): class TestFactoryNode(FactoryNode): factories = odict() factories['foo'] = BaseNode factories['bar'] = BaseNode node = TestFactoryNode() # static factories self.assertTrue( str(node['foo']).startswith("<BaseNode object 'foo' at")) self.assertTrue( str(node['bar']).startswith("<BaseNode object 'bar' at")) self.expect_error(KeyError, lambda: node['baz']) self.assertEqual(list([it for it in node]), ['foo', 'bar']) self.assertTrue(IInvalidate.providedBy(node)) self.assertEqual(node.values(), [node['foo'], node['bar']]) # invalidate node.invalidate() self.assertEqual(node.storage.values(), []) self.assertEqual(node.values(), [node['foo'], node['bar']]) self.assertEqual(node.storage.values(), [node['foo'], node['bar']]) node.invalidate('foo') self.assertEqual(node.storage.values(), [node['bar']])
def test_Invalidate(self): # When using default ``Invalidate``, Contents of node just gets # deleted. Be aware this implementation must not be used on persisting # nodes. # Build invalidating node @plumbing( Adopt, Invalidate, DefaultInit, Nodify, OdictStorage) class Node(object): pass # Test tree root = Node() root['c1'] = Node() root['c2'] = Node() root['c2']['d1'] = Node() root['c2']['d2'] = Node() self.assertTrue(IInvalidate.providedBy(root)) self.assertFalse(ICache.providedBy(root)) self.assertEqual(root.treerepr(), ( '<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c1\n' ' <class \'node.tests.test_cache.Node\'>: c2\n' ' <class \'node.tests.test_cache.Node\'>: d1\n' ' <class \'node.tests.test_cache.Node\'>: d2\n' )) # Active invalidation of child by key root.invalidate(key='c1') self.assertEqual(root.treerepr(), ( '<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c2\n' ' <class \'node.tests.test_cache.Node\'>: d1\n' ' <class \'node.tests.test_cache.Node\'>: d2\n' )) err = self.expect_error(KeyError, root.invalidate, key='c1') self.assertEqual(str(err), '\'c1\'') # Active invalidation of all children root['c2'].invalidate() self.assertEqual(root.treerepr(), ( '<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c2\n' ))
def test_VolatileStorageInvalidate(self): # When a node internally uses a volatile storage like ``DictStorage`` # or ``OdictStorage``, some can use ``VolatileStorageInvalidate`` for # invalidation @plumbing( Adopt, VolatileStorageInvalidate, DefaultInit, Nodify, OdictStorage) class Node(object): pass # Test tree: root = Node() root['c1'] = Node() root['c2'] = Node() root['c2']['d1'] = Node() root['c2']['d2'] = Node() self.assertTrue(IInvalidate.providedBy(root)) self.assertFalse(ICache.providedBy(root)) self.assertEqual(root.treerepr(), ( '<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c1\n' ' <class \'node.tests.test_cache.Node\'>: c2\n' ' <class \'node.tests.test_cache.Node\'>: d1\n' ' <class \'node.tests.test_cache.Node\'>: d2\n' )) # Active invalidation of child by key root.invalidate(key='c1') self.assertEqual(root.treerepr(), ( '<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c2\n' ' <class \'node.tests.test_cache.Node\'>: d1\n' ' <class \'node.tests.test_cache.Node\'>: d2\n' )) err = self.expect_error(KeyError, root.invalidate, key='c1') self.assertEqual(str(err), '\'c1\'') # Active invalidation of all children root['c2'].invalidate() self.assertEqual(root.treerepr(), ( '<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c2\n' ))
def test_Invalidate(self): # When using default ``Invalidate``, Contents of node just gets # deleted. Be aware this implementation must not be used on persisting # nodes. # Build invalidating node @plumbing(Adopt, Invalidate, DefaultInit, Nodify, OdictStorage) class Node(object): pass # Test tree root = Node() root['c1'] = Node() root['c2'] = Node() root['c2']['d1'] = Node() root['c2']['d2'] = Node() self.assertTrue(IInvalidate.providedBy(root)) self.assertFalse(ICache.providedBy(root)) self.assertEqual(root.treerepr(), ('<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c1\n' ' <class \'node.tests.test_cache.Node\'>: c2\n' ' <class \'node.tests.test_cache.Node\'>: d1\n' ' <class \'node.tests.test_cache.Node\'>: d2\n')) # Active invalidation of child by key root.invalidate(key='c1') self.assertEqual(root.treerepr(), ('<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c2\n' ' <class \'node.tests.test_cache.Node\'>: d1\n' ' <class \'node.tests.test_cache.Node\'>: d2\n')) err = self.expectError(KeyError, root.invalidate, key='c1') self.assertEqual(str(err), '\'c1\'') # Active invalidation of all children root['c2'].invalidate() self.assertEqual(root.treerepr(), ('<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c2\n'))
def test_VolatileStorageInvalidate(self): # When a node internally uses a volatile storage like ``DictStorage`` # or ``OdictStorage``, some can use ``VolatileStorageInvalidate`` for # invalidation @plumbing(Adopt, VolatileStorageInvalidate, DefaultInit, Nodify, OdictStorage) class Node(object): pass # Test tree: root = Node() root['c1'] = Node() root['c2'] = Node() root['c2']['d1'] = Node() root['c2']['d2'] = Node() self.assertTrue(IInvalidate.providedBy(root)) self.assertFalse(ICache.providedBy(root)) self.assertEqual(root.treerepr(), ('<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c1\n' ' <class \'node.tests.test_cache.Node\'>: c2\n' ' <class \'node.tests.test_cache.Node\'>: d1\n' ' <class \'node.tests.test_cache.Node\'>: d2\n')) # Active invalidation of child by key root.invalidate(key='c1') self.assertEqual(root.treerepr(), ('<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c2\n' ' <class \'node.tests.test_cache.Node\'>: d1\n' ' <class \'node.tests.test_cache.Node\'>: d2\n')) err = self.expectError(KeyError, root.invalidate, key='c1') self.assertEqual(str(err), '\'c1\'') # Active invalidation of all children root['c2'].invalidate() self.assertEqual(root.treerepr(), ('<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: c2\n'))
def test_FactoryNode(self): class TestFactoryNode(FactoryNode): factories = odict() factories['foo'] = BaseNode factories['bar'] = BaseNode node = TestFactoryNode() # static factories self.assertTrue(str(node['foo']).startswith("<BaseNode object 'foo' at")) self.assertTrue(str(node['bar']).startswith("<BaseNode object 'bar' at")) self.expect_error(KeyError, lambda: node['baz']) self.assertEqual(list([it for it in node]), ['foo', 'bar']) self.assertTrue(IInvalidate.providedBy(node)) self.assertEqual(node.values(), [node['foo'], node['bar']]) # invalidate node.invalidate() self.assertEqual(node.storage.values(), []) self.assertEqual(node.values(), [node['foo'], node['bar']]) self.assertEqual(node.storage.values(), [node['foo'], node['bar']]) node.invalidate('foo') self.assertEqual(node.storage.values(), [node['bar']])
def test_Cache(self): # Build a node with active invalidation and cache functionality @plumbing(Adopt, Cache, Invalidate, DefaultInit, Nodify, OdictStorage) class Node(object): pass root = Node() root['c1'] = Node() root['c2'] = Node() root['c2']['d1'] = Node() root['c2']['d2'] = Node() self.assertTrue(IInvalidate.providedBy(root)) self.assertTrue(ICache.providedBy(root)) # We just accessed 'c2' above, only cached value on root at the moment self.assertEqual(list(root.cache.keys()), ['c2']) expected = '<Node object \'c2\' at' self.assertTrue(str(root.cache['c2']).startswith(expected)) expected = '<Node object \'c1\' at' self.assertTrue(str(root['c1']).startswith(expected)) # After accessing 'c1', it is cached as well: self.checkOutput( """\ [('c1', <Node object 'c1' at ...>), ('c2', <Node object 'c2' at ...>)] """, str(sorted(root.cache.items()))) # Invalidate plumbing removes item from cache root.invalidate(key='c1') self.assertEqual(list(root.cache.keys()), ['c2']) root.invalidate() self.assertEqual(root.cache, {}) self.assertEqual(root.treerepr(), ('<class \'node.tests.test_cache.Node\'>: None\n')) # Test invalidation plumbing hook with missing cache values root['x1'] = Node() root['x2'] = Node() self.assertEqual(root.treerepr(), ('<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: x1\n' ' <class \'node.tests.test_cache.Node\'>: x2\n')) self.checkOutput( """\ [('x1', <Node object 'x1' at ...>), ('x2', <Node object 'x2' at ...>)] """, str(sorted(root.cache.items()))) del root.cache['x1'] del root.cache['x2'] root.invalidate(key='x1') self.assertEqual(root.treerepr(), ('<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: x2\n')) del root.cache['x2'] root.invalidate() self.assertEqual(root.treerepr(), ('<class \'node.tests.test_cache.Node\'>: None\n'))
def test_Cache(self): # Build a node with active invalidation and cache functionality @plumbing( Adopt, Cache, Invalidate, DefaultInit, Nodify, OdictStorage) class Node(object): pass root = Node() root['c1'] = Node() root['c2'] = Node() root['c2']['d1'] = Node() root['c2']['d2'] = Node() self.assertTrue(IInvalidate.providedBy(root)) self.assertTrue(ICache.providedBy(root)) # We just accessed 'c2' above, only cached value on root at the moment self.assertEqual(list(root.cache.keys()), ['c2']) expected = '<Node object \'c2\' at' self.assertTrue(str(root.cache['c2']).startswith(expected)) expected = '<Node object \'c1\' at' self.assertTrue(str(root['c1']).startswith(expected)) # After accessing 'c1', it is cached as well: self.check_output("""\ [('c1', <Node object 'c1' at ...>), ('c2', <Node object 'c2' at ...>)] """, str(sorted(root.cache.items()))) # Invalidate plumbing removes item from cache root.invalidate(key='c1') self.assertEqual(list(root.cache.keys()), ['c2']) root.invalidate() self.assertEqual(root.cache, {}) self.assertEqual(root.treerepr(), ( '<class \'node.tests.test_cache.Node\'>: None\n' )) # Test invalidation plumbing hook with missing cache values root['x1'] = Node() root['x2'] = Node() self.assertEqual(root.treerepr(), ( '<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: x1\n' ' <class \'node.tests.test_cache.Node\'>: x2\n' )) self.check_output("""\ [('x1', <Node object 'x1' at ...>), ('x2', <Node object 'x2' at ...>)] """, str(sorted(root.cache.items()))) del root.cache['x1'] del root.cache['x2'] root.invalidate(key='x1') self.assertEqual(root.treerepr(), ( '<class \'node.tests.test_cache.Node\'>: None\n' ' <class \'node.tests.test_cache.Node\'>: x2\n' )) del root.cache['x2'] root.invalidate() self.assertEqual(root.treerepr(), ( '<class \'node.tests.test_cache.Node\'>: None\n' ))