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 - dmueller@suse.com + +- 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 + + +@contextlib.contextmanager +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: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org