diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3df093d1..13f219a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: python-version: '3.x' - name: "Main Script" run: | - EXTRA_INSTALL="numpy" + EXTRA_INSTALL="numpy siphash24" curl -L -O https://gitlab.tiker.net/inducer/ci-support/raw/main/prepare-and-run-mypy.sh . ./prepare-and-run-mypy.sh python3 mypy @@ -89,7 +89,7 @@ jobs: # AK, 2020-12-13 rm pytools/mpiwrap.py - EXTRA_INSTALL="numpy frozendict immutabledict orderedsets constantdict immutables pyrsistent attrs" + EXTRA_INSTALL="numpy frozendict immutabledict orderedsets constantdict immutables pyrsistent attrs siphash24" curl -L -O https://gitlab.tiker.net/inducer/ci-support/raw/main/build-and-test-py-project.sh . ./build-and-test-py-project.sh @@ -104,6 +104,7 @@ jobs: python-version: '3.x' - name: "Main Script" run: | + EXTRA_INSTALL="siphash24" rm pytools/{convergence,spatial_btree,obj_array,mpiwrap}.py curl -L -O https://gitlab.tiker.net/inducer/ci-support/raw/main/build-and-test-py-project.sh . ./build-and-test-py-project.sh diff --git a/pyproject.toml b/pyproject.toml index 2fce1070..a134159b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,6 @@ dependencies = [ "platformdirs>=2.2", # for dataclass_transform with frozen_default "typing-extensions>=4; python_version<'3.13'", - "siphash24>=1.6", ] [project.optional-dependencies] @@ -46,6 +45,9 @@ test = [ "pytest", "ruff", ] +siphash = [ + "siphash24>=1.6", +] [project.urls] Documentation = "https://documen.tician.de/pytools/" diff --git a/pytools/persistent_dict.py b/pytools/persistent_dict.py index 50e35072..f3a5a05d 100644 --- a/pytools/persistent_dict.py +++ b/pytools/persistent_dict.py @@ -50,9 +50,15 @@ TypeVar, cast, ) +from warnings import warn -from siphash24 import siphash13 +try: + from siphash24 import siphash13 as _default_hash +except ImportError: + warn("pytools.persistent_dict: unable to import 'siphash24.siphash13', " + "falling back to hashlib.sha256", stacklevel=1) + from hashlib import sha256 as _default_hash if TYPE_CHECKING: from _typeshed import ReadableBuffer @@ -161,7 +167,7 @@ class KeyBuilder: # this exists so that we can (conceivably) switch algorithms at some point # down the road - new_hash: Callable[..., Hash] = siphash13 + new_hash: Callable[..., Hash] = _default_hash def rec(self, key_hash: Hash, key: Any) -> Hash: """ @@ -429,7 +435,6 @@ class CollisionWarning(UserWarning): def __getattr__(name: str) -> Any: if name in ("NoSuchEntryInvalidKeyError", "NoSuchEntryInvalidContentsError"): - from warnings import warn warn(f"pytools.persistent_dict.{name} has been removed.", stacklevel=2) return NoSuchEntryError @@ -506,7 +511,6 @@ def __init__(self, # https://www.sqlite.org/pragma.html#pragma_synchronous if safe_sync is None or safe_sync: if safe_sync is None: - from warnings import warn warn(f"pytools.persistent_dict '{identifier}': " "enabling safe_sync as default. " "This provides strong protection against data loss, " @@ -531,7 +535,6 @@ def __del__(self) -> None: def _collision_check(self, key: K, stored_key: K) -> None: if stored_key != key: # Key collision, oh well. - from warnings import warn warn(f"{self.identifier}: key collision in cache at " f"'{self.container_dir}' -- these are sufficiently unlikely " "that they're often indicative of a broken hash key " @@ -571,7 +574,6 @@ def _exec_sql_fn(self, fn: Callable[[], T]) -> Optional[T]: and not e.sqlite_errorcode == sqlite3.SQLITE_BUSY): raise if n % 20 == 0: - from warnings import warn warn(f"PersistentDict: database '{self.filename}' busy, {n} " "retries", stacklevel=3) else: