From 7bce3c3e5c85091d35ccdce84a2428f9d3d6f642 Mon Sep 17 00:00:00 2001 From: Jonas Teuwen Date: Thu, 6 Aug 2026 17:51:57 +0200 Subject: [PATCH 01/11] ci: skip musllinux and drop in-build wheel tests in release workflow PyTorch ships no musllinux wheels, so a musllinux `direct` wheel is not installable; skip it. Also drop cibuildwheel's in-build test, which would `pip install` the wheel with its full runtime stack (torch + CUDA wheels) just to run numpy-only native smoke tests. The dedicated smoke-wheels job already exercises the abi3 wheels with --no-deps on 3.12 and 3.13. Co-authored-by: Cursor --- .github/workflows/release.yml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 573424f7..a71854da 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,12 +58,10 @@ jobs: - platform: macos_arm64 builder: macos-14 cibw_archs: arm64 - # x86_64 is cross-compiled on the arm64 macOS runner; its tests cannot - # run here, so they are skipped and covered by smoke-wheels (Rosetta). + # x86_64 is cross-compiled on the arm64 macOS runner. - platform: macos_x86_64 builder: macos-14 cibw_archs: x86_64 - test_skip: "*" - platform: windows_x86_64 builder: windows-2022 cibw_archs: AMD64 @@ -91,6 +89,9 @@ jobs: env: # A single abi3 wheel per platform, built with CPython 3.12. CIBW_BUILD: "cp312-*" + # Skip musllinux: PyTorch (a hard runtime dependency) publishes no + # musllinux wheels, so a musllinux `direct` wheel is not installable. + CIBW_SKIP: "*-musllinux*" CIBW_ARCHS: ${{ matrix.cibw_archs }} CIBW_BUILD_VERBOSITY: "1" # C++20 (std::numbers, std::span) needs a modern toolchain; the @@ -101,15 +102,11 @@ jobs: # Meson would otherwise auto-select it over MSVC. `--vsenv` activates # the Visual Studio environment. CIBW_CONFIG_SETTINGS_WINDOWS: "setup-args=--vsenv" - # Run the native extension smoke tests against the freshly built - # wheel. cibuildwheel runs this from a temporary directory, and - # `--import-mode=importlib` keeps pytest from putting the source tree - # (which has no compiled .so) on sys.path, so `import direct` resolves - # to the installed wheel. - CIBW_TEST_REQUIRES: "pytest numpy" - CIBW_TEST_COMMAND: >- - python -m pytest --import-mode=importlib {project}/tests/tests_common/_gaussian_native_test.py {project}/tests/tests_common/_poisson_native_test.py {project}/tests/tests_ssl/_gaussian_fill_native_test.py - CIBW_TEST_SKIP: ${{ matrix.test_skip }} + # No in-build test here: cibuildwheel would `pip install` the wheel + # with its full runtime stack (torch + the CUDA wheels), which is slow + # and unavailable on some targets. The dedicated `smoke-wheels` job + # tests the native extensions against the built wheel with --no-deps + # on both 3.12 and 3.13 instead. - name: Upload wheel if: steps.gate.outputs.run == 'true' uses: actions/upload-artifact@v4 From 4c57a3a278f5b408d09cf08b25b56b2a45ad4e0d Mon Sep 17 00:00:00 2001 From: Jonas Teuwen Date: Fri, 7 Aug 2026 09:12:46 +0200 Subject: [PATCH 02/11] ci: build per-version wheels on Windows to fix abi3 DLL load failure The nanobind WrapDB subproject links the version-specific python3XY import library, so the Windows "abi3" wheel built on 3.12 imports python312.dll and fails to load on 3.13+ (DLL load failed). Build per-version wheels on Windows with -Dpython.allow_limited_api=false; keep a single abi3 wheel on Linux/macOS. --- .github/workflows/release.yml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a71854da..187ed85a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -49,22 +49,32 @@ jobs: fail-fast: false matrix: include: + # Linux/macOS ship a single abi3 wheel (cp312-*) usable on 3.12+. - platform: linux_x86_64 builder: ubuntu-24.04 cibw_archs: x86_64 + cibw_build: "cp312-*" - platform: linux_aarch64 builder: ubuntu-24.04-arm cibw_archs: aarch64 + cibw_build: "cp312-*" - platform: macos_arm64 builder: macos-14 cibw_archs: arm64 + cibw_build: "cp312-*" # x86_64 is cross-compiled on the arm64 macOS runner. - platform: macos_x86_64 builder: macos-14 cibw_archs: x86_64 + cibw_build: "cp312-*" + # Windows cannot use abi3: the nanobind WrapDB subproject links the + # version-specific python3XY import library, so an "abi3" wheel built on + # 3.12 actually imports python312.dll and fails to load on 3.13+. Build + # per-version wheels instead (limited API disabled below). - platform: windows_x86_64 builder: windows-2022 cibw_archs: AMD64 + cibw_build: "cp312-* cp313-*" steps: - name: Checkout uses: actions/checkout@v5 @@ -87,8 +97,8 @@ jobs: package-dir: . output-dir: artifacts/wheels env: - # A single abi3 wheel per platform, built with CPython 3.12. - CIBW_BUILD: "cp312-*" + # abi3 (cp312-*) on Linux/macOS; per-version on Windows (see matrix). + CIBW_BUILD: ${{ matrix.cibw_build }} # Skip musllinux: PyTorch (a hard runtime dependency) publishes no # musllinux wheels, so a musllinux `direct` wheel is not installable. CIBW_SKIP: "*-musllinux*" @@ -100,8 +110,10 @@ jobs: CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28 # Force MSVC on Windows: the runner ships MinGW GCC on PATH, and # Meson would otherwise auto-select it over MSVC. `--vsenv` activates - # the Visual Studio environment. - CIBW_CONFIG_SETTINGS_WINDOWS: "setup-args=--vsenv" + # the Visual Studio environment. `-Dpython.allow_limited_api=false` + # disables the limited API (overriding pyproject's limited-api=true) so + # each interpreter gets a wheel linked against its own pythonXY.dll. + CIBW_CONFIG_SETTINGS_WINDOWS: "setup-args=--vsenv setup-args=-Dpython.allow_limited_api=false" # No in-build test here: cibuildwheel would `pip install` the wheel # with its full runtime stack (torch + the CUDA wheels), which is slow # and unavailable on some targets. The dedicated `smoke-wheels` job @@ -146,7 +158,8 @@ jobs: strategy: fail-fast: false matrix: - # Install the cp312-abi3 wheel on 3.12 and 3.13 to prove the stable ABI. + # Install on 3.12 and 3.13: proves the abi3 wheel on Linux/macOS and the + # per-version wheels on Windows both load on each interpreter. python: ["3.12", "3.13"] target: - platform: linux_x86_64 From 9f920a928cda4e1f7827a9f059338d772bc2868a Mon Sep 17 00:00:00 2001 From: Jonas Teuwen Date: Fri, 7 Aug 2026 09:23:36 +0200 Subject: [PATCH 03/11] docs: convert README raw:: html to native RST for PyPI PyPI's description renderer disables the reStructuredText `raw` directive, so `twine check` (verify-metadata) rejected every artifact during publishing. Replace the raw HTML logo, badge bar, nav links, and figure with native RST (image/figure directives and badge substitutions) so the long_description renders on PyPI while still looking right on GitHub. Co-authored-by: Cursor --- README.rst | 74 +++++++++++++++++++++++------------------------------- 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/README.rst b/README.rst index c28e86ea..47615e79 100644 --- a/README.rst +++ b/README.rst @@ -1,40 +1,18 @@ -.. raw:: html +.. image:: https://github.com/NKI-AI/direct/assets/71031687/14ce8234-7ef1-4e32-84c6-966dc393e7ca + :alt: DIRECT + :width: 400px + :align: center -
- -
-
DIRECT: Deep Image REConstruction Toolkit
+========================================= +DIRECT: Deep Image REConstruction Toolkit +========================================= -
- -.. raw:: html - -
- -
- - - JOSS - - Tests - - Ruff - - Codacy - - Codecov - -
- -

- Installation • - Quick Start • - Documentation • - Model Zoo
-

- -
+|JOSS| |Tests| |Ruff| |Codacy| |Codecov| +`Installation `_ • +`Quick Start `_ • +`Documentation `_ • +`Model Zoo `_ ``DIRECT`` is a Python, end-to-end pipeline for solving Inverse Problems emerging in Imaging Processing. It is built with PyTorch and stores state-of-the-art Deep Learning imaging inverse problem solvers such as denoising, dealiasing and reconstruction. @@ -42,15 +20,11 @@ By defining a base forward linear or non-linear operator, ``DIRECT`` can be used ``DIRECT`` stores inverse problem solvers such as the vSHARP, Learned Primal Dual algorithm, Recurrent Inference Machine and Recurrent Variational Network, which were part of the winning solutions in Facebook & NYUs FastMRI challenge in 2019, the Calgary-Campinas MRI reconstruction challenge at MIDL 2020 and the CMRxRecon challenge 2023. For a full list of the baselines currently implemented in DIRECT see `here <#baselines-and-trained-models>`_. -.. raw:: html - -
- -
Zero-filled reconstruction, Compressed-Sensing (CS) reconstruction using the BART toolbox, Reconstruction using a RIM model trained with DIRECT
-
- - +.. figure:: https://raw.githubusercontent.com/NKI-AI/direct/main/.github/direct.png + :alt: DIRECT reconstruction examples + :align: center + Zero-filled reconstruction, Compressed-Sensing (CS) reconstruction using the BART toolbox, Reconstruction using a RIM model trained with DIRECT Quick install ------------- @@ -101,3 +75,19 @@ If you use DIRECT in your own research, or want to refer to baseline results pub title = {DIRECT: Deep Image REConstruction Toolkit}, journal = {Journal of Open Source Software} } + +.. |JOSS| image:: https://joss.theoj.org/papers/10.21105/joss.04278/status.svg + :target: https://doi.org/10.21105/joss.04278 + :alt: JOSS +.. |Tests| image:: https://github.com/NKI-AI/direct/actions/workflows/tests.yml/badge.svg + :target: https://github.com/NKI-AI/direct/actions/workflows/tests.yml + :alt: Tests +.. |Ruff| image:: https://github.com/NKI-AI/direct/actions/workflows/ruff.yml/badge.svg + :target: https://github.com/NKI-AI/direct/actions/workflows/ruff.yml + :alt: Ruff +.. |Codacy| image:: https://api.codacy.com/project/badge/Grade/1c55d497dead4df69d6f256da51c98b7 + :target: https://app.codacy.com/gh/NKI-AI/direct + :alt: Codacy +.. |Codecov| image:: https://codecov.io/gh/NKI-AI/direct/branch/main/graph/badge.svg?token=STYAUFCKJY + :target: https://codecov.io/gh/NKI-AI/direct + :alt: Codecov From b30b96eb64f7b6bd7cf92c6d0c974b09caa93cb7 Mon Sep 17 00:00:00 2001 From: Jonas Teuwen Date: Fri, 7 Aug 2026 09:41:43 +0200 Subject: [PATCH 04/11] build: rename PyPI distribution from direct to direct-recon The `direct` name on PyPI is taken, so publish under `direct-recon`. Only the distribution name changes; the import package stays `direct` (install_subdir), so `pip install direct-recon` then `import direct`. Update uv's no-build-isolation-package to the new distribution name, the wheel smoke-install name, the metadata-version test lookup, the PyPI install docs, and uv.lock. Co-authored-by: Cursor --- .github/workflows/release.yml | 2 +- installation.rst | 2 +- pyproject.toml | 15 +++++++++------ tests/version_test.py | 3 ++- uv.lock | 18 +++++++++--------- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 187ed85a..0d20400d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -223,7 +223,7 @@ jobs: py="$repo/.venv/bin/python" fi uv pip install --python "$py" pytest numpy - uv pip install --python "$py" --no-deps --no-index --find-links dist direct + uv pip install --python "$py" --no-deps --no-index --find-links dist direct-recon # Run from a scratch dir (not the repo root) with importlib import mode # so the uncompiled source tree never shadows the installed wheel. cd "$RUNNER_TEMP" diff --git a/installation.rst b/installation.rst index e47aed8b..41617321 100644 --- a/installation.rst +++ b/installation.rst @@ -110,7 +110,7 @@ Install using ``conda`` (alternative) .. code-block:: - pip3 install direct + pip3 install direct-recon To build from a checkout instead, clone the repository, navigate to ``direct/`` and run diff --git a/pyproject.toml b/pyproject.toml index 5671c46e..c67133df 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,9 @@ requires = ["meson-python>=0.18", "meson>=1.5"] build-backend = "mesonpy" [project] -name = "direct" +# Distribution name on PyPI. The import package is still `direct` (see +# meson.build / install_subdir), so `pip install direct-recon` then `import direct`. +name = "direct-recon" description = "DIRECT - Deep Image REConsTruction - is a deep learning framework for MRI reconstruction." readme = "README.rst" license = { text = "Apache-2.0" } @@ -72,11 +74,12 @@ docs = [ [tool.uv] default-groups = ["dev", "build"] -# Build `direct` against the already-synced `build` group instead of an isolated -# build environment. Without this, meson-python's editable install records the -# absolute path of the isolated build env's `ninja`, which uv later deletes, -# breaking `import direct` on the next run. -no-build-isolation-package = ["direct"] +# Build `direct-recon` against the already-synced `build` group instead of an +# isolated build environment. Without this, meson-python's editable install +# records the absolute path of the isolated build env's `ninja`, which uv later +# deletes, breaking `import direct` on the next run. Matches the distribution +# name in `[project] name`, not the import package. +no-build-isolation-package = ["direct-recon"] [tool.pytest.ini_options] # Keep collection inside the project's own suite; never descend into the diff --git a/tests/version_test.py b/tests/version_test.py index 0c944dfb..fdc35bdd 100644 --- a/tests/version_test.py +++ b/tests/version_test.py @@ -50,7 +50,8 @@ def _pyproject_version() -> str: def test_dunder_version_matches_installed_metadata() -> None: - assert direct.__version__ == importlib.metadata.version("direct") + # Distribution name (PyPI) is `direct-recon`; the import package is `direct`. + assert direct.__version__ == importlib.metadata.version("direct-recon") def test_pyproject_version_matches_dunder_version() -> None: diff --git a/uv.lock b/uv.lock index 9e1c378b..4258d491 100644 --- a/uv.lock +++ b/uv.lock @@ -197,7 +197,7 @@ name = "cuda-bindings" version = "13.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cuda-pathfinder" }, + { name = "cuda-pathfinder", marker = "sys_platform != 'ios'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/52/c8/b2589d68acf7e3d63e2be330b84bc25712e97ed799affbca7edd7eae25d6/cuda_bindings-13.2.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e865447abfb83d6a98ad5130ed3c70b1fc295ae3eeee39fd07b4ddb0671b6788", size = 5722404, upload-time = "2026-03-11T00:12:44.041Z" }, @@ -259,7 +259,7 @@ nvtx = [ ] [[package]] -name = "direct" +name = "direct-recon" version = "2.1.0" source = { editable = "." } dependencies = [ @@ -853,7 +853,7 @@ name = "nvidia-cublas" version = "13.1.1.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cuda-nvrtc" }, + { name = "nvidia-cuda-nvrtc", marker = "sys_platform != 'ios'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/a7/a1/0bd24ee8c8d03adac032fd2909426a00c88f8c57961b1277ded97f91119f/nvidia_cublas-13.1.1.3-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:b7a210458267ac818974c53038fbec2e969d5c99f305ab15c72522fa9f001dd5", size = 542848918, upload-time = "2026-04-08T18:46:22.985Z" }, @@ -892,7 +892,7 @@ name = "nvidia-cudnn-cu13" version = "9.20.0.48" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cublas" }, + { name = "nvidia-cublas", marker = "sys_platform != 'ios'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/56/c5/83384d846b2fd17c44bd499b36c75a45ed4f095fbbb2252294e89cea5c5c/nvidia_cudnn_cu13-9.20.0.48-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:e31454ae00094b0c55319d9d15b6fa2fc50a9e1c0f5c8c80fb75258234e731e1", size = 444574296, upload-time = "2026-03-09T19:28:27.751Z" }, @@ -904,7 +904,7 @@ name = "nvidia-cufft" version = "12.0.0.61" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-nvjitlink" }, + { name = "nvidia-nvjitlink", marker = "sys_platform != 'ios'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/8b/ae/f417a75c0259e85c1d2f83ca4e960289a5f814ed0cea74d18c353d3e989d/nvidia_cufft-12.0.0.61-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2708c852ef8cd89d1d2068bdbece0aa188813a0c934db3779b9b1faa8442e5f5", size = 214053554, upload-time = "2025-09-04T08:31:38.196Z" }, @@ -934,9 +934,9 @@ name = "nvidia-cusolver" version = "12.0.4.66" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-cublas" }, - { name = "nvidia-cusparse" }, - { name = "nvidia-nvjitlink" }, + { name = "nvidia-cublas", marker = "sys_platform != 'ios'" }, + { name = "nvidia-cusparse", marker = "sys_platform != 'ios'" }, + { name = "nvidia-nvjitlink", marker = "sys_platform != 'ios'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/c8/c3/b30c9e935fc01e3da443ec0116ed1b2a009bb867f5324d3f2d7e533e776b/nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:02c2457eaa9e39de20f880f4bd8820e6a1cfb9f9a34f820eb12a155aa5bc92d2", size = 223467760, upload-time = "2025-09-04T08:33:04.222Z" }, @@ -948,7 +948,7 @@ name = "nvidia-cusparse" version = "12.6.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "nvidia-nvjitlink" }, + { name = "nvidia-nvjitlink", marker = "sys_platform != 'ios'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/f8/94/5c26f33738ae35276672f12615a64bd008ed5be6d1ebcb23579285d960a9/nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:80bcc4662f23f1054ee334a15c72b8940402975e0eab63178fc7e670aa59472c", size = 162155568, upload-time = "2025-09-04T08:33:42.864Z" }, From 5d60e03a1b65db583a84ef118fd17d8d82e04e1e Mon Sep 17 00:00:00 2001 From: Jonas Teuwen Date: Fri, 7 Aug 2026 09:44:28 +0200 Subject: [PATCH 05/11] docs: add dedicated Install from PyPI section Surface `pip install direct-recon` as a first-class installation path (right after the recommended uv flow) instead of burying it inside the conda steps, clarifying that the import package is still `direct` and covering the editable install variant. Co-authored-by: Cursor --- installation.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/installation.rst b/installation.rst index 41617321..9839d7e8 100644 --- a/installation.rst +++ b/installation.rst @@ -60,6 +60,34 @@ directly from ``pyproject.toml`` and the committed ``uv.lock``. uv run direct --help uv run pytest +Install from PyPI (``pip``) +--------------------------- + +``DIRECT`` is published to PyPI as ``direct-recon`` (the import package is still +``direct``). On the supported platforms this fetches a prebuilt ``abi3`` wheel, +so nothing is compiled: + +.. code-block:: + + pip install direct-recon + +.. code-block:: python + + import direct + +If no wheel is available for your platform, ``pip`` builds the C++ extensions +from the source distribution via ``meson-python`` + ``nanobind`` in an isolated +build environment; only a working C++20 compiler is required. The conda section +below shows a step-by-step build, including installing PyTorch with CUDA first. + +For an editable/development install, install the build tooling first and disable +build isolation so the on-import rebuild keeps working: + +.. code-block:: + + pip install meson-python meson ninja + pip install --no-build-isolation -e . + Install using Docker -------------------- From a11edef73aeaf2dde88b043e134d1122bc29a943 Mon Sep 17 00:00:00 2001 From: Jonas Teuwen Date: Fri, 7 Aug 2026 09:47:33 +0200 Subject: [PATCH 06/11] docs: add PyPI install and badge for direct-recon to README Add `pip install direct-recon` as the primary install (uv shown for development) and a PyPI version badge, noting the import package stays `direct`. Co-authored-by: Cursor --- README.rst | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 47615e79..7171d891 100644 --- a/README.rst +++ b/README.rst @@ -7,7 +7,7 @@ DIRECT: Deep Image REConstruction Toolkit ========================================= -|JOSS| |Tests| |Ruff| |Codacy| |Codecov| +|PyPI| |JOSS| |Tests| |Ruff| |Codacy| |Codecov| `Installation `_ • `Quick Start `_ • @@ -29,7 +29,14 @@ For a full list of the baselines currently implemented in DIRECT see `here <#bas Quick install ------------- -The recommended way to install ``DIRECT`` is with `uv `_: +``DIRECT`` is published to PyPI as ``direct-recon`` (the import package is still +``direct``): + +.. code-block:: bash + + pip install direct-recon + +For development, the recommended way is with `uv `_: .. code-block:: bash @@ -76,6 +83,9 @@ If you use DIRECT in your own research, or want to refer to baseline results pub journal = {Journal of Open Source Software} } +.. |PyPI| image:: https://img.shields.io/pypi/v/direct-recon.svg + :target: https://pypi.org/project/direct-recon/ + :alt: PyPI .. |JOSS| image:: https://joss.theoj.org/papers/10.21105/joss.04278/status.svg :target: https://doi.org/10.21105/joss.04278 :alt: JOSS From 1feb1660c81bc0aee765706d32180b4b7fc1a060 Mon Sep 17 00:00:00 2001 From: Jonas Teuwen Date: Fri, 7 Aug 2026 12:50:42 +0200 Subject: [PATCH 07/11] release: bump version to 2.1.1 Bump the version across pyproject.toml, meson.build, direct/__init__.py, and uv.lock (kept in sync by tests/version_test.py). Co-authored-by: Cursor --- direct/__init__.py | 2 +- meson.build | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/direct/__init__.py b/direct/__init__.py index 47ae027f..7fe4798d 100644 --- a/direct/__init__.py +++ b/direct/__init__.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. __author__ = """direct contributors""" -__version__ = "2.1.0" +__version__ = "2.1.1" diff --git a/meson.build b/meson.build index e2c53064..5e4e53c2 100644 --- a/meson.build +++ b/meson.build @@ -13,7 +13,7 @@ # limitations under the License. project('direct', 'cpp', - version : '2.1.0', + version : '2.1.1', license : 'Apache-2.0', meson_version : '>=1.3', default_options : [ diff --git a/pyproject.toml b/pyproject.toml index c67133df..b682ff08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ classifiers = [ # Static so uv can read metadata without invoking the build backend (required # because `direct` is built without isolation; see `[tool.uv]` below). Kept in # sync with meson.build and direct/__init__.py by tests/version_test.py. -version = "2.1.0" +version = "2.1.1" dependencies = [ "numpy>=2.4,<3", "h5py>=3.16", diff --git a/uv.lock b/uv.lock index 4258d491..c9dc5a9e 100644 --- a/uv.lock +++ b/uv.lock @@ -260,7 +260,7 @@ nvtx = [ [[package]] name = "direct-recon" -version = "2.1.0" +version = "2.1.1" source = { editable = "." } dependencies = [ { name = "einops" }, From f2d236b3e0c67d675785c3b3cd75de0dbcee121c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:07:54 +0000 Subject: [PATCH 08/11] docs: clarify Windows wheel exception for limited-api note Co-authored-by: georgeyiasemis <71031687+georgeyiasemis@users.noreply.github.com> --- pyproject.toml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b682ff08..962271ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -94,9 +94,10 @@ direct = "direct.cli.cli:main" Homepage = "https://github.com/NKI-AI/direct" [tool.meson-python] -# The C++ extensions target the CPython 3.12 stable ABI (abi3), so the wheels -# are tagged `abi3` and a single wheel per platform serves every supported -# interpreter. +# The C++ extensions target the CPython 3.12 stable ABI (abi3), so non-Windows +# wheels are tagged `abi3` and a single wheel per platform serves every +# supported interpreter. Windows builds override this in the release workflow +# and emit per-version wheels. limited-api = true [tool.meson-python.args] From 919a6d4352c8da5fa2ae16a91c7e8d1c1b6c090c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:11:49 +0000 Subject: [PATCH 09/11] Revert distribution rename to keep PR scope on release CI Co-authored-by: georgeyiasemis <71031687+georgeyiasemis@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- README.rst | 9 ++++----- installation.rst | 9 ++++----- pyproject.toml | 9 ++++----- tests/version_test.py | 4 ++-- uv.lock | 2 +- 6 files changed, 16 insertions(+), 19 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0d20400d..187ed85a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -223,7 +223,7 @@ jobs: py="$repo/.venv/bin/python" fi uv pip install --python "$py" pytest numpy - uv pip install --python "$py" --no-deps --no-index --find-links dist direct-recon + uv pip install --python "$py" --no-deps --no-index --find-links dist direct # Run from a scratch dir (not the repo root) with importlib import mode # so the uncompiled source tree never shadows the installed wheel. cd "$RUNNER_TEMP" diff --git a/README.rst b/README.rst index 7171d891..8ea5520c 100644 --- a/README.rst +++ b/README.rst @@ -29,12 +29,11 @@ For a full list of the baselines currently implemented in DIRECT see `here <#bas Quick install ------------- -``DIRECT`` is published to PyPI as ``direct-recon`` (the import package is still -``direct``): +``DIRECT`` is published to PyPI as ``direct``: .. code-block:: bash - pip install direct-recon + pip install direct For development, the recommended way is with `uv `_: @@ -83,8 +82,8 @@ If you use DIRECT in your own research, or want to refer to baseline results pub journal = {Journal of Open Source Software} } -.. |PyPI| image:: https://img.shields.io/pypi/v/direct-recon.svg - :target: https://pypi.org/project/direct-recon/ +.. |PyPI| image:: https://img.shields.io/pypi/v/direct.svg + :target: https://pypi.org/project/direct/ :alt: PyPI .. |JOSS| image:: https://joss.theoj.org/papers/10.21105/joss.04278/status.svg :target: https://doi.org/10.21105/joss.04278 diff --git a/installation.rst b/installation.rst index 9839d7e8..d8ea47d7 100644 --- a/installation.rst +++ b/installation.rst @@ -63,13 +63,12 @@ directly from ``pyproject.toml`` and the committed ``uv.lock``. Install from PyPI (``pip``) --------------------------- -``DIRECT`` is published to PyPI as ``direct-recon`` (the import package is still -``direct``). On the supported platforms this fetches a prebuilt ``abi3`` wheel, -so nothing is compiled: +``DIRECT`` is published to PyPI as ``direct``. On the supported platforms this +fetches a prebuilt ``abi3`` wheel, so nothing is compiled: .. code-block:: - pip install direct-recon + pip install direct .. code-block:: python @@ -138,7 +137,7 @@ Install using ``conda`` (alternative) .. code-block:: - pip3 install direct-recon + pip3 install direct To build from a checkout instead, clone the repository, navigate to ``direct/`` and run diff --git a/pyproject.toml b/pyproject.toml index 962271ac..8da9d422 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,9 +3,8 @@ requires = ["meson-python>=0.18", "meson>=1.5"] build-backend = "mesonpy" [project] -# Distribution name on PyPI. The import package is still `direct` (see -# meson.build / install_subdir), so `pip install direct-recon` then `import direct`. -name = "direct-recon" +# Distribution name on PyPI and import package name. +name = "direct" description = "DIRECT - Deep Image REConsTruction - is a deep learning framework for MRI reconstruction." readme = "README.rst" license = { text = "Apache-2.0" } @@ -74,12 +73,12 @@ docs = [ [tool.uv] default-groups = ["dev", "build"] -# Build `direct-recon` against the already-synced `build` group instead of an +# Build `direct` against the already-synced `build` group instead of an # isolated build environment. Without this, meson-python's editable install # records the absolute path of the isolated build env's `ninja`, which uv later # deletes, breaking `import direct` on the next run. Matches the distribution # name in `[project] name`, not the import package. -no-build-isolation-package = ["direct-recon"] +no-build-isolation-package = ["direct"] [tool.pytest.ini_options] # Keep collection inside the project's own suite; never descend into the diff --git a/tests/version_test.py b/tests/version_test.py index fdc35bdd..a575231b 100644 --- a/tests/version_test.py +++ b/tests/version_test.py @@ -50,8 +50,8 @@ def _pyproject_version() -> str: def test_dunder_version_matches_installed_metadata() -> None: - # Distribution name (PyPI) is `direct-recon`; the import package is `direct`. - assert direct.__version__ == importlib.metadata.version("direct-recon") + # Distribution name (PyPI) matches the import package. + assert direct.__version__ == importlib.metadata.version("direct") def test_pyproject_version_matches_dunder_version() -> None: diff --git a/uv.lock b/uv.lock index c9dc5a9e..e1e2358c 100644 --- a/uv.lock +++ b/uv.lock @@ -259,7 +259,7 @@ nvtx = [ ] [[package]] -name = "direct-recon" +name = "direct" version = "2.1.1" source = { editable = "." } dependencies = [ From be478392766ed3cd5d9ab27c764aab2b5bbe616c Mon Sep 17 00:00:00 2001 From: George Yiasemis Date: Fri, 7 Aug 2026 13:12:06 +0200 Subject: [PATCH 10/11] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: George Yiasemis --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 187ed85a..0156258f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -100,7 +100,7 @@ jobs: # abi3 (cp312-*) on Linux/macOS; per-version on Windows (see matrix). CIBW_BUILD: ${{ matrix.cibw_build }} # Skip musllinux: PyTorch (a hard runtime dependency) publishes no - # musllinux wheels, so a musllinux `direct` wheel is not installable. + # musllinux wheels, so a musllinux `direct-recon` wheel is not installable. CIBW_SKIP: "*-musllinux*" CIBW_ARCHS: ${{ matrix.cibw_archs }} CIBW_BUILD_VERBOSITY: "1" From e7f893268e8760e72769b15c282b1d353c0ca771 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:52:28 +0000 Subject: [PATCH 11/11] docs: clarify Windows wheels are not abi3 Co-authored-by: georgeyiasemis <71031687+georgeyiasemis@users.noreply.github.com> --- installation.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/installation.rst b/installation.rst index d8ea47d7..7416bcd0 100644 --- a/installation.rst +++ b/installation.rst @@ -64,7 +64,8 @@ Install from PyPI (``pip``) --------------------------- ``DIRECT`` is published to PyPI as ``direct``. On the supported platforms this -fetches a prebuilt ``abi3`` wheel, so nothing is compiled: +fetches a prebuilt wheel (``abi3`` on Linux/macOS, Python-version-specific on +Windows), so nothing is compiled: .. code-block:: @@ -133,7 +134,8 @@ Install using ``conda`` (alternative) #. Install ``DIRECT`` from PyPI. On the supported platforms this fetches a - prebuilt ``abi3`` wheel, so nothing is compiled: + prebuilt wheel (``abi3`` on Linux/macOS, Python-version-specific on + Windows), so nothing is compiled: .. code-block::