From dea0d8780a2d42ea6c46938bd11bfe5f460cb244 Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Mon, 27 Nov 2023 14:20:39 -0600 Subject: [PATCH] persistent_dict: separate different sources of KeyErrors (#189) * persistent_dict: separate different sources of KeyErrors * add to doc --- pytools/persistent_dict.py | 51 +++++++++++++++++++--------- pytools/test/test_persistent_dict.py | 10 +++--- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/pytools/persistent_dict.py b/pytools/persistent_dict.py index 65fb6e9c..e8f1d7ec 100644 --- a/pytools/persistent_dict.py +++ b/pytools/persistent_dict.py @@ -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 @@ -528,6 +531,18 @@ class NoSuchEntryError(KeyError): pass +class NoSuchEntryInvalidKeyError(NoSuchEntryError): + pass + + +class NoSuchEntryInvalidContentsError(NoSuchEntryError): + pass + + +class NoSuchEntryCollisionError(NoSuchEntryError): + pass + + class ReadOnlyEntryError(KeyError): pass @@ -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) @@ -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) @@ -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) # }}} @@ -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) @@ -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 @@ -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) diff --git a/pytools/test/test_persistent_dict.py b/pytools/test/test_persistent_dict.py index 2c3aeabd..85576828 100644 --- a/pytools/test/test_persistent_dict.py +++ b/pytools/test/test_persistent_dict.py @@ -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 @@ -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 @@ -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