diff --git a/.travis.yml b/.travis.yml index c4e371c..443574e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: python python: - "2.6" - "2.7" - - "3.2" - "3.3" - "3.4" diff --git a/chest/core.py b/chest/core.py index fa95d44..a1d5b77 100644 --- a/chest/core.py +++ b/chest/core.py @@ -95,6 +95,7 @@ def __init__(self, data=None, path=None, available_memory=None, on_miss=_do_nothing, on_overflow=_do_nothing, open=open, open_many=_open_many, + readonly=False, mode='b'): # In memory storage self.inmem = data or dict() @@ -115,6 +116,7 @@ def __init__(self, data=None, path=None, available_memory=None, self.open = open self.open_many = open_many self._key_to_filename = key_to_filename + self.readonly = readonly keyfile = os.path.join(self.path, '.keys') try: @@ -134,6 +136,9 @@ def __init__(self, data=None, path=None, available_memory=None, self._on_miss = on_miss self._on_overflow = on_overflow + if (not self._explicitly_given_path) and self.readonly: + raise TypeError("Can't create an empty readonly chest") + def __str__(self): return '' % self.path @@ -196,6 +201,9 @@ def _update_lru(self, key): self.heap[key] = self.counter def __delitem__(self, key): + if self.readonly: + raise TypeError("Can't delete from readonly chest") + if key in self.inmem: self.memory_usage -= nbytes(self.inmem[key]) del self.inmem[key] @@ -209,6 +217,9 @@ def __delitem__(self, key): del self._keys[key] def __setitem__(self, key, value): + if self.readonly: + raise TypeError("Can't assign in readonly chest") + with self.lock: if key in self._keys: del self[key] @@ -223,7 +234,7 @@ def __setitem__(self, key, value): def __del__(self): if self._explicitly_given_path: - if os.path.exists(self.path): + if os.path.exists(self.path) and not self.readonly: self.flush() else: with self.lock: diff --git a/chest/tests/test_core.py b/chest/tests/test_core.py index 544a6fb..647b9b9 100644 --- a/chest/tests/test_core.py +++ b/chest/tests/test_core.py @@ -458,3 +458,38 @@ def test_prefetch(): assert not raises(KeyError, lambda: c[1]) c.prefetch([1, 2]) assert not raises(KeyError, lambda: c[2]) + + +def test_readonly(): + with tmp_chest(path="here") as c1: + c1[0] = 0 + c1["foo"] = "bar" + c1.flush() + with tmp_chest(path="here", readonly=True) as c2: + assert c2[0] == 0 + assert c2["foo"] == "bar" + try: + c2[0] = 1 + assert False + except TypeError: + assert True + except: + assert False + try: + c2["spam"] = "eggs" + assert False + except TypeError: + assert True + except: + assert False + try: + del c2["foo"] + assert False + except TypeError: + assert True + except: + assert False + + +def test_readonly_nopath(): + assert raises(TypeError, lambda: Chest(readonly=True))