ENH: Add comprehensive tests for itk.Image buffer protocol and lifetime#6027
Conversation
|
| Filename | Overview |
|---|---|
| Modules/Core/Common/wrapping/test/CMakeLists.txt | Registers two new Python tests (itkImageInteropPythonTest, itkImageLifetimePythonTest); straightforward addition, no issues. |
| Modules/Core/Common/wrapping/test/itkImageTest.py | Updated buffer-protocol test with runtime feature detection (HAS_BUFFER, HAS_ARRAY_COPY_PARAM, HAS_ZEROCOPY); all paths properly guarded and skipped when features absent; no issues found. |
| Modules/Core/Common/wrapping/test/itkImageInteropTest.py | New NumPy/PyTorch/Dask interop test with feature-guarded __buffer__ calls (fixed from earlier review), printing skip(), and sys.exit(1) on failure; no remaining issues. |
| Modules/Core/Common/wrapping/test/itkImageLifetimeTest.py | New lifetime/GC/leak test; well-structured with explicit del + gc.collect() per section. get_rss_bytes() on macOS uses ru_maxrss (peak, not current RSS), which can give false-negative leak results when prior test phases already pushed the process peak above the leak-test threshold. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Script start: feature detection] --> B{HAS_BUFFER?}
A --> C{HAS_ZEROCOPY?}
A --> D{HAS_ARRAY_COPY_PARAM?}
B -- yes --> E[Run __buffer__ / memoryview tests]
B -- no --> F[skip with message]
C -- yes --> G[Run np.asarray zero-copy / lifetime tests]
C -- no --> H[skip with message]
D -- yes --> I[Run __array__ copy= protocol tests]
D -- no --> J[skip with message]
E & G & I --> K[Lifetime / GC / refcount / circular-ref checks]
K --> L[Section 10: RSS growth leak detection]
L --> M{get_rss_bytes available?}
M -- Linux /proc --> N[Accurate current RSS delta]
M -- macOS ru_maxrss --> O[Peak RSS delta — may miss small leaks]
M -- unavailable --> P[skip RSS tests]
N & O & P --> Q{failed > 0?}
Q -- yes --> R[sys.exit 1]
Q -- no --> S[All tests passed]
Reviews (2): Last reviewed commit: "ENH: Add comprehensive tests for itk.Ima..." | Re-trigger Greptile
5ddca1e to
df27b60
Compare
Add runtime feature detection to itkImageInteropTest.py so the test passes on builds where the NumPy 2.x __array__(copy=) protocol and zero-copy np.asarray support are not yet available. HAS_ARRAY_COPY_PARAM : __array__ accepts the 'copy' keyword HAS_ZEROCOPY : np.asarray returns a view sharing memory Zero-copy assertions and __array__(copy=...) protocol checks are now gated on these flags and report SKIP when the feature is missing. This keeps PR InsightSoftwareConsortium#6027 (test additions) decoupled from PR InsightSoftwareConsortium#6026, which will land the actual __array__/__buffer__ behavior changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
e07b4a3 to
87d7e27
Compare
Add three test suites with automatic feature detection so they can be cherry-picked into ITKv5.4.5 — tests for unavailable features are skipped with descriptive messages rather than failing. Feature detection at runtime: - hasattr(image, '__buffer__'): PEP 688 (ITK 6.x) - hasattr(image, '__array_interface__'): NumPy v3 interface (ITK 6.x) - image.__array__(copy=None): NumPy 2.0 copy param (ITK 6.x) - np.asarray zero-copy mutation test: zero-copy support (ITK 6.x) itkImageTest.py (25-27 assertions depending on Python version): - Basic __array__() and np.asarray() [all ITK versions] - __buffer__() PEP 688: 2D/3D, UC/SS/F [skip if unavailable] - memoryview(image) auto-dispatch [skip if Python < 3.12] - np.asarray zero-copy mutation [skip if unavailable] - __array__(copy=None/True/False) [skip if unavailable] itkImageLifetimeTest.py (54-56 assertions): - Deep copy: np.array(copy=True), array_from_image [all versions] - __array__() zero-copy lifetime [skip if unavailable] - np.asarray del-image safety [skip if unavailable] - __buffer__/memoryview lifetime [skip if unavailable] - Chained refs: slice, transpose, ravel [skip if unavailable] - Filter pipeline output lifetime [skip if unavailable] - Weak reference GC verification [skip if unavailable] - Reference count verification [skip if unavailable] - Circular reference detection [all versions] - RSS memory growth (200x cycles) [all versions] itkImageInteropTest.py (37 assertions when fully supported): - NumPy: CT/MRI/DWI clinical sizes [all versions] - Zero-copy assertions gated on HAS_ZEROCOPY [skip if unavailable] - __array__(copy=...) protocol gated on HAS_ARRAY_COPY_PARAM - PyTorch: 14 tests [optional, skip if not installed] - Dask: 9 tests [optional, skip if not installed] Co-Authored-By: Hans J. Johnson <hans-johnson@uiowa.edu> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
87d7e27 to
86f75a9
Compare
…l-tests ENH: Backport #6027 — comprehensive tests for itk.Image buffer protocol and lifetime
Summary
Add three test suites for itk.Image data export with automatic feature
detection, allowing cherry-pick into ITKv5.4.5 and forward compatibility
with PEP 688 buffer protocol support.
Tests for unavailable features are skipped (not failed) with
descriptive messages:
Test results (tests only, no production code changes)
Zero failures on all Python versions.
Features detected as absent (correct — no production code in this PR):
__buffer__=False, copy_param=False, zero_copy=FalseFeature detection
Tests probe the actual ITK build at runtime:
hasattr(image, '__buffer__')— PEP 688 buffer exporthasattr(image, '__array_interface__')— NumPy v3 array interfaceimage.__array__(copy=None)— NumPy 2.0 copy parameternp.asarraymutation test — zero-copy behaviorTest coverage
itkImageTest.py:
__buffer__,memoryview,np.asarray,__array__copy protocolitkImageLifetimeTest.py:
del imagesafety on every export path, weak-ref GC,refcount verification, circular reference detection, RSS memory growth (200x cycles).
All tests run inside a function scope with explicit
del+gc.collect().itkImageInteropTest.py: NumPy (CT/MRI/DWI clinical sizes), PyTorch (optional),
Dask (optional)
Motivation
Prepares the test infrastructure for PR #6026 (PEP 688 buffer protocol).
When #6026's production code is added, all 13 skipped tests will run and
pass (verified: 56 pass, 0 fail, 0 skip on Python 3.12+).
Test plan
🤖 Generated with Claude Code