Hello community,

here is the log from the commit of package python-zake for openSUSE:Factory 
checked in at 2014-07-02 15:04:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-zake (Old)
 and      /work/SRC/openSUSE:Factory/.python-zake.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-zake"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-zake/python-zake.changes  2014-04-03 
18:38:19.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python-zake.new/python-zake.changes     
2014-07-02 15:05:12.000000000 +0200
@@ -1,0 +2,7 @@
+Tue Jun 24 07:21:50 UTC 2014 - [email protected]
+
+- update to 0.0.20:
+  * Added testsuite
+  * Use concurrent.future for greater good
+
+-------------------------------------------------------------------

Old:
----
  zake-0.0.14.tar.gz

New:
----
  zake-0.0.20.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-zake.spec ++++++
--- /var/tmp/diff_new_pack.FgIBGW/_old  2014-07-02 15:05:13.000000000 +0200
+++ /var/tmp/diff_new_pack.FgIBGW/_new  2014-07-02 15:05:13.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python-zake
-Version:        0.0.14
+Version:        0.0.20
 Release:        0
 Summary:        Testing utilities for the kazoo library
 License:        Apache-2.0

++++++ zake-0.0.14.tar.gz -> zake-0.0.20.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/PKG-INFO new/zake-0.0.20/PKG-INFO
--- old/zake-0.0.14/PKG-INFO    2014-02-02 10:25:39.000000000 +0100
+++ new/zake-0.0.20/PKG-INFO    2014-05-10 21:10:25.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: zake
-Version: 0.0.14
+Version: 0.0.20
 Summary: A python package that works to provide a nice set of testing 
utilities for the kazoo library.
 Home-page: https://github.com/yahoo/Zake
 Author: Joshua Harlow
@@ -9,7 +9,8 @@
 Description: Zake
         ====
         
-        .. image:: https://travis-ci.org/yahoo/Zake.png?branch=master   
:target: https://travis-ci.org/yahoo/Zake
+        .. image:: https://travis-ci.org/yahoo/Zake.png?branch=master
+           :target: https://travis-ci.org/yahoo/Zake
         
         
         A python package that works to provide a nice set of testing utilities 
for the kazoo library.
@@ -34,3 +35,8 @@
 Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Operating System :: POSIX :: Linux
 Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/README.rst new/zake-0.0.20/README.rst
--- old/zake-0.0.14/README.rst  2014-02-02 09:45:12.000000000 +0100
+++ new/zake-0.0.20/README.rst  2014-05-10 21:09:41.000000000 +0200
@@ -1,7 +1,8 @@
 Zake
 ====
 
-.. image:: https://travis-ci.org/yahoo/Zake.png?branch=master   :target: 
https://travis-ci.org/yahoo/Zake
+.. image:: https://travis-ci.org/yahoo/Zake.png?branch=master
+   :target: https://travis-ci.org/yahoo/Zake
 
 
 A python package that works to provide a nice set of testing utilities for the 
kazoo library.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/setup.py new/zake-0.0.20/setup.py
--- old/zake-0.0.14/setup.py    2014-02-02 10:21:20.000000000 +0100
+++ new/zake-0.0.20/setup.py    2014-05-10 21:09:41.000000000 +0200
@@ -23,7 +23,7 @@
 
 setup(
     name='zake',
-    version='0.0.14',
+    version='0.0.20',
     description='A python package that works to provide a nice set of '
                 'testing utilities for the kazoo library.',
     author="Joshua Harlow",
@@ -33,6 +33,8 @@
     install_requires=[
         'kazoo',
         'six',
+        'testtools',
+        'futures',
     ],
     classifiers=[
         "Development Status :: 4 - Beta",
@@ -40,6 +42,11 @@
         "License :: OSI Approved :: Apache Software License",
         "Operating System :: POSIX :: Linux",
         "Programming Language :: Python",
+        "Programming Language :: Python :: 2",
+        "Programming Language :: Python :: 2.6",
+        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.3",
     ],
     keywords="kazoo testing zookeeper",
     packages=find_packages(),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/zake/fake_client.py 
new/zake-0.0.20/zake/fake_client.py
--- old/zake-0.0.14/zake/fake_client.py 2014-02-02 10:21:36.000000000 +0100
+++ new/zake-0.0.20/zake/fake_client.py 2014-05-10 21:09:41.000000000 +0200
@@ -17,16 +17,18 @@
 #    under the License.
 
 import collections
+import functools
 import logging
-import os
 import time
 
+from concurrent import futures
 import six
 
 from kazoo import exceptions as k_exceptions
 from kazoo.handlers import threading as k_threading
 from kazoo.protocol import paths as k_paths
 from kazoo.protocol import states as k_states
+from kazoo.recipe import watchers as k_watchers
 
 from zake import fake_storage as fs
 from zake import utils
@@ -39,11 +41,22 @@
 # differently).
 SERVER_VERSION = (3, 4, 0)
 
+_NO_ACL_MSG = "ACLs not currently supported"
+
 
 def _make_cb(func, args, type=''):
     return k_states.Callback(type=type, func=func, args=args)
 
 
+class SequentialThreadingHandler(k_threading.SequentialThreadingHandler):
+    def __init__(self, spawn_workers):
+        super(SequentialThreadingHandler, self).__init__()
+        self._spawner = futures.ThreadPoolExecutor(max_workers=spawn_workers)
+
+    def spawn(self, func, *args, **kwargs):
+        return self._spawner.submit(func, *args, **kwargs)
+
+
 class FakeClient(object):
     """A fake mostly functional/good enough kazoo compat. client
 
@@ -53,13 +66,18 @@
     testing frameworks (while in use and after the fact).
     """
 
-    def __init__(self, handler=None, storage=None, server_version=None):
+    def __init__(self, handler=None,
+                 storage=None, server_version=None,
+                 handler_spawn_workers=1):
         self._listeners = set()
-        self._watches = collections.defaultdict(list)
+        self._child_watches = collections.defaultdict(list)
+        self._data_watches = collections.defaultdict(list)
         if handler:
             self.handler = handler
+            self._stop_handler = False
         else:
-            self.handler = k_threading.SequentialThreadingHandler()
+            self.handler = SequentialThreadingHandler(handler_spawn_workers)
+            self._stop_handler = True
         if storage is not None:
             self.storage = storage
         else:
@@ -74,6 +92,9 @@
                 raise ValueError("Non-empty server version expected")
         self.expired = False
         self.logger = LOG
+        # Helper objects that makes these easier to create.
+        self.ChildrenWatch = functools.partial(k_watchers.ChildrenWatch, self)
+        self.DataWatch = functools.partial(k_watchers.DataWatch, self)
 
     def command(self, cmd=b'ruok'):
         self.verify()
@@ -100,8 +121,12 @@
         return IOError
 
     @property
-    def watches(self):
-        return self._watches
+    def child_watches(self):
+        return self._child_watches
+
+    @property
+    def data_watches(self):
+        return self._data_watches
 
     @property
     def listeners(self):
@@ -140,67 +165,48 @@
             time.sleep(0.001)
 
     def create(self, path, value=b"", acl=None,
-               ephemeral=False, sequence=False):
+               ephemeral=False, sequence=False, makepath=False):
         self.verify()
         if not isinstance(path, six.string_types):
             raise TypeError("path must be a string")
         if not isinstance(value, six.binary_type):
             raise TypeError("value must be a byte string")
-
-        path = k_paths.normpath(path)
-        if sequence:
-            raise NotImplementedError("Sequencing not currently supported")
         if acl:
-            raise NotImplementedError("ACL not currently supported")
-        with self.storage.lock:
-            if path in self.storage:
-                raise k_exceptions.NodeExistsError("Node %s already there"
-                                                   % path)
-            parent_path = os.path.split(path)[0]
-            if parent_path == path and path in self.storage:
-                # This is "/" and it already exists.
-                return
-            elif parent_path == path:
-                # This is "/" and it doesn't already exists.
-                pass
-            elif parent_path not in self.storage:
-                raise k_exceptions.NoNodeError("No parent %s" % (parent_path))
-            self.storage[path] = {
-                # Kazoo clients expect in milliseconds
-                'created_on': utils.millitime(),
-                'updated_on': utils.millitime(),
-                'version': 0,
-                # Not supported for now...
-                'aversion': -1,
-                'cversion': -1,
-                'data': value,
-            }
-            parents = sorted(six.iterkeys(self.storage.get_parents(path)))
-        if not parents:
-            return
+            raise NotImplementedError(_NO_ACL_MSG)
 
-        # Fire any attached watches.
-        event = k_states.WatchedEvent(type=k_states.EventType.CREATED,
-                                      state=k_states.KeeperState.CONNECTED,
-                                      path=path)
-        self._fire_watches([parents[-1]], event)
-        event = k_states.WatchedEvent(type=k_states.EventType.CHILD,
-                                      state=k_states.KeeperState.CONNECTED,
-                                      path=path)
-        self._fire_watches(parents[0:-1], event)
+        if makepath:
+            for p in utils.partition_path(path)[0:-1]:
+                if not self.exists(p):
+                    self.create(p)
+
+        created, parents, path = self.storage.create(path,
+                                                     value=value,
+                                                     sequence=sequence)
+        # Fire off child notifications that this node was created.
+        if parents:
+            event = k_states.WatchedEvent(type=k_states.EventType.CHILD,
+                                          state=k_states.KeeperState.CONNECTED,
+                                          path=path)
+            self._fire_watches(parents, event, self._child_watches)
+        # Fire off data notifications that this node was created.
+        if created:
+            event = k_states.WatchedEvent(type=k_states.EventType.CREATED,
+                                          state=k_states.KeeperState.CONNECTED,
+                                          path=path)
+            self._fire_watches([path], event, self._data_watches)
         return path
 
     def create_async(self, path, value=b"", acl=None,
-                     ephemeral=False, sequence=False):
+                     ephemeral=False, sequence=False, makepath=False):
         return self._generate_async(self.create, path, value=value,
                                     acl=acl, ephemeral=ephemeral,
-                                    sequence=sequence)
+                                    sequence=sequence, makepath=makepath)
 
     def _make_znode(self, path, node):
         child_count = len(self.get_children(path))
-        return k_states.ZnodeStat(czxid=-1,
-                                  mzxid=-1,
-                                  pzxid=-1,
+        return k_states.ZnodeStat(czxid=node['version'],
+                                  mzxid=node['version'],
+                                  pzxid=node['version'],
                                   ctime=node['created_on'],
                                   mtime=node['updated_on'],
                                   version=node['version'],
@@ -219,9 +225,21 @@
         except KeyError:
             raise k_exceptions.NoNodeError("No path %s" % (path))
         if watch:
-            self._watches[path].append(watch)
+            self._data_watches[path].append(watch)
         return (node['data'], self._make_znode(path, node))
 
+    def set_acls(self, path, acls, version=-1):
+        raise NotImplementedError(_NO_ACL_MSG)
+
+    def set_acls_async(self, path, acls, version=-1):
+        raise NotImplementedError(_NO_ACL_MSG)
+
+    def get_acls_async(self, path):
+        raise NotImplementedError(_NO_ACL_MSG)
+
+    def get_acls(self, path):
+        raise NotImplementedError(_NO_ACL_MSG)
+
     def get_async(self, path, watch=None):
         return self._generate_async(self.get, path, watch=watch)
 
@@ -232,6 +250,10 @@
                 self._connected = True
                 self._fire_state_change(k_states.KazooState.CONNECTED)
 
+    def restart(self):
+        self.stop()
+        self.start()
+
     def _fire_state_change(self, state):
         for func in self._listeners:
             self.handler.dispatch_callback(_make_cb(func, [state]))
@@ -239,7 +261,7 @@
     def _generate_async(self, func, *args, **kwargs):
         async_result = self.handler.async_result()
 
-        def run():
+        def call(func, args, kwargs):
             try:
                 result = func(*args, **kwargs)
                 async_result.set(result)
@@ -247,18 +269,21 @@
             except Exception as exc:
                 async_result.set_exception(exc)
 
-        self.handler.dispatch_callback(_make_cb(run, []))
+        cb = _make_cb(call, [func, args, kwargs], type='async')
+        self.handler.dispatch_callback(cb)
         return async_result
 
     def exists(self, path, watch=None):
         self.verify()
         if not isinstance(path, six.string_types):
             raise TypeError("path must be a string")
-
         try:
-            return self.get(path, watch=watch)[1]
+            exists = bool(self.get(path)[1])
         except k_exceptions.NoNodeError:
-            return None
+            exists = None
+        if watch:
+            self._data_watches[path].append(watch)
+        return exists
 
     def exists_async(self, path, watch=None):
         return self._generate_async(self.exists, path, watch=watch)
@@ -286,18 +311,13 @@
                 self.storage[path]['version'] += 1
             except KeyError:
                 raise k_exceptions.NoNodeError("No path %s" % (path))
-            parents = sorted(six.iterkeys(self.storage.get_parents(path)))
             (_data, stat) = self.get(path)
 
         # Fire any attached watches.
         event = k_states.WatchedEvent(type=k_states.EventType.CHANGED,
                                       state=k_states.KeeperState.CONNECTED,
                                       path=path)
-        self._fire_watches([path], event)
-        event = k_states.WatchedEvent(type=k_states.EventType.CHILD,
-                                      state=k_states.KeeperState.CONNECTED,
-                                      path=path)
-        self._fire_watches(parents, event)
+        self._fire_watches([path], event, self._data_watches)
         return stat
 
     def set_async(self, path, value, version=-1):
@@ -314,7 +334,7 @@
         path = k_paths.normpath(path)
         paths = self.storage.get_children(path)
         if watch:
-            self._watches[path].append(watch)
+            self._child_watches[path].append(watch)
         if include_data:
             children_with_data = []
             for (p, data) in six.iteritems(paths):
@@ -327,16 +347,19 @@
             return children
 
     def get_children_async(self, path, watch=None, include_data=False):
-        return self._generate_async(self.get_children, path, watch=watch, 
include_data=include_data)
+        return self._generate_async(self.get_children, path,
+                                    watch=watch, include_data=include_data)
 
     def stop(self):
         with self._lock:
             if not self._connected:
                 return
             self._fire_state_change(k_states.KazooState.LOST)
-            self.handler.stop()
+            if self._stop_handler:
+                self.handler.stop()
             self._listeners.clear()
-            self._watches.clear()
+            self._child_watches.clear()
+            self._data_watches.clear()
             self._connected = False
 
     def delete(self, path, recursive=False):
@@ -350,17 +373,37 @@
                 raise k_exceptions.NoNodeError("No path %s" % (path))
             if recursive:
                 paths = [path]
-                for p in six.iterkeys(self.storage.get_children(path)):
+                children = self.storage.get_children(path, only_direct=False)
+                for p in six.iterkeys(children):
                     paths.append(p)
             else:
+                children = self.storage.get_children(path, only_direct=False)
+                if children:
+                    raise k_exceptions.NotEmptyError("Path %s is not-empty"
+                                                     " (%s children exist)"
+                                                     % (path, len(children)))
                 paths = [path]
-            for p in reversed(sorted(paths)):
+            paths = list(reversed(sorted(set(paths))))
+            for p in paths:
                 self.storage.pop(p)
+            parents = []
+            for p in paths:
+                parents.extend(self.storage.get_parents(p))
+            parents = list(reversed(sorted(set(parents))))
+            # Fire off parent notifications that these paths were removed.
+            for p in parents:
                 event = k_states.WatchedEvent(
                     type=k_states.EventType.DELETED,
                     state=k_states.KeeperState.CONNECTED,
                     path=p)
-                self._fire_watches([p], event)
+                self._fire_watches([p], event, self._child_watches)
+            # Fire off data notifications that these paths were removed.
+            for p in paths:
+                event = k_states.WatchedEvent(
+                    type=k_states.EventType.DELETED,
+                    state=k_states.KeeperState.CONNECTED,
+                    path=p)
+                self._fire_watches([p], event, self._data_watches)
             return True
 
     def delete_async(self, path, recursive=False):
@@ -376,9 +419,9 @@
     def remove_listener(self, listener):
         self._listeners.discard(listener)
 
-    def _fire_watches(self, paths, event):
+    def _fire_watches(self, paths, event, watch_source):
         for p in reversed(sorted(set(paths))):
-            watches = list(self._watches.pop(p, []))
+            watches = list(watch_source.pop(p, []))
             for w in watches:
                 self.handler.dispatch_callback(_make_cb(w, [event]))
 
@@ -398,6 +441,9 @@
             except k_exceptions.NodeExistsError:
                 pass
 
+    def ensure_path_async(self, path):
+        return self._generate_async(self.ensure_path, path)
+
     def close(self):
         self._connected = False
 
@@ -438,4 +484,5 @@
 
     def __exit__(self, type, value, tb):
         if not any((type, value, tb)):
-            self.commit()
+            if not self.committed:
+                self.commit()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/zake/fake_storage.py 
new/zake-0.0.20/zake/fake_storage.py
--- old/zake-0.0.14/zake/fake_storage.py        2013-12-26 06:41:12.000000000 
+0100
+++ new/zake-0.0.20/zake/fake_storage.py        2014-05-10 21:09:41.000000000 
+0200
@@ -16,32 +16,98 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import os
 import threading
 
 import six
 
 from zake import utils
 
+from kazoo import exceptions as k_exceptions
+from kazoo.protocol import paths as k_paths
+
+
+# See: https://issues.apache.org/jira/browse/ZOOKEEPER-243
+SEQ_ROLLOVER = 2147483647
+SEQ_ROLLOVER_TO = -2147483647
+
+
+def _split_path(path):
+    return os.path.split(path)
+
 
 class FakeStorage(object):
     """A place too place fake zookeeper paths + data."""
 
-    def __init__(self, lock=None, paths=None):
+    def __init__(self, lock=None, paths=None, sequences=None):
         if paths:
             self._paths = dict(paths)
         else:
             self._paths = {}
+        if sequences:
+            self._sequences = sequences
+        else:
+            self._sequences = {}
         if lock is None:
             lock = threading.RLock()
         self.lock = lock
+        # Ensure the root path *always* exists.
+        if "/" not in self._paths:
+            self._paths["/"] = {
+                'created_on': 0,
+                'updated_on': 0,
+                'version': 0,
+                # Not supported for now...
+                'aversion': -1,
+                'cversion': -1,
+                'data': b"",
+            }
 
     @property
     def paths(self):
         with self.lock:
             return dict(self._paths)
 
+    @property
+    def sequences(self):
+        with self.lock:
+            return dict(self._sequences)
+
+    def create(self, path, value=b"", sequence=False):
+        path = k_paths.normpath(path)
+        parent_path, _node_name = _split_path(path)
+        if sequence:
+            with self.lock:
+                sequence_id = self._sequences.get(parent_path, 0)
+                if sequence_id == SEQ_ROLLOVER:
+                    self._sequences[parent_path] = SEQ_ROLLOVER_TO
+                else:
+                    self._sequences[parent_path] = sequence_id + 1
+                path = path + '%010d' % (sequence_id)
+        with self.lock:
+            if parent_path not in self:
+                raise k_exceptions.NoNodeError("Parent node %s does not exist"
+                                               % (parent_path))
+            if path in self:
+                raise k_exceptions.NodeExistsError("Node %s already"
+                                                   " exists" % (path))
+            self._paths[path] = {
+                # Kazoo clients expect in milliseconds
+                'created_on': utils.millitime(),
+                'updated_on': utils.millitime(),
+                'version': 0,
+                # Not supported for now...
+                'aversion': -1,
+                'cversion': -1,
+                'data': value,
+            }
+            parents = sorted(six.iterkeys(self.get_parents(path)))
+            return (True, parents, path)
+
     def pop(self, path):
         with self.lock:
+            if path == "/":
+                raise k_exceptions.BadArgumentsError("Can not delete '/'")
             self._paths.pop(path)
 
     def __setitem__(self, path, value):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/zake/test.py new/zake-0.0.20/zake/test.py
--- old/zake-0.0.14/zake/test.py        1970-01-01 01:00:00.000000000 +0100
+++ new/zake-0.0.20/zake/test.py        2014-05-10 21:09:41.000000000 +0200
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+#    Copyright (C) 2013 Yahoo! Inc. All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import testtools
+
+
+class Test(testtools.TestCase):
+    pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/zake/tests/__init__.py 
new/zake-0.0.20/zake/tests/__init__.py
--- old/zake-0.0.14/zake/tests/__init__.py      1970-01-01 01:00:00.000000000 
+0100
+++ new/zake-0.0.20/zake/tests/__init__.py      2014-05-10 21:09:41.000000000 
+0200
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+#    Copyright (C) 2013 Yahoo! Inc. All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/zake/tests/test_client.py 
new/zake-0.0.20/zake/tests/test_client.py
--- old/zake-0.0.14/zake/tests/test_client.py   1970-01-01 01:00:00.000000000 
+0100
+++ new/zake-0.0.20/zake/tests/test_client.py   2014-05-10 21:09:41.000000000 
+0200
@@ -0,0 +1,263 @@
+# -*- coding: utf-8 -*-
+
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+#    Copyright (C) 2014 Yahoo! Inc. All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import collections
+import contextlib
+import threading
+
+from kazoo import exceptions as k_exceptions
+from kazoo.recipe import watchers as k_watchers
+
+from zake import fake_client
+from zake import test
+
+
[email protected]
+def start_close(client):
+    client.start()
+    try:
+        yield client
+    finally:
+        client.close()
+
+
+class TestClient(test.Test):
+    def setUp(self):
+        super(TestClient, self).setUp()
+        self.client = fake_client.FakeClient()
+
+    def test_connected(self):
+        self.assertFalse(self.client.connected)
+        with start_close(self.client) as c:
+            self.assertTrue(c.connected)
+
+    def test_command(self):
+        with start_close(self.client) as c:
+            self.assertTrue(c.connected)
+            self.assertEqual("imok", c.command('ruok'))
+            self.client.command('kill')
+            self.assertFalse(c.connected)
+
+    def test_root(self):
+        with start_close(self.client) as c:
+            self.assertTrue(c.exists("/"))
+
+    def test_version(self):
+        with start_close(self.client) as c:
+            self.assertTrue(len(c.server_version()) > 0)
+            self.assertEqual(fake_client.SERVER_VERSION,
+                             c.server_version())
+
+    def test_make_path(self):
+        with start_close(self.client) as c:
+            c.create("/a/b/c", makepath=True)
+            self.assertTrue(c.exists("/a/b/c"))
+            self.assertTrue(c.exists("/a/b"))
+            self.assertTrue(c.exists("/a"))
+
+    def test_no_make_path(self):
+        with start_close(self.client) as c:
+            self.assertRaises(k_exceptions.KazooException,
+                              c.create, "/a/b/c")
+
+    def test_sequence(self):
+        with start_close(self.client) as c:
+            path = c.create("/", sequence=True)
+            self.assertEqual("/0000000000", path)
+            path = c.create("/", sequence=True)
+            self.assertEqual("/0000000001", path)
+            children = c.get_children("/")
+            self.assertEqual(2, len(children))
+            seqs = c.storage.sequences
+            self.assertEqual(1, len(seqs))
+            self.assertEqual(2, seqs['/'])
+
+    def test_command_no_connect(self):
+        self.assertRaises(k_exceptions.KazooException, self.client.sync, '/')
+
+    def test_create(self):
+        with start_close(self.client) as c:
+            c.ensure_path("/b")
+            c.create('/b/c', b'abc')
+            paths = c.storage.paths
+            self.assertEqual(3, len(paths))
+            self.assertEqual(1, len(c.storage.get_children("/b")))
+            self.assertEqual(1, len(c.storage.get_parents("/b")))
+            data, znode = c.get("/b/c")
+            self.assertEqual(b'abc', data)
+            self.assertEqual(0, znode.version)
+            c.set("/b/c", b"efg")
+            data, znode = c.get("/b/c")
+            self.assertEqual(b"efg", data)
+            self.assertEqual(1, znode.version)
+
+    def test_delete(self):
+        with start_close(self.client) as c:
+            self.assertRaises(k_exceptions.NoNodeError, c.delete, "/b")
+            c.ensure_path("/")
+            c.create("/b", b'b')
+            c.delete("/b")
+            self.assertRaises(k_exceptions.NoNodeError, c.delete, "/b")
+            self.assertFalse(c.exists("/b"))
+
+    def test_get_children(self):
+        with start_close(self.client) as c:
+            c.ensure_path("/a/b")
+            c.ensure_path("/a/c")
+            c.ensure_path("/a/d")
+            self.assertEqual(3, len(c.get_children("/a")))
+
+    def test_exists(self):
+        with start_close(self.client) as c:
+            c.ensure_path("/a")
+            self.assertTrue(c.exists("/"))
+            self.assertTrue(c.exists("/a"))
+
+    def test_sync(self):
+        with start_close(self.client) as c:
+            c.sync("/")
+
+    def test_transaction(self):
+        with start_close(self.client) as c:
+            c.ensure_path("/b")
+            with c.transaction() as txn:
+                txn.create("/b/c")
+                txn.set_data("/b/c", b'e')
+            data, znode = c.get("/b/c")
+            self.assertEqual(b'e', data)
+            self.assertTrue(txn.committed)
+
+    def test_data_watch(self):
+        updates = collections.deque()
+        ev = threading.Event()
+
+        def notify_me(data, stat):
+            updates.append((data, stat))
+            ev.set()
+
+        with start_close(self.client) as c:
+            k_watchers.DataWatch(self.client, "/b", func=notify_me)
+            ev.wait()
+            ev.clear()
+            c.ensure_path("/b")
+            ev.wait()
+            ev.clear()
+            c.set("/b", b"1")
+            ev.wait()
+            ev.clear()
+            c.set("/b", b"2")
+            ev.wait()
+            ev.clear()
+
+        self.assertEqual(4, len(updates))
+
+        ev.clear()
+        with start_close(self.client) as c:
+            c.delete("/b")
+            ev.wait()
+
+        self.assertEqual(5, len(updates))
+
+    def test_recursive_delete(self):
+        with start_close(self.client) as c:
+            c.ensure_path("/b/c/d/e")
+            c.ensure_path("/b/e/f/g")
+            c.ensure_path("/b/123/abc")
+            c.ensure_path("/a")
+            c.delete("/b", recursive=True)
+            self.assertTrue(c.get("/a"))
+            self.assertEqual(2, len(c.storage.paths))
+
+    def test_child_left_delete(self):
+        with start_close(self.client) as c:
+            c.ensure_path("/b/c/d/e")
+            self.assertRaises(k_exceptions.NotEmptyError, c.delete,
+                              "/b", recursive=False)
+
+    def test_child_watch(self):
+        updates = collections.deque()
+        ev = threading.Event()
+
+        def one_time_collector_func(children):
+            updates.extend(children)
+            if children:
+                ev.set()
+                return False
+
+        with start_close(self.client) as c:
+            k_watchers.ChildrenWatch(self.client, "/",
+                                     func=one_time_collector_func)
+            c.ensure_path("/b")
+            ev.wait()
+
+        self.assertEqual(['b'], list(updates))
+
+    def test_child_child_watch(self):
+        updates = collections.deque()
+        ev = threading.Event()
+
+        def one_time_collector_func(children):
+            updates.extend(children)
+            if children:
+                ev.set()
+                return False
+
+        with start_close(self.client) as c:
+            k_watchers.ChildrenWatch(self.client, "/b",
+                                     func=one_time_collector_func)
+            c.ensure_path("/b/c")
+            ev.wait()
+
+        self.assertEqual(['c'], list(updates))
+
+    def test_create_async(self):
+        with start_close(self.client) as c:
+            r = c.create_async("/b")
+            self.assertEqual("/b", r.get())
+            self.assertTrue(r.successful())
+            self.assertIsNone(r.exception)
+
+    def test_create_async_linked(self):
+        traces = collections.deque()
+        ev = threading.Event()
+
+        def add_trace(result):
+            traces.append(result)
+            ev.set()
+
+        with start_close(self.client) as c:
+            r = c.create_async("/b")
+            r.rawlink(add_trace)
+            self.assertEqual("/b", r.get())
+            ev.wait()
+
+        self.assertEqual(1, len(traces))
+        self.assertEqual(r, traces[0])
+
+    def test_create_async_exception(self):
+        ev = threading.Event()
+
+        def wait_for(result):
+            ev.set()
+
+        with start_close(self.client) as c:
+            r = c.create_async("/b/c/d")
+            r.rawlink(wait_for)
+            ev.wait()
+            self.assertFalse(r.successful())
+            self.assertIsNotNone(r.exception)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/zake/version.py 
new/zake-0.0.20/zake/version.py
--- old/zake-0.0.14/zake/version.py     2014-02-02 08:54:13.000000000 +0100
+++ new/zake-0.0.20/zake/version.py     2014-05-10 21:09:41.000000000 +0200
@@ -2,7 +2,7 @@
 
 # vim: tabstop=4 shiftwidth=4 softtabstop=4
 
-#    Copyright (C) 2013 Yahoo! Inc. All Rights Reserved.
+#    Copyright (C) 2014 Yahoo! Inc. All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
 #    not use this file except in compliance with the License. You may obtain
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/zake.egg-info/PKG-INFO 
new/zake-0.0.20/zake.egg-info/PKG-INFO
--- old/zake-0.0.14/zake.egg-info/PKG-INFO      2014-02-02 10:25:38.000000000 
+0100
+++ new/zake-0.0.20/zake.egg-info/PKG-INFO      2014-05-10 21:10:25.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: zake
-Version: 0.0.14
+Version: 0.0.20
 Summary: A python package that works to provide a nice set of testing 
utilities for the kazoo library.
 Home-page: https://github.com/yahoo/Zake
 Author: Joshua Harlow
@@ -9,7 +9,8 @@
 Description: Zake
         ====
         
-        .. image:: https://travis-ci.org/yahoo/Zake.png?branch=master   
:target: https://travis-ci.org/yahoo/Zake
+        .. image:: https://travis-ci.org/yahoo/Zake.png?branch=master
+           :target: https://travis-ci.org/yahoo/Zake
         
         
         A python package that works to provide a nice set of testing utilities 
for the kazoo library.
@@ -34,3 +35,8 @@
 Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Operating System :: POSIX :: Linux
 Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/zake.egg-info/SOURCES.txt 
new/zake-0.0.20/zake.egg-info/SOURCES.txt
--- old/zake-0.0.14/zake.egg-info/SOURCES.txt   2014-02-02 10:25:39.000000000 
+0100
+++ new/zake-0.0.20/zake.egg-info/SOURCES.txt   2014-05-10 21:10:25.000000000 
+0200
@@ -4,10 +4,13 @@
 zake/__init__.py
 zake/fake_client.py
 zake/fake_storage.py
+zake/test.py
 zake/utils.py
 zake/version.py
 zake.egg-info/PKG-INFO
 zake.egg-info/SOURCES.txt
 zake.egg-info/dependency_links.txt
 zake.egg-info/requires.txt
-zake.egg-info/top_level.txt
\ No newline at end of file
+zake.egg-info/top_level.txt
+zake/tests/__init__.py
+zake/tests/test_client.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zake-0.0.14/zake.egg-info/requires.txt 
new/zake-0.0.20/zake.egg-info/requires.txt
--- old/zake-0.0.14/zake.egg-info/requires.txt  2014-02-02 10:25:38.000000000 
+0100
+++ new/zake-0.0.20/zake.egg-info/requires.txt  2014-05-10 21:10:25.000000000 
+0200
@@ -1,2 +1,4 @@
 kazoo
-six
\ No newline at end of file
+six
+testtools
+futures
\ No newline at end of file

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to