Skip to content

Commit

Permalink
persistent_dict: separate different sources of KeyErrors (#189)
Browse files Browse the repository at this point in the history
* persistent_dict: separate different sources of KeyErrors

* add to doc
  • Loading branch information
matthiasdiener authored Nov 27, 2023
1 parent ff909ab commit dea0d87
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 21 deletions.
51 changes: 35 additions & 16 deletions pytools/persistent_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
This module also provides a disk-backed dictionary that uses persistent hashing.
.. autoexception:: NoSuchEntryError
.. autoexception:: NoSuchEntryInvalidKeyError
.. autoexception:: NoSuchEntryInvalidContentsError
.. autoexception:: NoSuchEntryCollisionError
.. autoexception:: ReadOnlyEntryError
.. autoexception:: CollisionWarning
Expand Down Expand Up @@ -528,6 +531,18 @@ class NoSuchEntryError(KeyError):
pass


class NoSuchEntryInvalidKeyError(NoSuchEntryError):
pass


class NoSuchEntryInvalidContentsError(NoSuchEntryError):
pass


class NoSuchEntryCollisionError(NoSuchEntryError):
pass


class ReadOnlyEntryError(KeyError):
pass

Expand Down Expand Up @@ -629,7 +644,7 @@ def _collision_check(self, key, stored_key, _stacklevel):
# This is here so we can step through equality comparison to
# see what is actually non-equal.
stored_key == key # pylint:disable=pointless-statement # noqa: B015
raise NoSuchEntryError(key)
raise NoSuchEntryCollisionError(key)

def __getitem__(self, key):
return self.fetch(key, _stacklevel=1)
Expand Down Expand Up @@ -783,7 +798,7 @@ def fetch(self, key, _stacklevel=0):
f"Remove the directory '{item_dir}' if necessary. "
f"(caught: {type(e).__name__}: {e})",
stacklevel=1 + _stacklevel)
raise NoSuchEntryError(key)
raise NoSuchEntryInvalidKeyError(key)

self._collision_check(key, read_key, 1 + _stacklevel)

Expand All @@ -796,12 +811,13 @@ def fetch(self, key, _stacklevel=0):

try:
read_contents = self._read(contents_file)
except Exception:
except Exception as e:
self._warn(f"{type(self).__name__}({self.identifier}) "
f"encountered an invalid key file for key {hexdigest_key}. "
f"Remove the directory '{item_dir}' if necessary.",
f"encountered an invalid contents file for key {hexdigest_key}. "
f"Remove the directory '{item_dir}' if necessary."
f"(caught: {type(e).__name__}: {e})",
stacklevel=1 + _stacklevel)
raise NoSuchEntryError(key)
raise NoSuchEntryInvalidContentsError(key)

# }}}

Expand Down Expand Up @@ -892,13 +908,14 @@ def fetch(self, key, _stacklevel=0):

try:
read_key = self._read(key_path)
except Exception:
except Exception as e:
item_dir_m.reset()
self._warn(f"{type(self).__name__}({self.identifier}) "
"encountered an invalid key file for key "
f"{hexdigest_key}. Entry deleted.",
f"{hexdigest_key}. Entry deleted."
f"(caught: {type(e).__name__}: {e})",
stacklevel=1 + _stacklevel)
raise NoSuchEntryError(key)
raise NoSuchEntryInvalidKeyError(key)

self._collision_check(key, read_key, 1 + _stacklevel)

Expand All @@ -911,13 +928,14 @@ def fetch(self, key, _stacklevel=0):

try:
read_contents = self._read(value_path)
except Exception:
except Exception as e:
item_dir_m.reset()
self._warn(f"{type(self).__name__}({self.identifier}) "
"encountered an invalid key file for key "
f"{hexdigest_key}. Entry deleted.",
"encountered an invalid contents file for key "
f"{hexdigest_key}. Entry deleted."
f"(caught: {type(e).__name__}: {e})",
stacklevel=1 + _stacklevel)
raise NoSuchEntryError(key)
raise NoSuchEntryInvalidContentsError(key)

return read_contents

Expand Down Expand Up @@ -950,13 +968,14 @@ def remove(self, key, _stacklevel=0):

try:
read_key = self._read(key_file)
except Exception:
except Exception as e:
item_dir_m.reset()
self._warn(f"{type(self).__name__}({self.identifier}) "
"encountered an invalid key file for key "
f"{hexdigest_key}. Entry deleted",
f"{hexdigest_key}. Entry deleted"
f"(caught: {type(e).__name__}: {e})",
stacklevel=1 + _stacklevel)
raise NoSuchEntryError(key)
raise NoSuchEntryInvalidKeyError(key)

self._collision_check(key, read_key, 1 + _stacklevel)

Expand Down
10 changes: 5 additions & 5 deletions pytools/test/test_persistent_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import pytest

from pytools.persistent_dict import (
CollisionWarning, KeyBuilder, NoSuchEntryError, PersistentDict,
ReadOnlyEntryError, WriteOncePersistentDict)
CollisionWarning, KeyBuilder, NoSuchEntryCollisionError, NoSuchEntryError,
PersistentDict, ReadOnlyEntryError, WriteOncePersistentDict)
from pytools.tag import Tag, tag_dataclass


Expand Down Expand Up @@ -214,12 +214,12 @@ def test_persistent_dict_cache_collisions():

# check lookup
with pytest.warns(CollisionWarning):
with pytest.raises(NoSuchEntryError):
with pytest.raises(NoSuchEntryCollisionError):
pdict.fetch(key2)

# check deletion
with pytest.warns(CollisionWarning):
with pytest.raises(NoSuchEntryError):
with pytest.raises(NoSuchEntryCollisionError):
del pdict[key2]

# check presence after deletion
Expand Down Expand Up @@ -342,7 +342,7 @@ def test_write_once_persistent_dict_cache_collisions():

# check lookup
with pytest.warns(CollisionWarning):
with pytest.raises(NoSuchEntryError):
with pytest.raises(NoSuchEntryCollisionError):
pdict.fetch(key2)

# check update
Expand Down

0 comments on commit dea0d87

Please sign in to comment.