From 0df1aaf19a5f245d58079806cc41ade508a33aac Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Fri, 18 Oct 2019 10:49:28 +0300 Subject: Revert "Change: refer to resource by name, not id" This reverts commit 03a559309b8790f6bc3ad3d92300a4c172910abb. --- ick2/__init__.py | 1 + ick2/apibase.py | 21 +++++++------ ick2/persistent.py | 82 +++++++++++++++++++++++++++++++++--------------- ick2/persistent_tests.py | 17 +++++++--- ick2/trans.py | 40 +++++++++++------------ 5 files changed, 102 insertions(+), 59 deletions(-) diff --git a/ick2/__init__.py b/ick2/__init__.py index e21f666..8bfa867 100644 --- a/ick2/__init__.py +++ b/ick2/__init__.py @@ -21,6 +21,7 @@ from .store import ( ) from .persistent import ( MemoryPersistentState, + MuckPersistentState, NotFound, Resource, resource_from_dict, diff --git a/ick2/apibase.py b/ick2/apibase.py index b950c11..e18ebe2 100644 --- a/ick2/apibase.py +++ b/ick2/apibase.py @@ -23,7 +23,8 @@ class APIbase: def __init__(self, state): assert (state is None or - isinstance(state, ick2.MemoryPersistentState)) + isinstance(state, ick2.MemoryPersistentState) or + isinstance(state, ick2.MuckPersistentState)) self._trans = ick2.TransactionalState(state) def get_routes(self, path): @@ -181,11 +182,11 @@ class ResourceApiBase(APIbase): body=body, token=token, kwargs=kwargs) as_dict = self.mangle_new_resource(body) - name = self.get_resource_name(as_dict) - if self._trans.has_resource(token, self._type_name, name): - raise ick2.ExistsAlready(name) + rid = self.get_resource_name(as_dict) + if self._trans.has_resource(token, self._type_name, rid): + raise ick2.ExistsAlready(rid) - with self._trans.new(token, self._type_name, name) as resource: + with self._trans.new(token, self._type_name, rid) as resource: resource.from_dict(as_dict) return as_dict @@ -197,11 +198,11 @@ class ResourceApiBase(APIbase): raise NotImplementedError() def update(self, body, name, token=None, **kwargs): - name = self.get_resource_name(body) - if not self._trans.has_resource(token, self._type_name, name): - raise ick2.NotFound(kind=self._type_name, name=name) + rid = self.get_resource_name(body) + if not self._trans.has_resource(token, self._type_name, rid): + raise ick2.NotFound(kind=self._type_name, rid=rid) - with self._trans.modify(token, self._type_name, name) as resource: + with self._trans.modify(token, self._type_name, rid) as resource: as_dict = self.mangle_updated_resource(resource.as_dict(), body) resource.from_dict(as_dict) @@ -212,5 +213,5 @@ class ResourceApiBase(APIbase): def delete(self, name, token=None, **kwargs): if not self._trans.has_resource(token, self._type_name, name): - raise ick2.NotFound(kind=self._type_name, name=name) + raise ick2.NotFound(kind=self._type_name, rid=name) self._trans.remove_resource(token, self._type_name, name) diff --git a/ick2/persistent.py b/ick2/persistent.py index e225b88..d323db7 100644 --- a/ick2/persistent.py +++ b/ick2/persistent.py @@ -27,28 +27,28 @@ import ick2 class PersistentStateInterface: # pragma: no cover - def get_resource_names(self, token, kind): + def get_resource_ids(self, token, kind): raise NotImplementedError() - def has_resource(self, token, kind, name): + def has_resource(self, token, kind, rid): raise NotImplementedError() - def get_resource(self, token, kind, name): + def get_resource(self, token, kind, rid): raise NotImplementedError() def get_resources(self, token, kind): return [ - self.get_resource(token, kind, name) - for name in self.get_resource_names(token, kind) + self.get_resource(token, kind, rid) + for rid in self.get_resource_ids(token, kind) ] - def write_resource(self, token, kind, name, resource): + def write_resource(self, token, kind, rid, resource): raise NotImplementedError() - def update_resource(self, token, kind, name, resource): + def update_resource(self, token, kind, rid, resource): raise NotImplementedError() - def remove_resource(self, token, kind, name): + def remove_resource(self, token, kind, rid): raise NotImplementedError() @@ -57,39 +57,71 @@ class MemoryPersistentState(PersistentStateInterface): def __init__(self): self._res = {} - def get_resource_names(self, token, kind): + def get_resource_ids(self, token, kind): if kind not in self._res: return [] return list(self._res[kind].keys()) - def has_resource(self, token, kind, name): - return kind in self._res and name in self._res[kind] + def has_resource(self, token, kind, rid): + return kind in self._res and rid in self._res[kind] - def get_resource(self, token, kind, name): - if kind not in self._res or name not in self._res[kind]: - raise ick2.NotFound(kind=kind, name=name) - return self._res[kind][name] + def get_resource(self, token, kind, rid): + if kind not in self._res or rid not in self._res[kind]: + raise ick2.NotFound(kind=kind, rid=rid) + return self._res[kind][rid] - def write_resource(self, token, kind, name, resource): + def write_resource(self, token, kind, rid, resource): if kind not in self._res: self._res[kind] = {} - self._res[kind][name] = resource + self._res[kind][rid] = resource - def update_resource(self, token, kind, name, resource): - self.write_resource(token, kind, name, resource) + def update_resource(self, token, kind, rid, resource): + self.write_resource(token, kind, rid, resource) - def remove_resource(self, token, kind, name): - if kind not in self._res or name not in self._res[kind]: - raise ick2.NotFound(kind=kind, name=name) - del self._res[kind][name] + def remove_resource(self, token, kind, rid): + if kind not in self._res or rid not in self._res[kind]: + raise ick2.NotFound(kind=kind, rid=rid) + del self._res[kind][rid] + + +class MuckPersistentState(PersistentStateInterface): + + def __init__(self): + self._res = {} + + def get_resource_ids(self, token, kind): + if kind not in self._res: + return [] + return list(self._res[kind].keys()) + + def has_resource(self, token, kind, rid): + return kind in self._res and rid in self._res[kind] + + def get_resource(self, token, kind, rid): + if kind not in self._res or rid not in self._res[kind]: + raise ick2.NotFound(kind=kind, rid=rid) + return self._res[kind][rid] + + def write_resource(self, token, kind, rid, resource): + if kind not in self._res: + self._res[kind] = {} + self._res[kind][rid] = resource + + def update_resource(self, token, kind, rid, resource): + self.write_resource(token, kind, rid, resource) + + def remove_resource(self, token, kind, rid): + if kind not in self._res or rid not in self._res[kind]: + raise ick2.NotFound(kind=kind, rid=rid) + del self._res[kind][rid] class NotFound(Exception): - def __init__(self, kind, name): + def __init__(self, kind, rid): super().__init__( 'Resource {}:{} not found'.format( - kind or "unknown", name or "unknown")) + kind or "unknown", rid or "unknown")) class Resource: # pragma: no cover diff --git a/ick2/persistent_tests.py b/ick2/persistent_tests.py index 18b5c5c..8406acf 100644 --- a/ick2/persistent_tests.py +++ b/ick2/persistent_tests.py @@ -29,7 +29,7 @@ class PersistentStateTestsMixIn: def test_has_no_resources_initially(self): token = self.get_token() - self.assertEqual(self.state.get_resource_names(token, 'silly'), []) + self.assertEqual(self.state.get_resource_ids(token, 'silly'), []) def test_has_no_resource_initially(self): token = self.get_token() @@ -43,7 +43,7 @@ class PersistentStateTestsMixIn: token = self.get_token() self.state.write_resource(token, 'silly', '#1', r) self.assertTrue(self.state.has_resource(token, 'silly', '#1')) - self.assertEqual(self.state.get_resource_names(token, 'silly'), ['#1']) + self.assertEqual(self.state.get_resource_ids(token, 'silly'), ['#1']) r2 = self.state.get_resource(token, 'silly', '#1') self.assertTrue(isinstance(r2, ick2.Resource)) @@ -61,7 +61,7 @@ class PersistentStateTestsMixIn: self.state.update_resource(token, 'silly', '#1', r2) self.assertTrue(self.state.has_resource(token, 'silly', '#1')) - self.assertEqual(self.state.get_resource_names(token, 'silly'), ['#1']) + self.assertEqual(self.state.get_resource_ids(token, 'silly'), ['#1']) actual = self.state.get_resource(token, 'silly', '#1') self.assertTrue(isinstance(actual, ick2.Resource)) @@ -75,7 +75,7 @@ class PersistentStateTestsMixIn: self.state.write_resource(token, 'silly', '#1', r) self.state.remove_resource(token, 'silly', '#1') self.assertFalse(self.state.has_resource(token, 'silly', '#1')) - self.assertEqual(self.state.get_resource_names(token, 'silly'), []) + self.assertEqual(self.state.get_resource_ids(token, 'silly'), []) def test_raises_error_removing_nonexistent_resource_kind(self): token = self.get_token() @@ -99,3 +99,12 @@ class MemoryPersistentStateTests(unittest.TestCase, PersistentStateTestsMixIn): def setUp(self): self.state = ick2.MemoryPersistentState() + + +class MuckPersistentStateTests(unittest.TestCase, PersistentStateTestsMixIn): + + def get_token(self): + return 'DUMMY-TOKEN' + + def setUp(self): + self.state = ick2.MuckPersistentState() diff --git a/ick2/trans.py b/ick2/trans.py index afbeeb2..171c996 100644 --- a/ick2/trans.py +++ b/ick2/trans.py @@ -19,14 +19,14 @@ import ick2 class TransactionalResource: - def __init__(self, token, state, kind, name): + def __init__(self, token, state, kind, rid): self.token = token self.state = state self.kind = kind - self.name = name - if state.has_resource(self.token, kind, name): + self.rid = rid + if state.has_resource(self.token, kind, rid): self.new = False - self.resource = state.get_resource(self.token, kind, name) + self.resource = state.get_resource(self.token, kind, rid) else: self.new = True self.resource = ick2.resource_from_dict({}) @@ -48,10 +48,10 @@ class TransactionalResource: if exc_type is None: if self.new: self.state.write_resource( - self.token, self.kind, self.name, self.resource) + self.token, self.kind, self.rid, self.resource) else: self.state.update_resource( - self.token, self.kind, self.name, self.resource) + self.token, self.kind, self.rid, self.resource) class TransactionalState: @@ -59,25 +59,25 @@ class TransactionalState: def __init__(self, state): self.state = state - def new(self, token, kind, name): - return TransactionalResource(token, self.state, kind, name) + def new(self, token, kind, rid): + return TransactionalResource(token, self.state, kind, rid) - def modify(self, token, kind, name): - if not self.state.has_resource(token, kind, name): - raise ick2.NotFound(kind=kind, name=name) - return TransactionalResource(token, self.state, kind, name) + def modify(self, token, kind, rid): + if not self.state.has_resource(token, kind, rid): + raise ick2.NotFound(kind=kind, rid=rid) + return TransactionalResource(token, self.state, kind, rid) - def get_resource_names(self, token, kind): - return self.state.get_resource_names(token, kind) + def get_resource_ids(self, token, kind): + return self.state.get_resource_ids(token, kind) - def has_resource(self, token, kind, name): - return self.state.has_resource(token, kind, name) + def has_resource(self, token, kind, rid): + return self.state.has_resource(token, kind, rid) - def get_resource(self, token, kind, name): - return self.state.get_resource(token, kind, name) + def get_resource(self, token, kind, rid): + return self.state.get_resource(token, kind, rid) def get_resources(self, token, kind): return self.state.get_resources(token, kind) - def remove_resource(self, token, kind, name): - self.state.remove_resource(token, kind, name) + def remove_resource(self, token, kind, rid): + self.state.remove_resource(token, kind, rid) -- cgit v1.2.1