arraybridge 0.3.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {arraybridge-0.3.0 → arraybridge-0.3.1}/PKG-INFO +1 -1
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/api_reference.rst +5 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/conf.py +1 -1
- {arraybridge-0.3.0 → arraybridge-0.3.1}/pyproject.toml +1 -1
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/__init__.py +3 -1
- arraybridge-0.3.1/src/arraybridge/array_geometry.py +57 -0
- arraybridge-0.3.1/tests/test_array_geometry.py +53 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/.github/workflows/ci.yml +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/.github/workflows/coverage-pages.yml +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/.github/workflows/gpu-tests.yml +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/.github/workflows/publish.yml +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/.gitignore +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/.readthedocs.yml +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/ADDING_NEW_FRAMEWORKS.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/CONTRIBUTING.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/LICENSE +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/README.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/TESTING.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/Makefile +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/CI_ARTIFACT_UPDATE.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/CI_CUPY_FIX.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/CI_IMPROVEMENTS.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/CONFLICT_VISUALIZATION.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/COVERAGE_AUDIT_PLAN.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/DEPLOYMENT_SUMMARY.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/GPU_TESTING_SETUP.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/MERGE_CONFLICT_RESOLUTION.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/MIGRATION_SUMMARY.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/QUICK_FIX_GUIDE.txt +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/README.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/archive/RESOLVED_FILES.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/ci-cd.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/.gitignore +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/Makefile +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/README.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/advanced_topics.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/ci-cd.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/contributing.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/converters.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/decorators.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/examples/basic_conversion.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/examples/decorators.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/examples/index.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/examples/multi_framework.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/gpu_features.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/index.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/installation.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/quickstart.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/stack_utils.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/docs/source/user_guide.rst +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/paper.bib +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/paper.md +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/scripts/release.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/scripts/update_version.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/scripts/verify_release_ready.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/array_operations.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/array_payload.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/converters.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/converters_registry.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/decorators.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/dtype_scaling.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/exceptions.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/framework_config.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/framework_ops.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/gpu_cleanup.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/oom_recovery.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/slice_processing.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/stack_utils.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/types.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/src/arraybridge/utils.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/__init__.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/conftest.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_converters.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_converters_registry.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_decorators.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_dtype_scaling.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_exceptions.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_framework_config.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_gpu_cleanup.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_integration.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_oom_recovery.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_registry_integration.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_slice_processing.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_stack_utils.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_types.py +0 -0
- {arraybridge-0.3.0 → arraybridge-0.3.1}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arraybridge
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Unified API for NumPy, CuPy, PyTorch, TensorFlow, JAX, and pyclesperanto with automatic memory type conversion
|
|
5
5
|
Project-URL: Homepage, https://github.com/OpenHCSDev/arraybridge
|
|
6
6
|
Project-URL: Documentation, https://arraybridge.readthedocs.io
|
|
@@ -12,6 +12,11 @@ Public imports
|
|
|
12
12
|
``detect_memory_type`` and ``convert_memory``
|
|
13
13
|
Detection and explicit conversion.
|
|
14
14
|
|
|
15
|
+
``ArrayGeometry``
|
|
16
|
+
Framework-neutral shape inspection for arrays and nominal ``ArrayPayload``
|
|
17
|
+
values. Geometry inspection reads declared shape metadata and does not move
|
|
18
|
+
device data to host memory.
|
|
19
|
+
|
|
15
20
|
``memory_types``, ``numpy``, ``cupy``, ``torch``, ``tensorflow``, ``jax``, ``pyclesperanto``
|
|
16
21
|
Callable memory declarations and wrappers.
|
|
17
22
|
|
|
@@ -22,7 +22,7 @@ sys.path.insert(0, str(PACKAGE_ROOT / "src"))
|
|
|
22
22
|
project = 'arraybridge'
|
|
23
23
|
copyright = '2025, Tristan Simas'
|
|
24
24
|
author = 'Tristan Simas'
|
|
25
|
-
release = '0.3.
|
|
25
|
+
release = '0.3.1'
|
|
26
26
|
|
|
27
27
|
# -- General configuration ---------------------------------------------------
|
|
28
28
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "arraybridge"
|
|
8
|
-
version = "0.3.
|
|
8
|
+
version = "0.3.1"
|
|
9
9
|
description = "Unified API for NumPy, CuPy, PyTorch, TensorFlow, JAX, and pyclesperanto with automatic memory type conversion"
|
|
10
10
|
authors = [{name = "Tristan Simas", email = "tristan.simas@mail.mcgill.ca"}]
|
|
11
11
|
license = {text = "MIT"}
|
|
@@ -5,9 +5,10 @@ This package provides automatic memory type conversion, declarative decorators,
|
|
|
5
5
|
and unified utilities for working with multiple array/tensor frameworks.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = "0.3.
|
|
8
|
+
__version__ = "0.3.1"
|
|
9
9
|
|
|
10
10
|
from . import decorators as _decorators
|
|
11
|
+
from .array_geometry import ArrayGeometry
|
|
11
12
|
from .array_payload import ArrayPayload
|
|
12
13
|
from .converters import convert_memory, detect_memory_type
|
|
13
14
|
from .dtype_scaling import SCALING_FUNCTIONS
|
|
@@ -39,6 +40,7 @@ __all__ = [
|
|
|
39
40
|
"MemoryType",
|
|
40
41
|
"MemoryContractAttribute",
|
|
41
42
|
"ArrayPayload",
|
|
43
|
+
"ArrayGeometry",
|
|
42
44
|
"CPU_MEMORY_TYPES",
|
|
43
45
|
"GPU_MEMORY_TYPES",
|
|
44
46
|
"SUPPORTED_MEMORY_TYPES",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Framework-neutral array geometry inspection."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from arraybridge.array_payload import ArrayPayload
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class ArrayGeometry:
|
|
15
|
+
"""Concrete shape metadata without moving array data between frameworks."""
|
|
16
|
+
|
|
17
|
+
shape: tuple[int, ...]
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def ndim(self) -> int:
|
|
21
|
+
"""Return the rank derived from the canonical shape."""
|
|
22
|
+
|
|
23
|
+
return len(self.shape)
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def from_value(cls, value: Any) -> ArrayGeometry | None:
|
|
27
|
+
"""Inspect an array or nominal payload without forcing host conversion."""
|
|
28
|
+
|
|
29
|
+
data = value.array_payload_data() if isinstance(value, ArrayPayload) else value
|
|
30
|
+
declared_shape = getattr(data, "shape", None)
|
|
31
|
+
if declared_shape is not None:
|
|
32
|
+
try:
|
|
33
|
+
return cls(tuple(int(axis_size) for axis_size in declared_shape))
|
|
34
|
+
except (TypeError, ValueError):
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
array = np.asarray(data)
|
|
39
|
+
except (TypeError, ValueError):
|
|
40
|
+
return None
|
|
41
|
+
return cls(tuple(int(axis_size) for axis_size in array.shape))
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def require_from_value(
|
|
45
|
+
cls,
|
|
46
|
+
value: Any,
|
|
47
|
+
*,
|
|
48
|
+
value_name: str = "Value",
|
|
49
|
+
) -> ArrayGeometry:
|
|
50
|
+
"""Return concrete geometry or reject a value without an array shape."""
|
|
51
|
+
|
|
52
|
+
geometry = cls.from_value(value)
|
|
53
|
+
if geometry is None:
|
|
54
|
+
raise TypeError(
|
|
55
|
+
f"{value_name} requires concrete array geometry, got " f"{type(value).__name__}."
|
|
56
|
+
)
|
|
57
|
+
return geometry
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from arraybridge import ArrayGeometry, ArrayPayload
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DeviceArray:
|
|
10
|
+
"""Array-shaped value that rejects implicit host conversion."""
|
|
11
|
+
|
|
12
|
+
shape = (2, 3, 4)
|
|
13
|
+
|
|
14
|
+
def __array__(self, dtype=None):
|
|
15
|
+
del dtype
|
|
16
|
+
raise TypeError("implicit host conversion is forbidden")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DevicePayload(ArrayPayload):
|
|
20
|
+
def __init__(self, data):
|
|
21
|
+
self.data = data
|
|
22
|
+
|
|
23
|
+
def array_payload_data(self):
|
|
24
|
+
return self.data
|
|
25
|
+
|
|
26
|
+
def with_data(self, data):
|
|
27
|
+
return type(self)(data)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_array_geometry_reads_declared_device_shape_without_host_conversion() -> None:
|
|
31
|
+
assert ArrayGeometry.from_value(DeviceArray()) == ArrayGeometry((2, 3, 4))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_array_geometry_unwraps_nominal_array_payload() -> None:
|
|
35
|
+
assert ArrayGeometry.from_value(DevicePayload(DeviceArray())) == ArrayGeometry((2, 3, 4))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_array_geometry_falls_back_for_python_array_inputs() -> None:
|
|
39
|
+
assert ArrayGeometry.from_value([[1, 2], [3, 4]]) == ArrayGeometry((2, 2))
|
|
40
|
+
assert ArrayGeometry.from_value(np.zeros((4, 5))) == ArrayGeometry((4, 5))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_array_geometry_requires_concrete_shape() -> None:
|
|
44
|
+
class UnshapedValue:
|
|
45
|
+
def __array__(self, dtype=None):
|
|
46
|
+
del dtype
|
|
47
|
+
raise TypeError("not an array")
|
|
48
|
+
|
|
49
|
+
with pytest.raises(TypeError, match="Runtime output requires concrete array geometry"):
|
|
50
|
+
ArrayGeometry.require_from_value(
|
|
51
|
+
UnshapedValue(),
|
|
52
|
+
value_name="Runtime output",
|
|
53
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|