Skip to content

ENH: Add comprehensive tests for itk.Image buffer protocol and lifetime#6027

Merged
hjmjohnson merged 1 commit intoInsightSoftwareConsortium:mainfrom
hjmjohnson:pep688-tests-only
Apr 11, 2026
Merged

ENH: Add comprehensive tests for itk.Image buffer protocol and lifetime#6027
hjmjohnson merged 1 commit intoInsightSoftwareConsortium:mainfrom
hjmjohnson:pep688-tests-only

Conversation

@hjmjohnson
Copy link
Copy Markdown
Member

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:

SKIP: PEP 688 __buffer__ tests (__buffer__ not available in this ITK version)
SKIP: np.asarray zero-copy tests (zero-copy np.asarray not available in this ITK version)

Test results (tests only, no production code changes)

Python itkImageTest itkImageLifetimeTest itkImageInteropTest
3.10.20 pass (3 skip) 12 pass, 0 fail, 13 skip pass
3.11.15 pass (3 skip) 12 pass, 0 fail, 13 skip pass
3.12.13 pass (3 skip) 12 pass, 0 fail, 13 skip pass
3.13.12 pass (3 skip) 12 pass, 0 fail, 13 skip pass
3.14.3 pass (3 skip) 12 pass, 0 fail, 13 skip pass

Zero failures on all Python versions.

Features detected as absent (correct — no production code in this PR):
__buffer__=False, copy_param=False, zero_copy=False

Feature detection

Tests probe the actual ITK build at runtime:

  • hasattr(image, '__buffer__') — PEP 688 buffer export
  • hasattr(image, '__array_interface__') — NumPy v3 array interface
  • image.__array__(copy=None) — NumPy 2.0 copy parameter
  • np.asarray mutation test — zero-copy behavior

Test coverage

itkImageTest.py: __buffer__, memoryview, np.asarray, __array__ copy protocol

itkImageLifetimeTest.py: del image safety 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

  • 0 failures on Python 3.10, 3.11, 3.12, 3.13, 3.14
  • Features correctly detected as absent without production code
  • Cherry-pick safe for ITKv5.4.5

🤖 Generated with Claude Code

@github-actions github-actions bot added type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Enhancement Improvement of existing methods or implementation area:Python wrapping Python bindings for a class type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Core Issues affecting the Core module labels Apr 9, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 9, 2026

Greptile Summary

This PR adds three Python test suites for itk.Image buffer protocol and lifetime safety (itkImageTest.py, itkImageLifetimeTest.py, itkImageInteropTest.py), with runtime feature detection that skips tests gracefully on older ITK builds. All previously flagged issues (unconditional __buffer__() calls, silent skip(), check() vs skip() for RSS unavailability) have been resolved in df27b60.

Confidence Score: 5/5

Safe to merge — test-only PR, zero production code changes, all prior review concerns addressed.

All remaining findings are P2. The macOS RSS measurement concern is a test-reliability issue on one platform that does not affect correctness on Linux CI. No failures reported across Python 3.10–3.14.

Modules/Core/Common/wrapping/test/itkImageLifetimeTest.py — get_rss_bytes() macOS path.

Important Files Changed

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]
Loading

Reviews (2): Last reviewed commit: "ENH: Add comprehensive tests for itk.Ima..." | Re-trigger Greptile

@hjmjohnson hjmjohnson force-pushed the pep688-tests-only branch 2 times, most recently from 5ddca1e to df27b60 Compare April 9, 2026 17:23
@hjmjohnson hjmjohnson marked this pull request as draft April 10, 2026 02:51
hjmjohnson added a commit to hjmjohnson/ITK that referenced this pull request Apr 10, 2026
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>
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>
@hjmjohnson hjmjohnson marked this pull request as ready for review April 10, 2026 20:55
@hjmjohnson hjmjohnson requested a review from thewtex April 10, 2026 20:55
@hjmjohnson
Copy link
Copy Markdown
Member Author

@thewtex This might be good to backport to 5.4. If you intend to backport #6026, then I would recommend backporting this as well.

@hjmjohnson hjmjohnson merged commit 86f75a9 into InsightSoftwareConsortium:main Apr 11, 2026
19 checks passed
thewtex added a commit that referenced this pull request Apr 13, 2026
…l-tests

ENH: Backport #6027 — comprehensive tests for itk.Image buffer protocol and lifetime
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Core Issues affecting the Core module area:Python wrapping Python bindings for a class type:Enhancement Improvement of existing methods or implementation type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant