summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2019-10-18 11:39:28 +0300
committerLars Wirzenius <liw@liw.fi>2019-10-18 11:39:28 +0300
commit7e674fb46c1e42506c15b3a79c120956b3ff3336 (patch)
treef7623212ef69154d2246c6c383fd15f4b446e1fb
parent77104290b1af83fea2221aea26c5b0618dd6fae2 (diff)
downloadick2-master.tar.gz
Revert "Add: MemoryPersitentState"HEADmaster
This reverts commit 581f6cd53f57599326439dccb355e882e7858faa.
-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, 68 insertions, 41 deletions
diff --git a/ick2/__init__.py b/ick2/__init__.py
index 0016f13..f489396 100644
--- a/ick2/__init__.py
+++ b/ick2/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2019 Lars Wirzenius
+# Copyright (C) 2017-2018 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 (
- MemoryPersistentState,
+ FilePersistentState,
NotFound,
Resource,
resource_from_dict,
diff --git a/ick2/apibase.py b/ick2/apibase.py
index f330eae..c08f7cf 100644
--- a/ick2/apibase.py
+++ b/ick2/apibase.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2019 Lars Wirzenius
+# Copyright (C) 2017-2018 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.MemoryPersistentState)
+ assert state is None or isinstance(state, ick2.FilePersistentState)
self._trans = ick2.TransactionalState(state)
def get_routes(self, path):
diff --git a/ick2/persistent.py b/ick2/persistent.py
index bb0aeb6..1d79e3d 100644
--- a/ick2/persistent.py
+++ b/ick2/persistent.py
@@ -49,33 +49,64 @@ class PersistentStateInterface: # pragma: no cover
raise NotImplementedError()
-class MemoryPersistentState(PersistentStateInterface):
+class FilePersistentState(PersistentStateInterface):
def __init__(self):
- self._res = {}
+ self._dir = None
- def get_resource_ids(self, kind):
- if kind not in self._res:
- return []
- return list(self._res[kind].keys())
+ 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 has_resource(self, kind, rid):
- return kind in self._res and rid in self._res[kind]
+ 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 []
def get_resource(self, kind, rid):
- if kind not in self._res or rid not in self._res[kind]:
+ filename = self._filename(kind, rid)
+ if not os.path.exists(filename):
raise ick2.NotFound(kind=kind, rid=rid)
- return self._res[kind][rid]
+ with open(filename, 'r') as f:
+ as_dict = yaml.load(f, Loader=yaml.CSafeLoader)
+ return resource_from_dict(as_dict)
def write_resource(self, kind, rid, resource):
- if kind not in self._res:
- self._res[kind] = {}
- self._res[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)
def remove_resource(self, 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]
+ filename = self._filename(kind, rid)
+ os.remove(filename)
class NotFound(Exception):
diff --git a/ick2/persistent_tests.py b/ick2/persistent_tests.py
index 61cd43f..de279a1 100644
--- a/ick2/persistent_tests.py
+++ b/ick2/persistent_tests.py
@@ -22,7 +22,18 @@ import unittest
import ick2
-class PersistentStateTestsMixIn:
+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)
def test_has_no_resources_initially(self):
self.assertEqual(self.state.get_resource_ids('silly'), [])
@@ -49,20 +60,3 @@ class PersistentStateTestsMixIn:
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 5be2a58..b6ec9e9 100644
--- a/ick2/projectapi_tests.py
+++ b/ick2/projectapi_tests.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2019 Lars Wirzenius
+# Copyright (C) 2017-2018 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,7 +27,8 @@ class ProjectAPITests(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.mkdtemp()
self.statedir = os.path.join(self.tempdir, 'state/dir')
- self.state = ick2.MemoryPersistentState()
+ self.state = ick2.FilePersistentState()
+ self.state.set_directory(self.statedir)
def tearDown(self):
shutil.rmtree(self.tempdir)
diff --git a/ick2/workapi_tests.py b/ick2/workapi_tests.py
index 8652110..c368b4b 100644
--- a/ick2/workapi_tests.py
+++ b/ick2/workapi_tests.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2019 Lars Wirzenius
+# Copyright (C) 2017-2018 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,7 +28,8 @@ class WorkAPITests(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.mkdtemp()
self.statedir = os.path.join(self.tempdir, 'state/dir')
- self.state = ick2.MemoryPersistentState()
+ self.state = ick2.FilePersistentState()
+ self.state.set_directory(self.statedir)
self.claims = None
def tearDown(self):