summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2019-07-14 12:50:04 +0300
committerLars Wirzenius <liw@liw.fi>2019-08-03 21:06:50 +0300
commit581f6cd53f57599326439dccb355e882e7858faa (patch)
tree19236daf6feaab66dd07b8cbcdb609db4b653be1
parent97f3390944d2189d6bf0be2f2d451784c71e1856 (diff)
downloadick2-581f6cd53f57599326439dccb355e882e7858faa.tar.gz
Add: MemoryPersitentState
-rw-r--r--ick2/__init__.py4
-rw-r--r--ick2/apibase.py4
-rw-r--r--ick2/persistent.py61
-rw-r--r--ick2/persistent_tests.py30
-rw-r--r--ick2/projectapi_tests.py5
-rw-r--r--ick2/workapi_tests.py5
6 files changed, 41 insertions, 68 deletions
diff --git a/ick2/__init__.py b/ick2/__init__.py
index f489396..0016f13 100644
--- a/ick2/__init__.py
+++ b/ick2/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2018 Lars Wirzenius
+# Copyright (C) 2017-2019 Lars Wirzenius
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
@@ -16,7 +16,7 @@
from .version import __version__, __version_info__
from .logging import setup_logging, log
from .persistent import (
- FilePersistentState,
+ MemoryPersistentState,
NotFound,
Resource,
resource_from_dict,
diff --git a/ick2/apibase.py b/ick2/apibase.py
index c08f7cf..f330eae 100644
--- a/ick2/apibase.py
+++ b/ick2/apibase.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2018 Lars Wirzenius
+# Copyright (C) 2017-2019 Lars Wirzenius
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
@@ -19,7 +19,7 @@ import ick2
class APIbase:
def __init__(self, state):
- assert state is None or isinstance(state, ick2.FilePersistentState)
+ assert state is None or isinstance(state, ick2.MemoryPersistentState)
self._trans = ick2.TransactionalState(state)
def get_routes(self, path):
diff --git a/ick2/persistent.py b/ick2/persistent.py
index 1d79e3d..bb0aeb6 100644
--- a/ick2/persistent.py
+++ b/ick2/persistent.py
@@ -49,64 +49,33 @@ class PersistentStateInterface: # pragma: no cover
raise NotImplementedError()
-class FilePersistentState(PersistentStateInterface):
+class MemoryPersistentState(PersistentStateInterface):
def __init__(self):
- self._dir = None
+ self._res = {}
- def get_directory(self):
- return self._dir
-
- def set_directory(self, dirname):
- self._dir = dirname
-
- def _safe(self, name):
- return urllib.parse.quote(name, safe='')
-
- def _unsafe(self, safe):
- return urllib.parse.unquote(safe)
-
- def _unsafe_list(self, safe_names):
- return [self._unsafe(safe) for safe in safe_names]
-
- def _dirname(self, kind):
- return os.path.join(self._dir, self._safe(kind))
-
- def _filename(self, kind, rid):
- dirname = self._dirname(kind)
- return os.path.join(dirname, self._safe(rid))
+ def get_resource_ids(self, kind):
+ if kind not in self._res:
+ return []
+ return list(self._res[kind].keys())
def has_resource(self, kind, rid):
- filename = self._filename(kind, rid)
- return os.path.exists(filename)
-
- def get_resource_ids(self, kind):
- dirname = self._dirname(kind)
- if os.path.exists(dirname):
- return self._unsafe_list(os.listdir(dirname))
- return []
+ return kind in self._res and rid in self._res[kind]
def get_resource(self, kind, rid):
- filename = self._filename(kind, rid)
- if not os.path.exists(filename):
+ if kind not in self._res or rid not in self._res[kind]:
raise ick2.NotFound(kind=kind, rid=rid)
- with open(filename, 'r') as f:
- as_dict = yaml.load(f, Loader=yaml.CSafeLoader)
- return resource_from_dict(as_dict)
+ return self._res[kind][rid]
def write_resource(self, kind, rid, resource):
- dirname = self._dirname(kind)
- if not os.path.exists(dirname):
- os.makedirs(dirname)
-
- filename = self._filename(kind, rid)
- with open(filename, 'w') as f:
- yaml.dump(
- resource.as_dict(), stream=f, Dumper=yaml.CSafeDumper)
+ if kind not in self._res:
+ self._res[kind] = {}
+ self._res[kind][rid] = resource
def remove_resource(self, kind, rid):
- filename = self._filename(kind, rid)
- os.remove(filename)
+ 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):
diff --git a/ick2/persistent_tests.py b/ick2/persistent_tests.py
index de279a1..61cd43f 100644
--- a/ick2/persistent_tests.py
+++ b/ick2/persistent_tests.py
@@ -22,18 +22,7 @@ import unittest
import ick2
-class FilePersistentStateTests(unittest.TestCase):
-
- def setUp(self):
- self.tempdir = tempfile.mkdtemp()
- self.state = ick2.FilePersistentState()
- self.state.set_directory(self.tempdir)
-
- def tearDown(self):
- shutil.rmtree(self.tempdir)
-
- def test_returns_dirname(self):
- self.assertEqual(self.state.get_directory(), self.tempdir)
+class PersistentStateTestsMixIn:
def test_has_no_resources_initially(self):
self.assertEqual(self.state.get_resource_ids('silly'), [])
@@ -60,3 +49,20 @@ class FilePersistentStateTests(unittest.TestCase):
self.state.remove_resource('silly', '#1')
self.assertFalse(self.state.has_resource('silly', '#1'))
self.assertEqual(self.state.get_resource_ids('silly'), [])
+
+ def test_raises_error_removing_nonexistent_resource_kind(self):
+ with self.assertRaises(ick2.NotFound):
+ self.state.remove_resource('silly', '#1')
+
+ def test_raises_error_removing_nonexistent_resource(self):
+ as_dict = {'foo': 'bar'}
+ r = ick2.resource_from_dict(as_dict)
+ self.state.write_resource('silly', '#1', r)
+ with self.assertRaises(ick2.NotFound):
+ self.state.remove_resource('silly', '#2')
+
+
+class MemoryPersistentStateTests(unittest.TestCase, PersistentStateTestsMixIn):
+
+ def setUp(self):
+ self.state = ick2.MemoryPersistentState()
diff --git a/ick2/projectapi_tests.py b/ick2/projectapi_tests.py
index b6ec9e9..5be2a58 100644
--- a/ick2/projectapi_tests.py
+++ b/ick2/projectapi_tests.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2018 Lars Wirzenius
+# Copyright (C) 2017-2019 Lars Wirzenius
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
@@ -27,8 +27,7 @@ class ProjectAPITests(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.mkdtemp()
self.statedir = os.path.join(self.tempdir, 'state/dir')
- self.state = ick2.FilePersistentState()
- self.state.set_directory(self.statedir)
+ self.state = ick2.MemoryPersistentState()
def tearDown(self):
shutil.rmtree(self.tempdir)
diff --git a/ick2/workapi_tests.py b/ick2/workapi_tests.py
index c368b4b..8652110 100644
--- a/ick2/workapi_tests.py
+++ b/ick2/workapi_tests.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2018 Lars Wirzenius
+# Copyright (C) 2017-2019 Lars Wirzenius
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
@@ -28,8 +28,7 @@ class WorkAPITests(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.mkdtemp()
self.statedir = os.path.join(self.tempdir, 'state/dir')
- self.state = ick2.FilePersistentState()
- self.state.set_directory(self.statedir)
+ self.state = ick2.MemoryPersistentState()
self.claims = None
def tearDown(self):