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.
Files changed (132) hide show
  1. {arraybridge-0.2.10 → arraybridge-0.3.0}/.github/workflows/ci.yml +1 -1
  2. {arraybridge-0.2.10 → arraybridge-0.3.0}/.github/workflows/coverage-pages.yml +4 -15
  3. {arraybridge-0.2.10 → arraybridge-0.3.0}/.github/workflows/publish.yml +20 -4
  4. arraybridge-0.3.0/ADDING_NEW_FRAMEWORKS.md +63 -0
  5. {arraybridge-0.2.10 → arraybridge-0.3.0}/CONTRIBUTING.md +38 -25
  6. arraybridge-0.3.0/PKG-INFO +143 -0
  7. arraybridge-0.3.0/README.md +73 -0
  8. arraybridge-0.3.0/TESTING.md +46 -0
  9. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/CI_IMPROVEMENTS.md +0 -1
  10. arraybridge-0.3.0/docs/archive/README.md +5 -0
  11. arraybridge-0.3.0/docs/ci-cd.md +7 -0
  12. arraybridge-0.3.0/docs/source/README.md +15 -0
  13. arraybridge-0.3.0/docs/source/advanced_topics.rst +24 -0
  14. arraybridge-0.3.0/docs/source/api_reference.rst +40 -0
  15. arraybridge-0.3.0/docs/source/ci-cd.rst +25 -0
  16. {arraybridge-0.2.10 → arraybridge-0.3.0}/docs/source/conf.py +13 -5
  17. arraybridge-0.3.0/docs/source/contributing.rst +27 -0
  18. arraybridge-0.3.0/docs/source/converters.rst +47 -0
  19. arraybridge-0.3.0/docs/source/decorators.rst +59 -0
  20. arraybridge-0.3.0/docs/source/examples/basic_conversion.rst +16 -0
  21. arraybridge-0.3.0/docs/source/examples/decorators.rst +18 -0
  22. arraybridge-0.3.0/docs/source/examples/multi_framework.rst +18 -0
  23. arraybridge-0.3.0/docs/source/gpu_features.rst +34 -0
  24. arraybridge-0.3.0/docs/source/index.rst +33 -0
  25. arraybridge-0.3.0/docs/source/installation.rst +58 -0
  26. arraybridge-0.3.0/docs/source/quickstart.rst +54 -0
  27. arraybridge-0.3.0/docs/source/stack_utils.rst +25 -0
  28. arraybridge-0.3.0/docs/source/user_guide.rst +35 -0
  29. {arraybridge-0.2.10 → arraybridge-0.3.0}/pyproject.toml +17 -8
  30. arraybridge-0.3.0/scripts/release.py +117 -0
  31. arraybridge-0.3.0/scripts/update_version.py +79 -0
  32. arraybridge-0.3.0/scripts/verify_release_ready.py +307 -0
  33. {arraybridge-0.2.10 → arraybridge-0.3.0}/src/arraybridge/__init__.py +22 -19
  34. arraybridge-0.3.0/src/arraybridge/array_operations.py +396 -0
  35. arraybridge-0.3.0/src/arraybridge/array_payload.py +31 -0
  36. arraybridge-0.3.0/src/arraybridge/converters.py +85 -0
  37. {arraybridge-0.2.10 → arraybridge-0.3.0}/src/arraybridge/converters_registry.py +47 -69
  38. arraybridge-0.3.0/src/arraybridge/decorators.py +577 -0
  39. arraybridge-0.3.0/src/arraybridge/dtype_scaling.py +25 -0
  40. arraybridge-0.3.0/src/arraybridge/framework_config.py +26 -0
  41. arraybridge-0.3.0/src/arraybridge/framework_ops.py +7 -0
  42. arraybridge-0.3.0/src/arraybridge/gpu_cleanup.py +78 -0
  43. arraybridge-0.3.0/src/arraybridge/oom_recovery.py +90 -0
  44. {arraybridge-0.2.10 → arraybridge-0.3.0}/src/arraybridge/slice_processing.py +36 -5
  45. {arraybridge-0.2.10 → arraybridge-0.3.0}/src/arraybridge/stack_utils.py +23 -127
  46. arraybridge-0.3.0/src/arraybridge/types.py +984 -0
  47. arraybridge-0.3.0/src/arraybridge/utils.py +173 -0
  48. {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_converters.py +58 -0
  49. {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_converters_registry.py +37 -31
  50. arraybridge-0.3.0/tests/test_decorators.py +541 -0
  51. {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_dtype_scaling.py +85 -59
  52. arraybridge-0.3.0/tests/test_framework_config.py +29 -0
  53. arraybridge-0.3.0/tests/test_gpu_cleanup.py +156 -0
  54. {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_registry_integration.py +5 -22
  55. {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_slice_processing.py +29 -5
  56. arraybridge-0.3.0/tests/test_stack_utils.py +378 -0
  57. arraybridge-0.3.0/tests/test_types.py +446 -0
  58. arraybridge-0.3.0/tests/test_utils.py +248 -0
  59. arraybridge-0.2.10/.github/badges/coverage.svg +0 -1
  60. arraybridge-0.2.10/ADDING_NEW_FRAMEWORKS.md +0 -215
  61. arraybridge-0.2.10/PKG-INFO +0 -243
  62. arraybridge-0.2.10/README.md +0 -175
  63. arraybridge-0.2.10/SETUP_INSTRUCTIONS.md +0 -64
  64. arraybridge-0.2.10/TESTING.md +0 -175
  65. arraybridge-0.2.10/docs/ci-cd.md +0 -352
  66. arraybridge-0.2.10/docs/source/README.md +0 -145
  67. arraybridge-0.2.10/docs/source/advanced_topics.rst +0 -637
  68. arraybridge-0.2.10/docs/source/api/converters.rst +0 -46
  69. arraybridge-0.2.10/docs/source/api/decorators.rst +0 -72
  70. arraybridge-0.2.10/docs/source/api/exceptions.rst +0 -39
  71. arraybridge-0.2.10/docs/source/api/index.rst +0 -24
  72. arraybridge-0.2.10/docs/source/api/types.rst +0 -54
  73. arraybridge-0.2.10/docs/source/api/utils.rst +0 -70
  74. arraybridge-0.2.10/docs/source/api_reference.rst +0 -629
  75. arraybridge-0.2.10/docs/source/ci-cd.rst +0 -32
  76. arraybridge-0.2.10/docs/source/contributing.rst +0 -24
  77. arraybridge-0.2.10/docs/source/converters.rst +0 -474
  78. arraybridge-0.2.10/docs/source/decorators.rst +0 -638
  79. arraybridge-0.2.10/docs/source/examples/basic_conversion.rst +0 -98
  80. arraybridge-0.2.10/docs/source/examples/decorators.rst +0 -124
  81. arraybridge-0.2.10/docs/source/examples/multi_framework.rst +0 -132
  82. arraybridge-0.2.10/docs/source/gpu_features.rst +0 -624
  83. arraybridge-0.2.10/docs/source/index.rst +0 -96
  84. arraybridge-0.2.10/docs/source/installation.rst +0 -229
  85. arraybridge-0.2.10/docs/source/quickstart.rst +0 -281
  86. arraybridge-0.2.10/docs/source/stack_utils.rst +0 -603
  87. arraybridge-0.2.10/docs/source/user_guide.rst +0 -568
  88. arraybridge-0.2.10/scripts/release.py +0 -63
  89. arraybridge-0.2.10/scripts/update_and_release.py +0 -114
  90. arraybridge-0.2.10/scripts/update_version.py +0 -111
  91. arraybridge-0.2.10/scripts/verify_release_ready.py +0 -274
  92. arraybridge-0.2.10/src/arraybridge/converters.py +0 -71
  93. arraybridge-0.2.10/src/arraybridge/decorators.py +0 -387
  94. arraybridge-0.2.10/src/arraybridge/dtype_scaling.py +0 -179
  95. arraybridge-0.2.10/src/arraybridge/framework_config.py +0 -442
  96. arraybridge-0.2.10/src/arraybridge/framework_ops.py +0 -14
  97. arraybridge-0.2.10/src/arraybridge/gpu_cleanup.py +0 -141
  98. arraybridge-0.2.10/src/arraybridge/oom_recovery.py +0 -148
  99. arraybridge-0.2.10/src/arraybridge/types.py +0 -47
  100. arraybridge-0.2.10/src/arraybridge/utils.py +0 -366
  101. arraybridge-0.2.10/tests/test_decorators.py +0 -234
  102. arraybridge-0.2.10/tests/test_framework_config.py +0 -412
  103. arraybridge-0.2.10/tests/test_gpu_cleanup.py +0 -244
  104. arraybridge-0.2.10/tests/test_stack_utils.py +0 -169
  105. arraybridge-0.2.10/tests/test_types.py +0 -81
  106. arraybridge-0.2.10/tests/test_utils.py +0 -404
  107. {arraybridge-0.2.10 → arraybridge-0.3.0}/.github/workflows/gpu-tests.yml +0 -0
  108. {arraybridge-0.2.10 → arraybridge-0.3.0}/.gitignore +0 -0
  109. {arraybridge-0.2.10 → arraybridge-0.3.0}/.readthedocs.yml +0 -0
  110. {arraybridge-0.2.10 → arraybridge-0.3.0}/LICENSE +0 -0
  111. {arraybridge-0.2.10 → arraybridge-0.3.0}/docs/Makefile +0 -0
  112. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/CI_ARTIFACT_UPDATE.md +0 -0
  113. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/CI_CUPY_FIX.md +0 -0
  114. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/CONFLICT_VISUALIZATION.md +0 -0
  115. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/COVERAGE_AUDIT_PLAN.md +0 -0
  116. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/DEPLOYMENT_SUMMARY.md +0 -0
  117. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/GPU_TESTING_SETUP.md +0 -0
  118. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/MERGE_CONFLICT_RESOLUTION.md +0 -0
  119. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/MIGRATION_SUMMARY.md +0 -0
  120. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/QUICK_FIX_GUIDE.txt +0 -0
  121. {arraybridge-0.2.10 → arraybridge-0.3.0/docs/archive}/RESOLVED_FILES.md +0 -0
  122. {arraybridge-0.2.10 → arraybridge-0.3.0}/docs/source/.gitignore +0 -0
  123. {arraybridge-0.2.10 → arraybridge-0.3.0}/docs/source/Makefile +0 -0
  124. {arraybridge-0.2.10 → arraybridge-0.3.0}/docs/source/examples/index.rst +0 -0
  125. {arraybridge-0.2.10 → arraybridge-0.3.0}/paper.bib +0 -0
  126. {arraybridge-0.2.10 → arraybridge-0.3.0}/paper.md +0 -0
  127. {arraybridge-0.2.10 → arraybridge-0.3.0}/src/arraybridge/exceptions.py +0 -0
  128. {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/__init__.py +0 -0
  129. {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/conftest.py +0 -0
  130. {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_exceptions.py +0 -0
  131. {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_integration.py +0 -0
  132. {arraybridge-0.2.10 → arraybridge-0.3.0}/tests/test_oom_recovery.py +0 -0
@@ -155,4 +155,4 @@ jobs:
155
155
  - name: Run mypy (type checking)
156
156
  continue-on-error: true # Scientific code often has complex types
157
157
  run: |
158
- mypy src/ --ignore-missing-imports
158
+ mypy src/
@@ -6,7 +6,7 @@ on:
6
6
  workflow_dispatch:
7
7
 
8
8
  permissions:
9
- contents: write # Needed for badge commit
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
- mkdir -p .github/badges
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/trissim/arraybridge) project." >> site/README.md
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/trissim/arraybridge/settings/pages"
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 build
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/trissim/arraybridge/issues)
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/trissim/arraybridge.git
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
- Edit `pyproject.toml`:
335
+ Update all three validated version projections with the side-effect-free helper:
338
336
 
339
- ```toml
340
- [project]
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. Create Tag
348
+ ### 3. Validate, Commit, and Push
349
349
 
350
350
  ```bash
351
- # Ensure you're on main branch
352
- git checkout main
353
- git pull upstream main
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
- # Create and push tag
356
- git tag -a v0.2.0 -m "Release version 0.2.0"
357
- git push upstream v0.2.0
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
- ### 4. Automated Publishing
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. Build the package
364
- 2. Create GitHub release
365
- 3. Publish to PyPI
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. Update `MemoryType` enum in `types.py`
397
- 2. Add framework config in `framework_config.py`
398
- 3. Implement converter in `conversion_helpers.py`
399
- 4. Add decorator support in `decorators.py`
400
- 5. Update documentation
401
- 6. Add tests with availability checks
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.
@@ -190,4 +190,3 @@ If issues arise, revert to previous CI by:
190
190
  ## Questions?
191
191
 
192
192
  See `TESTING.md` for detailed testing documentation.
193
-
@@ -0,0 +1,5 @@
1
+ # Archived ArrayBridge notes
2
+
3
+ These CI incident reports, migration summaries, conflict guides, and dated
4
+ coverage plans are superseded history. Use `README.md`, `CONTRIBUTING.md`,
5
+ `TESTING.md`, and the active Sphinx site under `docs/source/`.
@@ -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