From e68572e5297abbeacac98366d5a0601f2f1c27cc Mon Sep 17 00:00:00 2001 From: Samuel Marks Date: Mon, 27 Apr 2015 17:11:37 +1000 Subject: Implemented `pop` --- src/etcd/__init__.py | 2 ++ src/etcd/client.py | 31 +++++++++++++++++++++++++++++++ src/etcd/tests/unit/test_request.py | 20 ++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/src/etcd/__init__.py b/src/etcd/__init__.py index 9367ce9..18ef036 100644 --- a/src/etcd/__init__.py +++ b/src/etcd/__init__.py @@ -25,6 +25,8 @@ class EtcdResult(object): node (dict): The dictionary containing all node information. + prevNode (dict): The dictionary containing previous node information. + """ self.action = action for (key, default) in self._node_props.items(): diff --git a/src/etcd/client.py b/src/etcd/client.py index f50e4db..4bd746f 100644 --- a/src/etcd/client.py +++ b/src/etcd/client.py @@ -392,6 +392,37 @@ class Client(object): self.key_endpoint + key, self._MDELETE, params=kwds) return self._result_from_response(response) + def pop(self, key, recursive=None, dir=None, **kwdargs): + """ + Remove specified key from etcd and return the corresponding value. + + Args: + + key (str): Key. + + recursive (bool): if we want to recursively delete a directory, set + it to true + + dir (bool): if we want to delete a directory, set it to true + + prevValue (str): compare key to this value, and swap only if + corresponding (optional). + + prevIndex (int): modify key only if actual modifiedIndex matches the + provided one (optional). + + Returns: + client.EtcdResult + + Raises: + KeyValue: If the key doesn't exists. + + >>> print client.pop('/key').value + 'value' + + """ + return self.delete(key=key, recursive=recursive, dir=dir, **kwdargs)._prev_node + # Higher-level methods on top of the basic primitives def test_and_set(self, key, value, prev_value, ttl=None): """ diff --git a/src/etcd/tests/unit/test_request.py b/src/etcd/tests/unit/test_request.py index df1ae57..340bece 100644 --- a/src/etcd/tests/unit/test_request.py +++ b/src/etcd/tests/unit/test_request.py @@ -240,6 +240,26 @@ class TestClientApiInterface(TestClientApiBase): res = self.client.delete('/testKey') self.assertEquals(res, etcd.EtcdResult(**d)) + def test_pop(self): + """ Can pop a value """ + d = { + u'action': u'delete', + u'node': { + u'key': u'/testkey', + u'modifiedIndex': 3, + u'createdIndex': 2 + }, + u'prevNode': {u'newKey': False, u'createdIndex': None, + u'modifiedIndex': 190, u'value': u'test', u'expiration': None, + u'key': u'/testkey', u'ttl': None, u'dir': False} + } + + self._mock_api(200, d) + res = self.client.pop(d['node']['key']) + self.assertEquals({attr: getattr(res, attr) for attr in dir(res) + if attr in etcd.EtcdResult._node_props}, d['prevNode']) + self.assertEqual(res.value, d['prevNode']['value']) + def test_read(self): """ Can get a value """ d = { -- cgit v1.2.3