From 984f123b1d0c00af7ea130cf6f8756ebd5368c6e Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Sat, 10 Oct 2026 23:22:39 -0400 Subject: [PATCH] 0.4.1: mypy-clean ArrayOperations cache; mypy blocks CI The v0.4.0 publish ran mypy, which PR CI ran as non-blocking, and failed on two errors in the new ArrayOperations family: the leaf cache keyed on the class (AutoRegisterMeta's __hash__ does not match Hashable) and an unchecked optional memory_type. The cache now keys on the memory type value, and CI's mypy step blocks so publish-only failures surface on the PR. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 1 - src/arraybridge/__init__.py | 2 +- src/arraybridge/array_operations.py | 8 +++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 904f876..913717c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -153,6 +153,5 @@ jobs: black --check src/ - name: Run mypy (type checking) - continue-on-error: true # Scientific code often has complex types run: | mypy src/ diff --git a/src/arraybridge/__init__.py b/src/arraybridge/__init__.py index 28b3802..bf3496c 100644 --- a/src/arraybridge/__init__.py +++ b/src/arraybridge/__init__.py @@ -10,7 +10,7 @@ NumPy/numcodecs import cost. """ -__version__ = "0.4.0" +__version__ = "0.4.1" _LAZY_EXPORTS: dict[str, str] = { "MemoryType": ".types", diff --git a/src/arraybridge/array_operations.py b/src/arraybridge/array_operations.py index 13772a9..a628c0f 100644 --- a/src/arraybridge/array_operations.py +++ b/src/arraybridge/array_operations.py @@ -78,8 +78,8 @@ def _mapped_dtype(target_dtype: Any, module: Any) -> Any: @cache -def _leaf_instance(leaf: type[ArrayOperations]) -> ArrayOperations: - return leaf() +def _leaf_instance(memory_type_value: str) -> ArrayOperations: + return ArrayOperations.__registry__[memory_type_value]() class ArrayOperations(metaclass=AutoRegisterMeta): @@ -98,13 +98,15 @@ class ArrayOperations(metaclass=AutoRegisterMeta): @classmethod def for_memory(cls, memory_type: MemoryType) -> ArrayOperations: """Return the operations leaf declared for ``memory_type``.""" - return _leaf_instance(cls.__registry__[memory_type.value]) + return _leaf_instance(memory_type.value) @cached_property def module(self) -> Any: """The framework module, imported on first use.""" from arraybridge.types import MemoryType + # Only registered leaves are instantiated, and each declares memory_type. + assert self.memory_type is not None return MemoryType(self.memory_type).import_module() @property