[Checkins] SVN: zc.zk/trunk/src/zc/zk/ Added ``walk`` and ``is_ephemeral`` methods.

Jim Fulton jim at zope.com
Fri Jan 27 18:00:03 UTC 2012


Log message for revision 124218:
  Added ``walk`` and ``is_ephemeral`` methods.
  
  Fixed testing: When running with a real ZooKeeper server, the
  (virtual) root didn't have a ``zookeeper`` node.
  

Changed:
  U   zc.zk/trunk/src/zc/zk/README.txt
  U   zc.zk/trunk/src/zc/zk/__init__.py
  U   zc.zk/trunk/src/zc/zk/testing.py
  U   zc.zk/trunk/src/zc/zk/tests.py

-=-
Modified: zc.zk/trunk/src/zc/zk/README.txt
===================================================================
--- zc.zk/trunk/src/zc/zk/README.txt	2012-01-27 16:59:08 UTC (rev 124217)
+++ zc.zk/trunk/src/zc/zk/README.txt	2012-01-27 18:00:02 UTC (rev 124218)
@@ -845,7 +845,58 @@
 specifing access control lists. Use the ``--help`` option to see how
 to use it.
 
+Iterating over a tree
+=====================
 
+The ``walk`` method can be used to walk over the nodes in a tree:
+
+    >>> for path in zk.walk():
+    ...     print path
+    /
+    /cms
+    /cms/databases
+    /cms/providers
+    /cms/providers/1.2.3.4:5
+    /databases
+    /databases/cms
+    /fooservice
+    /fooservice/providers
+    /fooservice/providers/192.168.0.42:8080
+    /fooservice/providers/192.168.0.42:8081
+    /fooservice/providers/192.168.0.42:8082
+    /fooservice/provision
+    /fooservice/provision/node1
+    /fooservice/provision/node2
+    /lb
+    /lb/pools
+    /lb/pools/cms
+    /zookeeper
+    /zookeeper/quota
+
+    >>> for path in zk.walk('/fooservice'):
+    ...     print path
+    /fooservice
+    /fooservice/providers
+    /fooservice/providers/192.168.0.42:8080
+    /fooservice/providers/192.168.0.42:8081
+    /fooservice/providers/192.168.0.42:8082
+    /fooservice/provision
+    /fooservice/provision/node1
+    /fooservice/provision/node2
+
+Modifications to nodes are reflected while traversing:
+
+    >>> for path in zk.walk('/fooservice'):
+    ...     print path
+    ...     if 'provision' in zk.get_children(path):
+    ...         zk.delete_recursive(path+'/provision')
+    /fooservice
+    /fooservice/providers
+    /fooservice/providers/192.168.0.42:8080
+    /fooservice/providers/192.168.0.42:8081
+    /fooservice/providers/192.168.0.42:8082
+
+
 Graph analysis
 ==============
 
@@ -969,6 +1020,9 @@
        Boolean, defaulting to false, indicating whether to do a dry
        run of the import, without applying any changes.
 
+``is_ephemeral(path)``
+   Return ``True`` if the node at ``path`` is ephemeral,``False`` otherwise.
+
 ``ln(source, destination)``
    Create a symbolic link at the destination path pointing to the
    source path.
@@ -1006,6 +1060,9 @@
 ``resolve(path)``
    Find the real path for the given path.
 
+``walk(path)``
+   Iterate over the nodes of a tree rooted at path.
+
 In addition, ``ZooKeeper`` instances provide access to the following
 ZooKeeper functions as methods: ``acreate``, ``add_auth``,
 ``adelete``, ``aexists``, ``aget``, ``aget_acl``, ``aget_children``,
@@ -1104,13 +1161,18 @@
 Change History
 ==============
 
-0.6.1 (2012-01-27)
+0.7.0 (2012-01-27)
 ------------------
 
+- Added ``walk`` and ``is_ephemeral`` methods.
+
 - Fixed testing: There were spurious errors when closing a testing
   ZooKeeper connection in which ephemeral nodes were created and when
   they were deleted by another session.
 
+- Fixed testing: When running with a real ZooKeeper server, the
+  (virtual) root didn't have a ``zookeeper`` node.
+
 0.6.0 (2012-01-25)
 ------------------
 

Modified: zc.zk/trunk/src/zc/zk/__init__.py
===================================================================
--- zc.zk/trunk/src/zc/zk/__init__.py	2012-01-27 16:59:08 UTC (rev 124217)
+++ zc.zk/trunk/src/zc/zk/__init__.py	2012-01-27 18:00:02 UTC (rev 124218)
@@ -461,7 +461,7 @@
             print "%s not deleted due to ephemeral descendent." % path
             return ephemeral_child
 
-        ephemeral = self.get(path)[1]['ephemeralOwner'] and not force
+        ephemeral = self.is_ephemeral(path) and not force
         if dry_run:
             if ephemeral:
                 print "wouldn't delete %s because it's ephemeral." % path
@@ -475,6 +475,9 @@
                 self.delete(path)
         return ephemeral
 
+    def is_ephemeral(self, path):
+        return bool(self.get(path)[1]['ephemeralOwner'])
+
     def export_tree(self, path='/', ephemeral=False, name=None):
         output = []
         out = output.append
@@ -521,7 +524,6 @@
     def _set(self, path, data):
         return self.set(path, data)
 
-
     def ln(self, target, source):
         base, name = source.rsplit('/', 1)
         if target[-1] == '/':
@@ -540,6 +542,15 @@
             return zookeeper.CONNECTING_STATE
         return zookeeper.state(self.handle)
 
+    def walk(self, path='/'):
+        yield path
+        for name in sorted(self.get_children(path)):
+            if path != '/':
+                name = '/'+name
+            for p in self.walk(path+name):
+                yield p
+
+
 def _make_method(name):
     return (lambda self, *a, **kw:
             getattr(zookeeper, name)(self.handle, *a, **kw))

Modified: zc.zk/trunk/src/zc/zk/testing.py
===================================================================
--- zc.zk/trunk/src/zc/zk/testing.py	2012-01-27 16:59:08 UTC (rev 124217)
+++ zc.zk/trunk/src/zc/zk/testing.py	2012-01-27 18:00:02 UTC (rev 124218)
@@ -59,7 +59,8 @@
         if time.time() > deadline:
             raise AssertionError('timeout')
 
-def setup_tree(tree, connection_string, root='/test-root'):
+def setup_tree(tree, connection_string, root='/test-root',
+               zookeeper_node=False):
     zk = zc.zk.ZooKeeper(connection_string)
     if zk.exists(root):
         zk.delete_recursive(root)
@@ -71,6 +72,13 @@
       threads = 1
       favorite_color = 'red'
     """, root)
+
+    if zookeeper_node:
+        zk.import_tree("""
+        /zookeeper
+          /quota
+        """, root)
+
     zk.close()
 
 def testing_with_real_zookeeper():
@@ -126,7 +134,7 @@
     if real_zk:
         test_root = '/zc.zk.testing.test-root%s' % random.randint(0, sys.maxint)
         globs['/zc.zk.testing.test-root'] = test_root
-        setup_tree(tree, real_zk, test_root)
+        setup_tree(tree, real_zk, test_root, True)
 
         orig_init = zookeeper.init
         cm = mock.patch('zookeeper.init')

Modified: zc.zk/trunk/src/zc/zk/tests.py
===================================================================
--- zc.zk/trunk/src/zc/zk/tests.py	2012-01-27 16:59:08 UTC (rev 124217)
+++ zc.zk/trunk/src/zc/zk/tests.py	2012-01-27 18:00:02 UTC (rev 124218)
@@ -1450,6 +1450,18 @@
     >>> zk.close()
     """
 
+def is_ephemeral():
+    """
+    >>> zk = zc.zk.ZooKeeper('zookeeper.example.com:2181')
+    >>> zk.register_server('/fooservice/providers', 'a:b')
+    >>> zk.is_ephemeral('/fooservice')
+    False
+    >>> zk.is_ephemeral('/fooservice/providers')
+    False
+    >>> zk.is_ephemeral('/fooservice/providers/a:b')
+    True
+    >>> zk.close()
+    """
 
 # XXX
 # deleting linked node



More information about the checkins mailing list