Skip to content

ENH: Backport #6026 — PEP 688 buffer protocol and np.asarray() lifetime safety#6042

Open
hjmjohnson wants to merge 1 commit intoInsightSoftwareConsortium:release-5.4from
hjmjohnson:backport-6026-pep688-buffer-protocol
Open

ENH: Backport #6026 — PEP 688 buffer protocol and np.asarray() lifetime safety#6042
hjmjohnson wants to merge 1 commit intoInsightSoftwareConsortium:release-5.4from
hjmjohnson:backport-6026-pep688-buffer-protocol

Conversation

@hjmjohnson
Copy link
Copy Markdown
Member

@hjmjohnson hjmjohnson commented Apr 11, 2026

Summary

Backport of #6026 (merged as 45a50960da on main) to release-5.4.

Cherry-picks the PEP 688 buffer protocol implementation and np.asarray() zero-copy lifetime safety fix onto the v5.4.x branch so that downstream consumers pinning to ITK 5.4 get the correct del image; arr[1,1,1] behavior without needing to wait for the ITK 6.x release.

What's in the cherry-pick

  • Modules/Bridge/NumPy/wrapping/PyBuffer.i.init — adds _BUFFER_FORMAT_MAP, _NUMPY_PIXELID_MAP, and the helper accessors; removes the long-double (LD) mapping that caused silent data corruption.
  • Wrapping/Generators/Python/PyBase/pyBase.i — adds __buffer__() (PEP 688), __array_interface__ property for NumPy v3, and simplifies __array__() to always return a zero-copy view via NDArrayITKBase (which pins the source image to prevent GC while any derived memoryview/array exists). Supports NumPy 2.0's copy= parameter.

Cherry-picked cleanly (one auto-merge in pyBase.i, no hand resolution needed).

Test plan

Dependency note

The companion follow-up backport of #6027 (comprehensive tests for this feature) is stacked on top of this branch. It is intentionally a separate PR so the fix can be reviewed and merged independently. Please merge this PR before the #6027 backport.

🤖 Generated with Claude Code

Add zero-copy data export to all wrapped itk.Image types via three
protocols, ensuring the exported array remains valid even after
the source image is deleted:

  image = itk.imread("brain.nii.gz")
  arr = np.asarray(image)
  del image
  print(arr[1,1,1])  # safe -- no crash

Protocol dispatch by Python version:
  3.12+:   np.asarray -> __buffer__ (PEP 688, zero-copy, memoryview
           pins self via NDArrayITKBase intermediary)
  3.10-11: np.asarray -> __array_interface__ (zero-copy, NumPy sets
           arr.base = self, preventing image GC)

All versions: image.__array__() returns NDArrayITKBase with
  .itk_base = image for explicit __array__ calls.

Changes to pyBase.i:
  - Add __buffer__() implementing PEP 688 buffer export with shaped
    memoryview. Uses NDArrayITKBase as intermediary to hold a Python
    reference to the image, preventing GC while any derived
    memoryview/array exists. flags parameter accepted for PEP 688
    compliance but not inspected (ITK buffers always writable).
  - Add __array_interface__ property returning NumPy v3 array
    interface dict. NumPy sets arr.base = self when creating arrays
    from this interface, providing correct lifetime on 3.10-3.11.
  - Simplify __array__() to always return zero-copy view via
    array_view_from_image(). Supports NumPy 2.0 copy= parameter.
    copy=True returns a plain ndarray so image can be GCd.

Changes to PyBuffer.i.init:
  - Add _BUFFER_FORMAT_MAP constant (before function definition)
  - Add _get_buffer_formatstring() with descriptive KeyError
  - Add _NUMPY_PIXELID_MAP and _get_numpy_pixelid()
  - Remove LD (long double) mapping (silent corruption)

Tested: Python 3.10-3.14, all pass (0 failures).

Supersedes InsightSoftwareConsortium#6020, InsightSoftwareConsortium#6018, InsightSoftwareConsortium#5673, InsightSoftwareConsortium#5665.
Addresses @thewtex (del image crash), @blowekamp (ref pinning).

Co-Authored-By: Hans J. Johnson <hans-johnson@uiowa.edu>
(cherry picked from commit 45a5096)
@github-actions github-actions bot added type:Enhancement Improvement of existing methods or implementation area:Python wrapping Python bindings for a class area:Bridge Issues affecting the Bridge module labels Apr 11, 2026
@hjmjohnson hjmjohnson requested a review from thewtex April 11, 2026 19:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Bridge Issues affecting the Bridge module area:Python wrapping Python bindings for a class type:Enhancement Improvement of existing methods or implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant