arraybridge 0.2.10__tar.gz → 0.3.0__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.2.10 → arraybridge-0.3.0}/.github/workflows/ci.yml +1 -1
- {arraybridge-0.2.10 → arraybridge-0.3.0}/.github/workflows/coverage-pages.yml +4 -15
- {arraybridge-0.2.10 → arraybridge-0.3.0}/.github/workflows/publish.yml +20 -4
- arraybridge-0.3.0/ADDING_NEW_FRAMEWORKS.md +63 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/CONTRIBUTING.md +38 -25
- arraybridge-0.3.0/PKG-INFO +143 -0
- arraybridge-0.3.0/README.md +73 -0
- arraybridge-0.3.0/TESTING.md +46 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/CI_IMPROVEMENTS.md +0 -1
- arraybridge-0.3.0/docs/archive/README.md +5 -0
- arraybridge-0.3.0/docs/ci-cd.md +7 -0
- arraybridge-0.3.0/docs/source/README.md +15 -0
- arraybridge-0.3.0/docs/source/advanced_topics.rst +24 -0
- arraybridge-0.3.0/docs/source/api_reference.rst +40 -0
- arraybridge-0.3.0/docs/source/ci-cd.rst +25 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/docs/source/conf.py +13 -5
- arraybridge-0.3.0/docs/source/contributing.rst +27 -0
- arraybridge-0.3.0/docs/source/converters.rst +47 -0
- arraybridge-0.3.0/docs/source/decorators.rst +59 -0
- arraybridge-0.3.0/docs/source/examples/basic_conversion.rst +16 -0
- arraybridge-0.3.0/docs/source/examples/decorators.rst +18 -0
- arraybridge-0.3.0/docs/source/examples/multi_framework.rst +18 -0
- arraybridge-0.3.0/docs/source/gpu_features.rst +34 -0
- arraybridge-0.3.0/docs/source/index.rst +33 -0
- arraybridge-0.3.0/docs/source/installation.rst +58 -0
- arraybridge-0.3.0/docs/source/quickstart.rst +54 -0
- arraybridge-0.3.0/docs/source/stack_utils.rst +25 -0
- arraybridge-0.3.0/docs/source/user_guide.rst +35 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/pyproject.toml +17 -8
- arraybridge-0.3.0/scripts/release.py +117 -0
- arraybridge-0.3.0/scripts/update_version.py +79 -0
- arraybridge-0.3.0/scripts/verify_release_ready.py +307 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/src/arraybridge/__init__.py +22 -19
- arraybridge-0.3.0/src/arraybridge/array_operations.py +396 -0
- arraybridge-0.3.0/src/arraybridge/array_payload.py +31 -0
- arraybridge-0.3.0/src/arraybridge/converters.py +85 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/src/arraybridge/converters_registry.py +47 -69
- arraybridge-0.3.0/src/arraybridge/decorators.py +577 -0
- arraybridge-0.3.0/src/arraybridge/dtype_scaling.py +25 -0
- arraybridge-0.3.0/src/arraybridge/framework_config.py +26 -0
- arraybridge-0.3.0/src/arraybridge/framework_ops.py +7 -0
- arraybridge-0.3.0/src/arraybridge/gpu_cleanup.py +78 -0
- arraybridge-0.3.0/src/arraybridge/oom_recovery.py +90 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/src/arraybridge/slice_processing.py +36 -5
- {arraybridge-0.2.10 → arraybridge-0.3.0}/src/arraybridge/stack_utils.py +23 -127
- arraybridge-0.3.0/src/arraybridge/types.py +984 -0
- arraybridge-0.3.0/src/arraybridge/utils.py +173 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_converters.py +58 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_converters_registry.py +37 -31
- arraybridge-0.3.0/tests/test_decorators.py +541 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_dtype_scaling.py +85 -59
- arraybridge-0.3.0/tests/test_framework_config.py +29 -0
- arraybridge-0.3.0/tests/test_gpu_cleanup.py +156 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_registry_integration.py +5 -22
- {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_slice_processing.py +29 -5
- arraybridge-0.3.0/tests/test_stack_utils.py +378 -0
- arraybridge-0.3.0/tests/test_types.py +446 -0
- arraybridge-0.3.0/tests/test_utils.py +248 -0
- arraybridge-0.2.10/.github/badges/coverage.svg +0 -1
- arraybridge-0.2.10/ADDING_NEW_FRAMEWORKS.md +0 -215
- arraybridge-0.2.10/PKG-INFO +0 -243
- arraybridge-0.2.10/README.md +0 -175
- arraybridge-0.2.10/SETUP_INSTRUCTIONS.md +0 -64
- arraybridge-0.2.10/TESTING.md +0 -175
- arraybridge-0.2.10/docs/ci-cd.md +0 -352
- arraybridge-0.2.10/docs/source/README.md +0 -145
- arraybridge-0.2.10/docs/source/advanced_topics.rst +0 -637
- arraybridge-0.2.10/docs/source/api/converters.rst +0 -46
- arraybridge-0.2.10/docs/source/api/decorators.rst +0 -72
- arraybridge-0.2.10/docs/source/api/exceptions.rst +0 -39
- arraybridge-0.2.10/docs/source/api/index.rst +0 -24
- arraybridge-0.2.10/docs/source/api/types.rst +0 -54
- arraybridge-0.2.10/docs/source/api/utils.rst +0 -70
- arraybridge-0.2.10/docs/source/api_reference.rst +0 -629
- arraybridge-0.2.10/docs/source/ci-cd.rst +0 -32
- arraybridge-0.2.10/docs/source/contributing.rst +0 -24
- arraybridge-0.2.10/docs/source/converters.rst +0 -474
- arraybridge-0.2.10/docs/source/decorators.rst +0 -638
- arraybridge-0.2.10/docs/source/examples/basic_conversion.rst +0 -98
- arraybridge-0.2.10/docs/source/examples/decorators.rst +0 -124
- arraybridge-0.2.10/docs/source/examples/multi_framework.rst +0 -132
- arraybridge-0.2.10/docs/source/gpu_features.rst +0 -624
- arraybridge-0.2.10/docs/source/index.rst +0 -96
- arraybridge-0.2.10/docs/source/installation.rst +0 -229
- arraybridge-0.2.10/docs/source/quickstart.rst +0 -281
- arraybridge-0.2.10/docs/source/stack_utils.rst +0 -603
- arraybridge-0.2.10/docs/source/user_guide.rst +0 -568
- arraybridge-0.2.10/scripts/release.py +0 -63
- arraybridge-0.2.10/scripts/update_and_release.py +0 -114
- arraybridge-0.2.10/scripts/update_version.py +0 -111
- arraybridge-0.2.10/scripts/verify_release_ready.py +0 -274
- arraybridge-0.2.10/src/arraybridge/converters.py +0 -71
- arraybridge-0.2.10/src/arraybridge/decorators.py +0 -387
- arraybridge-0.2.10/src/arraybridge/dtype_scaling.py +0 -179
- arraybridge-0.2.10/src/arraybridge/framework_config.py +0 -442
- arraybridge-0.2.10/src/arraybridge/framework_ops.py +0 -14
- arraybridge-0.2.10/src/arraybridge/gpu_cleanup.py +0 -141
- arraybridge-0.2.10/src/arraybridge/oom_recovery.py +0 -148
- arraybridge-0.2.10/src/arraybridge/types.py +0 -47
- arraybridge-0.2.10/src/arraybridge/utils.py +0 -366
- arraybridge-0.2.10/tests/test_decorators.py +0 -234
- arraybridge-0.2.10/tests/test_framework_config.py +0 -412
- arraybridge-0.2.10/tests/test_gpu_cleanup.py +0 -244
- arraybridge-0.2.10/tests/test_stack_utils.py +0 -169
- arraybridge-0.2.10/tests/test_types.py +0 -81
- arraybridge-0.2.10/tests/test_utils.py +0 -404
- {arraybridge-0.2.10 → arraybridge-0.3.0}/.github/workflows/gpu-tests.yml +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/.gitignore +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/.readthedocs.yml +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/LICENSE +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/docs/Makefile +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/CI_ARTIFACT_UPDATE.md +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/CI_CUPY_FIX.md +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/CONFLICT_VISUALIZATION.md +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/COVERAGE_AUDIT_PLAN.md +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/DEPLOYMENT_SUMMARY.md +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/GPU_TESTING_SETUP.md +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/MERGE_CONFLICT_RESOLUTION.md +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/MIGRATION_SUMMARY.md +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/QUICK_FIX_GUIDE.txt +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/RESOLVED_FILES.md +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/docs/source/.gitignore +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/docs/source/Makefile +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/docs/source/examples/index.rst +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/paper.bib +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/paper.md +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/src/arraybridge/exceptions.py +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/__init__.py +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/conftest.py +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_exceptions.py +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_integration.py +0 -0
- {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_oom_recovery.py +0 -0
|
@@ -6,7 +6,7 @@ on:
|
|
|
6
6
|
workflow_dispatch:
|
|
7
7
|
|
|
8
8
|
permissions:
|
|
9
|
-
contents:
|
|
9
|
+
contents: read
|
|
10
10
|
pages: write
|
|
11
11
|
id-token: write
|
|
12
12
|
|
|
@@ -40,7 +40,6 @@ jobs:
|
|
|
40
40
|
pip install torch --index-url https://download.pytorch.org/whl/cpu
|
|
41
41
|
|
|
42
42
|
- name: Run tests with coverage
|
|
43
|
-
continue-on-error: true # Continue workflow even if tests fail
|
|
44
43
|
run: |
|
|
45
44
|
mkdir -p site
|
|
46
45
|
python -m pytest --cov=arraybridge \
|
|
@@ -50,8 +49,7 @@ jobs:
|
|
|
50
49
|
|
|
51
50
|
- name: Generate coverage badge
|
|
52
51
|
run: |
|
|
53
|
-
|
|
54
|
-
genbadge coverage -i coverage.xml -o .github/badges/coverage.svg -n "coverage"
|
|
52
|
+
genbadge coverage -i coverage.xml -o site/coverage-badge.svg -n "coverage"
|
|
55
53
|
|
|
56
54
|
- name: Create index.html and README
|
|
57
55
|
run: |
|
|
@@ -72,7 +70,7 @@ jobs:
|
|
|
72
70
|
# Create README.md in the site directory
|
|
73
71
|
echo "# arraybridge Code Coverage Reports" > site/README.md
|
|
74
72
|
echo "" >> site/README.md
|
|
75
|
-
echo "This site contains the code coverage reports for the [arraybridge](https://github.com/
|
|
73
|
+
echo "This site contains the code coverage reports for the [arraybridge](https://github.com/OpenHCSDev/arraybridge) project." >> site/README.md
|
|
76
74
|
echo "" >> site/README.md
|
|
77
75
|
echo "## Navigation" >> site/README.md
|
|
78
76
|
echo "" >> site/README.md
|
|
@@ -85,19 +83,10 @@ jobs:
|
|
|
85
83
|
echo "" >> site/README.md
|
|
86
84
|
echo "Last updated: $(date)" >> site/README.md
|
|
87
85
|
|
|
88
|
-
- name: Commit and push if coverage badge changed
|
|
89
|
-
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
90
|
-
run: |
|
|
91
|
-
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
|
92
|
-
git config --local user.name "github-actions[bot]"
|
|
93
|
-
git add .github/badges/coverage.svg -f
|
|
94
|
-
git commit -m "chore: update coverage badge" || exit 0
|
|
95
|
-
git push
|
|
96
|
-
|
|
97
86
|
- name: Check GitHub Pages status
|
|
98
87
|
run: |
|
|
99
88
|
echo "⚠️ IMPORTANT: Make sure GitHub Pages is enabled in your repository settings!"
|
|
100
|
-
echo "Go to https://github.com/
|
|
89
|
+
echo "Go to https://github.com/OpenHCSDev/arraybridge/settings/pages"
|
|
101
90
|
echo "Set 'Source' to 'GitHub Actions' to enable GitHub Pages deployment."
|
|
102
91
|
|
|
103
92
|
- name: Setup Pages
|
|
@@ -20,6 +20,8 @@ jobs:
|
|
|
20
20
|
steps:
|
|
21
21
|
- name: Checkout code
|
|
22
22
|
uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0
|
|
23
25
|
|
|
24
26
|
- name: Set up Python
|
|
25
27
|
uses: actions/setup-python@v5
|
|
@@ -29,7 +31,21 @@ jobs:
|
|
|
29
31
|
- name: Install build dependencies
|
|
30
32
|
run: |
|
|
31
33
|
python -m pip install --upgrade pip
|
|
32
|
-
pip install
|
|
34
|
+
pip install -e ".[dev]"
|
|
35
|
+
|
|
36
|
+
- name: Validate source and tests
|
|
37
|
+
run: |
|
|
38
|
+
ruff check src/ scripts/
|
|
39
|
+
black --check src/ scripts/
|
|
40
|
+
mypy src/
|
|
41
|
+
pytest -q --no-cov
|
|
42
|
+
|
|
43
|
+
- name: Verify release tag and main ancestry
|
|
44
|
+
run: |
|
|
45
|
+
declared_version=$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
|
|
46
|
+
test "$GITHUB_REF_NAME" = "v$declared_version"
|
|
47
|
+
git fetch origin main
|
|
48
|
+
git merge-base --is-ancestor "$GITHUB_SHA" origin/main
|
|
33
49
|
|
|
34
50
|
- name: Build package
|
|
35
51
|
run: python -m build
|
|
@@ -39,6 +55,9 @@ jobs:
|
|
|
39
55
|
pip install twine
|
|
40
56
|
twine check dist/*
|
|
41
57
|
|
|
58
|
+
- name: Publish to PyPI
|
|
59
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
60
|
+
|
|
42
61
|
- name: Create GitHub Release
|
|
43
62
|
uses: softprops/action-gh-release@v2
|
|
44
63
|
with:
|
|
@@ -46,6 +65,3 @@ jobs:
|
|
|
46
65
|
generate_release_notes: true
|
|
47
66
|
env:
|
|
48
67
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
49
|
-
|
|
50
|
-
- name: Publish to PyPI
|
|
51
|
-
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Adding a framework
|
|
2
|
+
|
|
3
|
+
This is a maintainer how-to for extending ArrayBridge's closed framework
|
|
4
|
+
taxonomy. Applications should consume `MemoryType`; they should not add their
|
|
5
|
+
own framework registry.
|
|
6
|
+
|
|
7
|
+
## 1. Define typed leaves
|
|
8
|
+
|
|
9
|
+
Add an `ArrayOperations` bundle in
|
|
10
|
+
`src/arraybridge/array_operations.py`. It must provide four ordinary callables:
|
|
11
|
+
|
|
12
|
+
- project an array to NumPy;
|
|
13
|
+
- create an array from NumPy on the requested framework-local device;
|
|
14
|
+
- stack prepared 2D arrays into one 3D array;
|
|
15
|
+
- apply the framework's dtype-scaling semantics.
|
|
16
|
+
|
|
17
|
+
Define device, stream, DLPack, cleanup, and OOM leaves in
|
|
18
|
+
`src/arraybridge/types.py`. Use the no-op defaults in `FrameworkRuntime` only
|
|
19
|
+
when the framework genuinely lacks that capability. Do not encode behavior as
|
|
20
|
+
strings or add a parallel `MemoryType`-keyed table.
|
|
21
|
+
|
|
22
|
+
## 2. Add the declaration
|
|
23
|
+
|
|
24
|
+
Add one `MemoryType` member carrying:
|
|
25
|
+
|
|
26
|
+
1. its stable value and import name;
|
|
27
|
+
2. its display name and module aliases;
|
|
28
|
+
3. whether it is GPU-backed;
|
|
29
|
+
4. any environment defaults that must be set before first import;
|
|
30
|
+
5. its `FrameworkRuntime` leaves;
|
|
31
|
+
6. its `ArrayOperations` bundle.
|
|
32
|
+
|
|
33
|
+
The converter classes, target conversion methods, compatibility operation view,
|
|
34
|
+
dtype-scaling view, cleanup adapters, and framework decorator are generated
|
|
35
|
+
from the enum. Do not wire them manually.
|
|
36
|
+
|
|
37
|
+
## 3. Prove the extension
|
|
38
|
+
|
|
39
|
+
Add focused tests for:
|
|
40
|
+
|
|
41
|
+
- module-name detection and optional-dependency failure;
|
|
42
|
+
- NumPy round trips and every supported DLPack pair;
|
|
43
|
+
- CPU-only installations of a nominally GPU framework;
|
|
44
|
+
- invalid, negative, and multiple framework-local device IDs;
|
|
45
|
+
- same-framework moves between two devices;
|
|
46
|
+
- one-, two-, and multi-slice stack/unstack behavior;
|
|
47
|
+
- immutable array types;
|
|
48
|
+
- cleanup and OOM behavior without importing an absent framework;
|
|
49
|
+
- generated registry and export completeness.
|
|
50
|
+
|
|
51
|
+
Run:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
ruff check src tests
|
|
55
|
+
black --check src tests
|
|
56
|
+
mypy src --ignore-missing-imports
|
|
57
|
+
pytest
|
|
58
|
+
python -m sphinx -E -W --keep-going -b html docs/source /tmp/arraybridge-docs
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
When GPU hardware is available, also exercise every installed framework pair in
|
|
62
|
+
one process. This catches import-order, allocator-coexistence, DLPack, and real
|
|
63
|
+
API-shape defects that isolated mocks cannot prove.
|
|
@@ -35,7 +35,7 @@ We are committed to providing a welcoming and inclusive environment. Please be r
|
|
|
35
35
|
|
|
36
36
|
### Finding Issues
|
|
37
37
|
|
|
38
|
-
- Check the [issue tracker](https://github.com/
|
|
38
|
+
- Check the [issue tracker](https://github.com/OpenHCSDev/arraybridge/issues)
|
|
39
39
|
- Look for issues labeled `good first issue` or `help wanted`
|
|
40
40
|
- Feel free to create new issues for bugs or feature requests
|
|
41
41
|
|
|
@@ -49,7 +49,7 @@ git clone https://github.com/YOUR_USERNAME/arraybridge.git
|
|
|
49
49
|
cd arraybridge
|
|
50
50
|
|
|
51
51
|
# Add upstream remote
|
|
52
|
-
git remote add upstream https://github.com/
|
|
52
|
+
git remote add upstream https://github.com/OpenHCSDev/arraybridge.git
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
### 2. Create Virtual Environment
|
|
@@ -135,13 +135,11 @@ def convert_memory(data: Any, source_type: str, target_type: str, gpu_id: int) -
|
|
|
135
135
|
MemoryConversionError: If conversion fails
|
|
136
136
|
|
|
137
137
|
Example:
|
|
138
|
-
```python
|
|
139
138
|
import numpy as np
|
|
140
139
|
from arraybridge import convert_memory
|
|
141
140
|
|
|
142
141
|
data = np.array([1, 2, 3])
|
|
143
142
|
result = convert_memory(data, "numpy", "torch", gpu_id=0)
|
|
144
|
-
```
|
|
145
143
|
"""
|
|
146
144
|
```
|
|
147
145
|
|
|
@@ -334,35 +332,48 @@ git push origin feature/your-feature-name
|
|
|
334
332
|
|
|
335
333
|
### 1. Update Version
|
|
336
334
|
|
|
337
|
-
|
|
335
|
+
Update all three validated version projections with the side-effect-free helper:
|
|
338
336
|
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
version = "0.2.0"
|
|
337
|
+
```bash
|
|
338
|
+
python scripts/update_version.py 0.3.0
|
|
342
339
|
```
|
|
343
340
|
|
|
341
|
+
Review the package, project, and documentation changes, then run
|
|
342
|
+
`python scripts/verify_release_ready.py --allow-dirty` before committing.
|
|
343
|
+
|
|
344
344
|
### 2. Update Changelog
|
|
345
345
|
|
|
346
346
|
Add release notes to `CHANGELOG.md` (if exists) or create GitHub release notes.
|
|
347
347
|
|
|
348
|
-
### 3.
|
|
348
|
+
### 3. Validate, Commit, and Push
|
|
349
349
|
|
|
350
350
|
```bash
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
351
|
+
ruff check src tests scripts
|
|
352
|
+
black --check src scripts
|
|
353
|
+
mypy src --ignore-missing-imports
|
|
354
|
+
pytest
|
|
355
|
+
python -m sphinx -E -W --keep-going -b html docs/source /tmp/arraybridge-docs
|
|
356
|
+
git commit
|
|
357
|
+
git push origin HEAD:main
|
|
358
|
+
```
|
|
354
359
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
360
|
+
### 4. Create the Release Tag
|
|
361
|
+
|
|
362
|
+
After the pushed commit is exactly `origin/main`, run:
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
python scripts/release.py
|
|
358
366
|
```
|
|
359
367
|
|
|
360
|
-
|
|
368
|
+
The script validates the clean published commit, confirms the PyPI version, and
|
|
369
|
+
pushes the matching annotated tag.
|
|
370
|
+
|
|
371
|
+
### 5. Automated Publishing
|
|
361
372
|
|
|
362
373
|
GitHub Actions will automatically:
|
|
363
|
-
1.
|
|
364
|
-
2.
|
|
365
|
-
3.
|
|
374
|
+
1. verify the tag, source, tests, and package metadata;
|
|
375
|
+
2. publish to PyPI;
|
|
376
|
+
3. create the GitHub release.
|
|
366
377
|
|
|
367
378
|
## Development Guidelines
|
|
368
379
|
|
|
@@ -393,12 +404,14 @@ GitHub Actions will automatically:
|
|
|
393
404
|
|
|
394
405
|
To add support for a new framework:
|
|
395
406
|
|
|
396
|
-
1.
|
|
397
|
-
2. Add
|
|
398
|
-
3.
|
|
399
|
-
4.
|
|
400
|
-
|
|
401
|
-
|
|
407
|
+
1. Add typed array-operation leaves in `array_operations.py`.
|
|
408
|
+
2. Add one `MemoryType` declaration carrying those operations and its runtime leaves.
|
|
409
|
+
3. Add detection, conversion-pair, stack, cross-device, and optional-dependency tests.
|
|
410
|
+
4. Update the extension and reference documentation.
|
|
411
|
+
|
|
412
|
+
Do not add framework behavior to `_FRAMEWORK_CONFIG`, a consumer registry, or
|
|
413
|
+
generated decorator exports. See `ADDING_NEW_FRAMEWORKS.md` for the complete
|
|
414
|
+
declaration-owned extension procedure.
|
|
402
415
|
|
|
403
416
|
## Getting Help
|
|
404
417
|
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: arraybridge
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Unified API for NumPy, CuPy, PyTorch, TensorFlow, JAX, and pyclesperanto with automatic memory type conversion
|
|
5
|
+
Project-URL: Homepage, https://github.com/OpenHCSDev/arraybridge
|
|
6
|
+
Project-URL: Documentation, https://arraybridge.readthedocs.io
|
|
7
|
+
Project-URL: Repository, https://github.com/OpenHCSDev/arraybridge
|
|
8
|
+
Project-URL: Issues, https://github.com/OpenHCSDev/arraybridge/issues
|
|
9
|
+
Author-email: Tristan Simas <tristan.simas@mail.mcgill.ca>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: array,conversion,cupy,gpu,jax,numpy,pytorch,tensor,tensorflow
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: metaclass-registry>=0.1.5
|
|
25
|
+
Requires-Dist: numpy>=1.20
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: cupy>=10.0; extra == 'all'
|
|
28
|
+
Requires-Dist: jax>=0.3; extra == 'all'
|
|
29
|
+
Requires-Dist: jaxlib>=0.3; extra == 'all'
|
|
30
|
+
Requires-Dist: pyclesperanto>=0.10; extra == 'all'
|
|
31
|
+
Requires-Dist: tensorflow>=2.8; extra == 'all'
|
|
32
|
+
Requires-Dist: torch>=1.10; extra == 'all'
|
|
33
|
+
Provides-Extra: cupy
|
|
34
|
+
Requires-Dist: cupy>=10.0; extra == 'cupy'
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: black>=23.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: packaging>=23.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
41
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
42
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
43
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
44
|
+
Provides-Extra: docs
|
|
45
|
+
Requires-Dist: sphinx-autodoc-typehints>=1.25; extra == 'docs'
|
|
46
|
+
Requires-Dist: sphinx-rtd-theme>=2.0; extra == 'docs'
|
|
47
|
+
Requires-Dist: sphinx>=7.0; extra == 'docs'
|
|
48
|
+
Provides-Extra: gpu
|
|
49
|
+
Requires-Dist: cucim-cu12<26.0.0,>=25.6.0; extra == 'gpu'
|
|
50
|
+
Requires-Dist: cupy-cuda12x<14.0.0,>=13.3.0; extra == 'gpu'
|
|
51
|
+
Requires-Dist: jax-cuda12-pjrt<0.6.0,>=0.5.3; extra == 'gpu'
|
|
52
|
+
Requires-Dist: jax-cuda12-plugin<0.6.0,>=0.5.3; extra == 'gpu'
|
|
53
|
+
Requires-Dist: jax<0.6.0,>=0.5.3; extra == 'gpu'
|
|
54
|
+
Requires-Dist: jaxlib<0.6.0,>=0.5.3; extra == 'gpu'
|
|
55
|
+
Requires-Dist: pyclesperanto>=0.17.1; extra == 'gpu'
|
|
56
|
+
Requires-Dist: tensorflow-probability[tf]<0.26.0,>=0.25.0; extra == 'gpu'
|
|
57
|
+
Requires-Dist: tensorflow<2.20.0,>=2.19.0; extra == 'gpu'
|
|
58
|
+
Requires-Dist: torch<2.8.0,>=2.6.0; extra == 'gpu'
|
|
59
|
+
Requires-Dist: torchvision<0.23.0,>=0.21.0; extra == 'gpu'
|
|
60
|
+
Provides-Extra: jax
|
|
61
|
+
Requires-Dist: jax>=0.3; extra == 'jax'
|
|
62
|
+
Requires-Dist: jaxlib>=0.3; extra == 'jax'
|
|
63
|
+
Provides-Extra: pyclesperanto
|
|
64
|
+
Requires-Dist: pyclesperanto>=0.10; extra == 'pyclesperanto'
|
|
65
|
+
Provides-Extra: tensorflow
|
|
66
|
+
Requires-Dist: tensorflow>=2.8; extra == 'tensorflow'
|
|
67
|
+
Provides-Extra: torch
|
|
68
|
+
Requires-Dist: torch>=1.10; extra == 'torch'
|
|
69
|
+
Description-Content-Type: text/markdown
|
|
70
|
+
|
|
71
|
+
# arraybridge
|
|
72
|
+
|
|
73
|
+
ArrayBridge provides explicit conversion and shared lifecycle utilities for
|
|
74
|
+
NumPy, CuPy, PyTorch, TensorFlow, JAX, and pyclesperanto arrays.
|
|
75
|
+
|
|
76
|
+
Core dependencies are NumPy and metaclass-registry. Other frameworks are
|
|
77
|
+
optional.
|
|
78
|
+
|
|
79
|
+
## Quick start
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
import numpy as np
|
|
83
|
+
|
|
84
|
+
from arraybridge import convert_memory, detect_memory_type
|
|
85
|
+
|
|
86
|
+
value = np.arange(6).reshape(2, 3)
|
|
87
|
+
assert detect_memory_type(value) == "numpy"
|
|
88
|
+
|
|
89
|
+
copy = convert_memory(
|
|
90
|
+
value,
|
|
91
|
+
source_type="numpy",
|
|
92
|
+
target_type="numpy",
|
|
93
|
+
gpu_id=0,
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`convert_memory` requires the declared source type, target type, and device id.
|
|
98
|
+
The source and target `MemoryType` declarations perform conversion directly.
|
|
99
|
+
The device id is required even for CPU conversions so call sites have one
|
|
100
|
+
stable signature. A GPU target must declare that identifier as available;
|
|
101
|
+
ArrayBridge does not silently place the value on the CPU.
|
|
102
|
+
|
|
103
|
+
## Declarative decorators
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from arraybridge import numpy
|
|
107
|
+
|
|
108
|
+
@numpy
|
|
109
|
+
def normalize(image):
|
|
110
|
+
return image / max(float(image.max()), 1.0)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The framework decorators attach `input_memory_type`, `output_memory_type`, and
|
|
114
|
+
`execution_memory_type` metadata, provide dtype/slice runtime parameters, and
|
|
115
|
+
add framework-specific stream/OOM handling where supported. They do **not**
|
|
116
|
+
convert inputs or outputs between frameworks and do not accept a `gpu_id`
|
|
117
|
+
argument. A host runtime must call `convert_memory` at the boundary it plans and
|
|
118
|
+
scope execution using the execution declaration.
|
|
119
|
+
|
|
120
|
+
## Stack utilities
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
import numpy as np
|
|
124
|
+
|
|
125
|
+
from arraybridge import stack_slices, unstack_slices
|
|
126
|
+
|
|
127
|
+
slices = [np.zeros((8, 8)), np.ones((8, 8))]
|
|
128
|
+
stack = stack_slices(slices, memory_type="numpy", gpu_id=0)
|
|
129
|
+
restored = unstack_slices(stack, memory_type="numpy", gpu_id=0)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`stack_slices` requires non-empty 2D inputs. `unstack_slices` requires a 3D
|
|
133
|
+
array. Both validate shape and use explicit target memory/device declarations.
|
|
134
|
+
|
|
135
|
+
## Installation
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
pip install arraybridge
|
|
139
|
+
pip install "arraybridge[torch]"
|
|
140
|
+
pip install "arraybridge[cupy]"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Documentation: <https://arraybridge.readthedocs.io>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# arraybridge
|
|
2
|
+
|
|
3
|
+
ArrayBridge provides explicit conversion and shared lifecycle utilities for
|
|
4
|
+
NumPy, CuPy, PyTorch, TensorFlow, JAX, and pyclesperanto arrays.
|
|
5
|
+
|
|
6
|
+
Core dependencies are NumPy and metaclass-registry. Other frameworks are
|
|
7
|
+
optional.
|
|
8
|
+
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
from arraybridge import convert_memory, detect_memory_type
|
|
15
|
+
|
|
16
|
+
value = np.arange(6).reshape(2, 3)
|
|
17
|
+
assert detect_memory_type(value) == "numpy"
|
|
18
|
+
|
|
19
|
+
copy = convert_memory(
|
|
20
|
+
value,
|
|
21
|
+
source_type="numpy",
|
|
22
|
+
target_type="numpy",
|
|
23
|
+
gpu_id=0,
|
|
24
|
+
)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`convert_memory` requires the declared source type, target type, and device id.
|
|
28
|
+
The source and target `MemoryType` declarations perform conversion directly.
|
|
29
|
+
The device id is required even for CPU conversions so call sites have one
|
|
30
|
+
stable signature. A GPU target must declare that identifier as available;
|
|
31
|
+
ArrayBridge does not silently place the value on the CPU.
|
|
32
|
+
|
|
33
|
+
## Declarative decorators
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from arraybridge import numpy
|
|
37
|
+
|
|
38
|
+
@numpy
|
|
39
|
+
def normalize(image):
|
|
40
|
+
return image / max(float(image.max()), 1.0)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The framework decorators attach `input_memory_type`, `output_memory_type`, and
|
|
44
|
+
`execution_memory_type` metadata, provide dtype/slice runtime parameters, and
|
|
45
|
+
add framework-specific stream/OOM handling where supported. They do **not**
|
|
46
|
+
convert inputs or outputs between frameworks and do not accept a `gpu_id`
|
|
47
|
+
argument. A host runtime must call `convert_memory` at the boundary it plans and
|
|
48
|
+
scope execution using the execution declaration.
|
|
49
|
+
|
|
50
|
+
## Stack utilities
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
import numpy as np
|
|
54
|
+
|
|
55
|
+
from arraybridge import stack_slices, unstack_slices
|
|
56
|
+
|
|
57
|
+
slices = [np.zeros((8, 8)), np.ones((8, 8))]
|
|
58
|
+
stack = stack_slices(slices, memory_type="numpy", gpu_id=0)
|
|
59
|
+
restored = unstack_slices(stack, memory_type="numpy", gpu_id=0)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`stack_slices` requires non-empty 2D inputs. `unstack_slices` requires a 3D
|
|
63
|
+
array. Both validate shape and use explicit target memory/device declarations.
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install arraybridge
|
|
69
|
+
pip install "arraybridge[torch]"
|
|
70
|
+
pip install "arraybridge[cupy]"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Documentation: <https://arraybridge.readthedocs.io>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Testing ArrayBridge
|
|
2
|
+
|
|
3
|
+
This is the practical test guide. The workflow files under `.github/workflows`
|
|
4
|
+
are the authority for the current CI matrix.
|
|
5
|
+
|
|
6
|
+
## Local core checks
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
python -m pip install -e ".[dev,docs]"
|
|
10
|
+
ruff check src tests
|
|
11
|
+
black --check src tests
|
|
12
|
+
mypy src --ignore-missing-imports
|
|
13
|
+
pytest
|
|
14
|
+
python -m sphinx -E -W --keep-going -b html docs/source /tmp/arraybridge-docs
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The default suite uses real optional frameworks when installed and otherwise
|
|
18
|
+
exercises declared unavailable paths and focused fakes. Markers such as
|
|
19
|
+
`torch`, `tensorflow`, `jax`, `cupy`, `pyclesperanto`, and `gpu` can select or
|
|
20
|
+
exclude framework-specific tests.
|
|
21
|
+
|
|
22
|
+
## Real GPU lattice check
|
|
23
|
+
|
|
24
|
+
On a GPU host, validate more than a single NumPy round trip:
|
|
25
|
+
|
|
26
|
+
- import all installed frameworks in one fresh process;
|
|
27
|
+
- enumerate framework-local devices through each `MemoryType`;
|
|
28
|
+
- convert a small exact array through every available source-target pair;
|
|
29
|
+
- stack and unstack one, two, and several planes in every framework;
|
|
30
|
+
- verify same-framework movement across multiple local devices when present;
|
|
31
|
+
- confirm absent frameworks are not imported by discovery or cleanup;
|
|
32
|
+
- exercise DLPack success and explicit CPU fallback paths;
|
|
33
|
+
- target OOM cleanup to the device that owned execution.
|
|
34
|
+
|
|
35
|
+
Use a fresh process and unset TensorFlow/JAX allocator variables when checking
|
|
36
|
+
that declaration-owned import defaults work. Framework warnings about shared
|
|
37
|
+
CUDA plugin registration should be recorded separately from value, device, or
|
|
38
|
+
shape failures.
|
|
39
|
+
|
|
40
|
+
## Interpreting CI
|
|
41
|
+
|
|
42
|
+
The main CI workflow runs the test suite across its declared Python and OS
|
|
43
|
+
matrix. The manual GPU-named workflow installs CPU-capable Torch and JAX on a
|
|
44
|
+
standard runner; it does not prove CUDA behavior. Real multi-framework and
|
|
45
|
+
multi-device results therefore remain a required release check on suitable
|
|
46
|
+
hardware.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# CI/CD documentation
|
|
2
|
+
|
|
3
|
+
The maintained CI/CD documentation is
|
|
4
|
+
[`source/ci-cd.rst`](source/ci-cd.rst). It deliberately links to the current
|
|
5
|
+
[GitHub Actions workflows](https://github.com/OpenHCSDev/arraybridge/actions)
|
|
6
|
+
instead of duplicating a version matrix or release procedure that can drift
|
|
7
|
+
from the workflow files.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# ArrayBridge documentation source
|
|
2
|
+
|
|
3
|
+
The active Sphinx source is this directory.
|
|
4
|
+
|
|
5
|
+
From the repository root:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
python -m pip install -e ".[docs]"
|
|
9
|
+
python -m sphinx -E -W --keep-going -b html docs/source docs/source/_build/html
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Narrative pages document public behavior and ownership. `api_reference.rst`
|
|
13
|
+
tracks the root export surface. Keep code examples valid under
|
|
14
|
+
`scripts/validate_docs.py` in the OpenHCS superproject and verify signatures
|
|
15
|
+
against `src/arraybridge/` when public APIs change.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Advanced extension topics
|
|
2
|
+
=========================
|
|
3
|
+
|
|
4
|
+
Framework behavior is carried by each ``MemoryType`` member. Add a framework by
|
|
5
|
+
extending that owning declaration:
|
|
6
|
+
|
|
7
|
+
1. add the ``MemoryType`` member;
|
|
8
|
+
2. provide its typed runtime and array-operation leaves;
|
|
9
|
+
3. define conversion, stack, scaling, and device behavior;
|
|
10
|
+
4. add cleanup and OOM behavior only when the framework supports them;
|
|
11
|
+
5. exercise detection and every supported conversion pair.
|
|
12
|
+
|
|
13
|
+
Do not add a parallel framework-name table in a consumer. Generic consumers use
|
|
14
|
+
``MemoryType`` directly. The converter registry and historical framework config
|
|
15
|
+
are generated projections, not authorities.
|
|
16
|
+
|
|
17
|
+
Version 0.3 keeps the private ``_FRAMEWORK_CONFIG`` and ``_FRAMEWORK_OPS`` names
|
|
18
|
+
only as read-only operation views. Their historical mapping shape is not a
|
|
19
|
+
compatibility contract. Migrate callers to ``MemoryType`` methods.
|
|
20
|
+
|
|
21
|
+
Conversion caching and batching belong to the caller because value lifetime and
|
|
22
|
+
semantic identity are application concerns. ArrayBridge functions remain
|
|
23
|
+
stateless at the conversion boundary except for declared thread-local GPU
|
|
24
|
+
context.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
API reference
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
Public imports
|
|
5
|
+
--------------
|
|
6
|
+
|
|
7
|
+
``MemoryType``, ``CPU_MEMORY_TYPES``, ``GPU_MEMORY_TYPES``, ``SUPPORTED_MEMORY_TYPES``
|
|
8
|
+
Framework declarations. Each member owns import identity, conversion,
|
|
9
|
+
stacking, dtype scaling, device discovery, scoped selection, movement,
|
|
10
|
+
DLPack import/export, cleanup, and pre-import coexistence defaults.
|
|
11
|
+
|
|
12
|
+
``detect_memory_type`` and ``convert_memory``
|
|
13
|
+
Detection and explicit conversion.
|
|
14
|
+
|
|
15
|
+
``memory_types``, ``numpy``, ``cupy``, ``torch``, ``tensorflow``, ``jax``, ``pyclesperanto``
|
|
16
|
+
Callable memory declarations and wrappers.
|
|
17
|
+
|
|
18
|
+
``DtypeConversion``
|
|
19
|
+
Output dtype policy values.
|
|
20
|
+
|
|
21
|
+
``stack_slices``, ``unstack_slices``, ``process_slices``
|
|
22
|
+
Validated plane/stack operations.
|
|
23
|
+
|
|
24
|
+
``cleanup_all_gpu_frameworks``
|
|
25
|
+
Installed-framework cache cleanup.
|
|
26
|
+
|
|
27
|
+
``MemoryConversionError``
|
|
28
|
+
Conversion failure boundary.
|
|
29
|
+
|
|
30
|
+
The canonical export list is ``arraybridge.__all__``. Names beginning with an
|
|
31
|
+
underscore are implementation surfaces even when temporarily re-exported for a
|
|
32
|
+
host migration.
|
|
33
|
+
|
|
34
|
+
Documented public surface
|
|
35
|
+
-------------------------
|
|
36
|
+
|
|
37
|
+
.. automodule:: arraybridge
|
|
38
|
+
:members:
|
|
39
|
+
:exclude-members: _FRAMEWORK_CONFIG, _FRAMEWORK_OPS, _ensure_module, _execute_with_oom_recovery, _get_device_id, _supports_dlpack
|
|
40
|
+
:member-order: bysource
|