From fcd75ac789c3c03000d5b8e260941ee38d06b135 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Mon, 18 Aug 2025 00:34:59 +0200 Subject: [PATCH 01/23] Narrow scopes where 3.12 hacks apply --- line_profiler/c_trace_callbacks.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/line_profiler/c_trace_callbacks.h b/line_profiler/c_trace_callbacks.h index e4238f1b..fe0aedc8 100644 --- a/line_profiler/c_trace_callbacks.h +++ b/line_profiler/c_trace_callbacks.h @@ -24,17 +24,17 @@ # ifndef Py_BUILD_CORE # define Py_BUILD_CORE 1 # endif -# ifdef _PyGC_FINALIZED -# undef _PyGC_FINALIZED -# endif -# ifdef HAVE_STD_ATOMIC -# undef HAVE_STD_ATOMIC -# endif -# if PY_VERSION_HEX >= 0x030900a6 // 3.9.0a6 -# include "internal/pycore_interp.h" -# else -# include "internal/pycore_pystate.h" +# if PY_VERSION_HEX < 0x030d0000 // 3.13 +# ifdef _PyGC_FINALIZED +# undef _PyGC_FINALIZED +# endif +# ifdef __linux__ +# ifdef HAVE_STD_ATOMIC +# undef HAVE_STD_ATOMIC +# endif +# endif # endif +# include "internal/pycore_interp.h" #endif typedef struct TraceCallback From 4f13a9cda92447fd2dcefc6f009164b350fe52ae Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Mon, 18 Aug 2025 01:15:05 +0200 Subject: [PATCH 02/23] Update CI to target and test ARM64 Windows --- .github/workflows/tests.yml | 36 +++++++++++++++++++++++++++++++++++- pyproject.toml | 2 ++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b11015ff..3af2c9d9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -236,6 +236,7 @@ jobs: install-extras: tests-strict,runtime-strict os: windows-latest arch: auto + # Note: cibuildwheel can't target 3.8 on Window ARM64 - python-version: '3.13' install-extras: tests-strict,runtime-strict,optional-strict os: ubuntu-latest @@ -248,6 +249,10 @@ jobs: install-extras: tests-strict,runtime-strict,optional-strict os: windows-latest arch: auto + - python-version: '3.13' + install-extras: tests-strict,runtime-strict,optional-strict + os: windows-11-arm + arch: auto - python-version: '3.13' install-extras: tests os: macOS-latest @@ -256,6 +261,10 @@ jobs: install-extras: tests os: windows-latest arch: auto + - python-version: '3.13' + install-extras: tests + os: windows-11-arm + arch: auto - python-version: '3.8' install-extras: tests,optional os: ubuntu-latest @@ -340,12 +349,37 @@ jobs: install-extras: tests,optional os: windows-latest arch: auto + # Note: again, cibuildwheel can't target 3.8 on Window ARM64 + - python-version: '3.9' + install-extras: tests,optional + os: windows-11-arm + arch: auto + - python-version: '3.10' + install-extras: tests,optional + os: windows-11-arm + arch: auto + - python-version: '3.11' + install-extras: tests,optional + os: windows-11-arm + arch: auto + - python-version: '3.12' + install-extras: tests,optional + os: windows-11-arm + arch: auto + - python-version: '3.13' + install-extras: tests,optional + os: windows-11-arm + arch: auto + - python-version: 3.14.0-rc.1 + install-extras: tests,optional + os: windows-11-arm + arch: auto steps: - name: Checkout source uses: actions/checkout@v4.2.2 - name: Enable MSVC 64bit uses: ilammy/msvc-dev-cmd@v1 - if: matrix.os == 'windows-latest' + if: startsWith(matrix.os, 'windows-') - name: Set up QEMU uses: docker/setup-qemu-action@v3.0.0 if: runner.os == 'Linux' && matrix.arch != 'auto' diff --git a/pyproject.toml b/pyproject.toml index bc62f15a..52511799 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,8 @@ test-extras = ["tests-strict", "runtime-strict"] # https://cibuildwheel.readthedocs.io/en/stable/options/#archs [tool.cibuildwheel.macos] archs = ["x86_64", "universal2", "arm64"] +[tool.cibuildwheel.windows] +archs = ['AMD64', 'ARM64'] [tool.mypy] From 3783b9f30ef9f12834f0da5a8c0fbf5ca516f734 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Mon, 18 Aug 2025 01:51:49 +0200 Subject: [PATCH 03/23] Fixed expressions and unset ${VSCMD_ARG_TGT_ARCH} --- .github/workflows/tests.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3af2c9d9..ed51ad5b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -137,7 +137,7 @@ jobs: uses: actions/checkout@v4.2.2 - name: Enable MSVC 64bit uses: ilammy/msvc-dev-cmd@v1 - if: matrix.os == 'windows-latest' && ${{ contains(matrix.cibw_skip, '*-win32') }} + if: ${{ startsWith(matrix.os, 'windows-') }} && ${{ contains(matrix.cibw_skip, '*-win32') }} - name: Set up QEMU uses: docker/setup-qemu-action@v3.0.0 if: runner.os == 'Linux' && matrix.arch != 'auto' @@ -155,6 +155,12 @@ jobs: PYTHONUTF8: '1' CIBW_CONFIG_SETTINGS: --build-option=--py-limited-api=cp38 CIBW_BUILD: cp38-* + # Note: apparently something (probably msvc-dev-cmd) sets the + # envvar, which prevents cibuildwheel from targeting non-native + # architecture on some versions... + # we can't unset envvars yet though (see actions/runner#1126), + # but let's see if this helps + VSCMD_ARG_TGT_ARCH: '' - name: Build binary wheels uses: pypa/cibuildwheel@v3.1.2 with: @@ -165,6 +171,7 @@ jobs: CIBW_ARCHS_LINUX: ${{ matrix.arch }} CIBW_ENVIRONMENT: PYTHONUTF8=1 PYTHONUTF8: '1' + VSCMD_ARG_TGT_ARCH: '' - name: Show built files shell: bash run: ls -la wheelhouse @@ -379,7 +386,7 @@ jobs: uses: actions/checkout@v4.2.2 - name: Enable MSVC 64bit uses: ilammy/msvc-dev-cmd@v1 - if: startsWith(matrix.os, 'windows-') + if: ${{ startsWith(matrix.os, 'windows-') }} - name: Set up QEMU uses: docker/setup-qemu-action@v3.0.0 if: runner.os == 'Linux' && matrix.arch != 'auto' From 1cc16baacc00b3bb879bbaa8943d868a6f249d9a Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Mon, 18 Aug 2025 04:04:26 +0200 Subject: [PATCH 04/23] pre-include `pycore_atomic.h` to circumvent bad funcdefs --- line_profiler/c_trace_callbacks.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/line_profiler/c_trace_callbacks.h b/line_profiler/c_trace_callbacks.h index fe0aedc8..39bd94ab 100644 --- a/line_profiler/c_trace_callbacks.h +++ b/line_profiler/c_trace_callbacks.h @@ -14,6 +14,11 @@ * and causes problems in 3.12 (see CPython #105268, #105350, #107348) * - Undefine the `HAVE_STD_ATOMIC` macro, which causes problems on * Linux in 3.12 (see CPython #108216) + * - Temporarily replace `_M_ARM64` with `_M_ARM` and pre-include + * `include/pycore_atomic.h` (which is indirectly + * included in `include/pycore_interp.h`), so that problematic + * function definitions therein are replaced with dummy ones (see + * #390) * Note in any case that we don't actually use `PyInterpreterState` * directly -- we just need its memory layout so that we can refer to * its `.last_restart_version` member @@ -25,13 +30,16 @@ # define Py_BUILD_CORE 1 # endif # if PY_VERSION_HEX < 0x030d0000 // 3.13 -# ifdef _PyGC_FINALIZED -# undef _PyGC_FINALIZED -# endif +# undef _PyGC_FINALIZED # ifdef __linux__ -# ifdef HAVE_STD_ATOMIC -# undef HAVE_STD_ATOMIC -# endif +# undef HAVE_STD_ATOMIC +# endif +# ifdef _M_ARM64 +# undef _M_ARM64 +# define _M_ARM +# include "internal/pycore_atomic.h" +# undef _M_ARM +# define _M_ARM64 # endif # endif # include "internal/pycore_interp.h" From eda8d0bb3b8c2cd2c03df7e8ed3c370335ff7adb Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Mon, 18 Aug 2025 05:03:02 +0200 Subject: [PATCH 05/23] temporarily truncate job matrix to focus on Windows-ARM64 --- .github/workflows/tests.yml | 247 +++++++++++++++++++----------------- pyproject.toml | 5 +- 2 files changed, 132 insertions(+), 120 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ed51ad5b..4f921367 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -125,8 +125,11 @@ jobs: # the standard [tool.cibuildwheel] section in pyproject.toml and set # explicitly here. os: - - ubuntu-latest - - macOS-latest + # FIXME START: temporarily truncate pipeline to focus on + # 3.12 on Windows + # - ubuntu-latest + # - macOS-latest + # FIXME END - windows-latest cibw_skip: - '*-win32 *-win32 cp313-musllinux_i686' @@ -231,131 +234,137 @@ jobs: # Xcookie generates an explicit list of environments that will be used # for testing instead of using the more concise matrix notation. include: - - python-version: '3.8' - install-extras: tests-strict,runtime-strict - os: ubuntu-latest - arch: auto - - python-version: '3.8' - install-extras: tests-strict,runtime-strict - os: macOS-latest - arch: auto - - python-version: '3.8' - install-extras: tests-strict,runtime-strict - os: windows-latest - arch: auto - # Note: cibuildwheel can't target 3.8 on Window ARM64 - - python-version: '3.13' - install-extras: tests-strict,runtime-strict,optional-strict - os: ubuntu-latest - arch: auto - - python-version: '3.13' - install-extras: tests-strict,runtime-strict,optional-strict - os: macOS-latest - arch: auto - - python-version: '3.13' - install-extras: tests-strict,runtime-strict,optional-strict - os: windows-latest - arch: auto + # FIXME START + # - python-version: '3.8' + # install-extras: tests-strict,runtime-strict + # os: ubuntu-latest + # arch: auto + # - python-version: '3.8' + # install-extras: tests-strict,runtime-strict + # os: macOS-latest + # arch: auto + # - python-version: '3.8' + # install-extras: tests-strict,runtime-strict + # os: windows-latest + # arch: auto + # # Note: cibuildwheel can't target 3.8 on Window ARM64 + # - python-version: '3.13' + # install-extras: tests-strict,runtime-strict,optional-strict + # os: ubuntu-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests-strict,runtime-strict,optional-strict + # os: macOS-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests-strict,runtime-strict,optional-strict + # os: windows-latest + # arch: auto + # FIXME END - python-version: '3.13' install-extras: tests-strict,runtime-strict,optional-strict os: windows-11-arm arch: auto - - python-version: '3.13' - install-extras: tests - os: macOS-latest - arch: auto - - python-version: '3.13' - install-extras: tests - os: windows-latest - arch: auto + # FIXME START + # - python-version: '3.13' + # install-extras: tests + # os: macOS-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests + # os: windows-latest + # arch: auto + # FIXME END - python-version: '3.13' install-extras: tests os: windows-11-arm arch: auto - - python-version: '3.8' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.9' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.10' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.11' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.12' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.13' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: 3.14.0-rc.1 - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.8' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.9' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.10' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.11' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.12' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.13' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: 3.14.0-rc.1 - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.8' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: '3.9' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: '3.10' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: '3.11' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: '3.12' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: '3.13' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: 3.14.0-rc.1 - install-extras: tests,optional - os: windows-latest - arch: auto + # FIXME START + # - python-version: '3.8' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.9' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.10' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.11' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.12' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: 3.14.0-rc.1 + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.8' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.9' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.10' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.11' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.12' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: 3.14.0-rc.1 + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.8' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: '3.9' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: '3.10' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: '3.11' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: '3.12' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: 3.14.0-rc.1 + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # FIXME END # Note: again, cibuildwheel can't target 3.8 on Window ARM64 - python-version: '3.9' install-extras: tests,optional diff --git a/pyproject.toml b/pyproject.toml index 52511799..dfc0bafc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,10 @@ omit =[ ] [tool.cibuildwheel] -build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" +# FIXME START +# build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" +build = "cp312-* cp313-* cp314-*" +# FIXME END skip = ["*-win32", "cp313-musllinux_i686"] build-frontend = "build" build-verbosity = 1 From 87e7723e7abc9ee59a0df6f6d24a74349583cb51 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Mon, 18 Aug 2025 05:17:58 +0200 Subject: [PATCH 06/23] sidestep inclusion of `pycore_atomic.h`, just mock what we need --- line_profiler/c_trace_callbacks.h | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/line_profiler/c_trace_callbacks.h b/line_profiler/c_trace_callbacks.h index 39bd94ab..a8abfbb7 100644 --- a/line_profiler/c_trace_callbacks.h +++ b/line_profiler/c_trace_callbacks.h @@ -14,11 +14,12 @@ * and causes problems in 3.12 (see CPython #105268, #105350, #107348) * - Undefine the `HAVE_STD_ATOMIC` macro, which causes problems on * Linux in 3.12 (see CPython #108216) - * - Temporarily replace `_M_ARM64` with `_M_ARM` and pre-include - * `include/pycore_atomic.h` (which is indirectly - * included in `include/pycore_interp.h`), so that problematic - * function definitions therein are replaced with dummy ones (see - * #390) + * - Set `Py_ATOMIC_H` to true to circumvent the #include of + * `include/pycore_atomic.h` (in `include/pycore_interp.h`, so that + * problematic function definitions therein are replaced with dummy + * ones (see #390); note that we still need to vendor in parts + * therefrom which are used by `pycore_interp.h` (or at least mock + * them) * Note in any case that we don't actually use `PyInterpreterState` * directly -- we just need its memory layout so that we can refer to * its `.last_restart_version` member @@ -34,12 +35,13 @@ # ifdef __linux__ # undef HAVE_STD_ATOMIC # endif -# ifdef _M_ARM64 -# undef _M_ARM64 -# define _M_ARM -# include "internal/pycore_atomic.h" -# undef _M_ARM -# define _M_ARM64 +# if (defined(_M_ARM) || defined(_M_ARM64)) && (! defined(Py_ATOMIC_H)) + typedef struct _Py_atomic_address { + volatile uintptr_t _value; + } _Py_atomic_address; +# define _Py_atomic_load_relaxed(foo) (0) +# define _Py_atomic_store_relaxed(foo, bar) (0) +# include "internal/pycore_interp.h" # endif # endif # include "internal/pycore_interp.h" From f407d00797d7258e9c5458e3ef0603151c1ebd73 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Mon, 18 Aug 2025 05:31:13 +0200 Subject: [PATCH 07/23] temporarily stop building Windows-AMD64 and ABI3 wheels --- .github/workflows/tests.yml | 38 +++++++++++++++++++------------------ pyproject.toml | 4 +++- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4f921367..2304bc58 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -146,24 +146,26 @@ jobs: if: runner.os == 'Linux' && matrix.arch != 'auto' with: platforms: all - - name: Build binary wheels - uses: pypa/cibuildwheel@v3.1.2 - with: - output-dir: wheelhouse - config-file: pyproject.toml - env: - CIBW_SKIP: ${{ matrix.cibw_skip }} - CIBW_ARCHS_LINUX: ${{ matrix.arch }} - CIBW_ENVIRONMENT: PYTHONUTF8=1 - PYTHONUTF8: '1' - CIBW_CONFIG_SETTINGS: --build-option=--py-limited-api=cp38 - CIBW_BUILD: cp38-* - # Note: apparently something (probably msvc-dev-cmd) sets the - # envvar, which prevents cibuildwheel from targeting non-native - # architecture on some versions... - # we can't unset envvars yet though (see actions/runner#1126), - # but let's see if this helps - VSCMD_ARG_TGT_ARCH: '' + # FIXME START + # - name: Build binary wheels + # uses: pypa/cibuildwheel@v3.1.2 + # with: + # output-dir: wheelhouse + # config-file: pyproject.toml + # env: + # CIBW_SKIP: ${{ matrix.cibw_skip }} + # CIBW_ARCHS_LINUX: ${{ matrix.arch }} + # CIBW_ENVIRONMENT: PYTHONUTF8=1 + # PYTHONUTF8: '1' + # CIBW_CONFIG_SETTINGS: --build-option=--py-limited-api=cp38 + # CIBW_BUILD: cp38-* + # # Note: apparently something (probably msvc-dev-cmd) sets the + # # envvar, which prevents cibuildwheel from targeting non-native + # # architecture on some versions... + # # we can't unset envvars yet though (see actions/runner#1126), + # # but let's see if this helps + # VSCMD_ARG_TGT_ARCH: '' + # FIXME END - name: Build binary wheels uses: pypa/cibuildwheel@v3.1.2 with: diff --git a/pyproject.toml b/pyproject.toml index dfc0bafc..50f11fe8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,9 @@ test-extras = ["tests-strict", "runtime-strict"] [tool.cibuildwheel.macos] archs = ["x86_64", "universal2", "arm64"] [tool.cibuildwheel.windows] -archs = ['AMD64', 'ARM64'] +# FIXME START +archs = ['ARM64'] +# FIXME END [tool.mypy] From 9fc296a521a37f72bd24f97def591fdbfc74e16a Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Mon, 18 Aug 2025 07:24:32 +0200 Subject: [PATCH 08/23] Added missing #define --- line_profiler/c_trace_callbacks.h | 1 + 1 file changed, 1 insertion(+) diff --git a/line_profiler/c_trace_callbacks.h b/line_profiler/c_trace_callbacks.h index a8abfbb7..aa3998ca 100644 --- a/line_profiler/c_trace_callbacks.h +++ b/line_profiler/c_trace_callbacks.h @@ -36,6 +36,7 @@ # undef HAVE_STD_ATOMIC # endif # if (defined(_M_ARM) || defined(_M_ARM64)) && (! defined(Py_ATOMIC_H)) +# define Py_ATOMIC_H typedef struct _Py_atomic_address { volatile uintptr_t _value; } _Py_atomic_address; From a974931881bdfd0327dcb13904c641bbe97f4fe2 Mon Sep 17 00:00:00 2001 From: da-woods Date: Mon, 18 Aug 2025 08:00:58 +0100 Subject: [PATCH 09/23] Try moving Python internal includes into the C file --- line_profiler/c_trace_callbacks.c | 39 +++++++++++++++++++++++++++ line_profiler/c_trace_callbacks.h | 44 ------------------------------- 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/line_profiler/c_trace_callbacks.c b/line_profiler/c_trace_callbacks.c index d036eefd..64affc00 100644 --- a/line_profiler/c_trace_callbacks.c +++ b/line_profiler/c_trace_callbacks.c @@ -1,5 +1,44 @@ #include "c_trace_callbacks.h" +/* + * XXX: would make better sense to declare `PyInterpreterState` in + * "Python_wrapper.h", but the file declaring it causes all sorts of + * trouble across various platforms and Python versions... so + * - Only include the file if we are actually using it here, i.e. in + * 3.12+, and + * - Undefine the `_PyGC_FINALIZED()` macro which is removed in 3.13+ + * and causes problems in 3.12 (see CPython #105268, #105350, #107348) + * - Undefine the `HAVE_STD_ATOMIC` macro, which causes problems on + * Linux in 3.12 (see CPython #108216) + * - Set `Py_ATOMIC_H` to true to circumvent the #include of + * `include/pycore_atomic.h` (in `include/pycore_interp.h`, so that + * problematic function definitions therein are replaced with dummy + * ones (see #390); note that we still need to vendor in parts + * therefrom which are used by `pycore_interp.h` (or at least mock + * them) + * Note in any case that we don't actually use `PyInterpreterState` + * directly -- we just need its memory layout so that we can refer to + * its `.last_restart_version` member + */ + +// _is -> PyInterpreterState +#if PY_VERSION_HEX >= 0x030c00b1 // 3.12.0b6 +# ifndef Py_BUILD_CORE +# define Py_BUILD_CORE 1 +# endif +# ifdef _PyGC_FINALIZED +# undef _PyGC_FINALIZED +# endif +# if defined(__linux__) && defined(HAVE_STD_ATOMIC) +# undef HAVE_STD_ATOMIC +# endif +# if PY_VERSION_HEX >= 0x030900a6 // 3.9.0a6 +# include "internal/pycore_interp.h" +# else +# include "internal/pycore_pystate.h" +# endif +#endif + #define CYTHON_MODULE "line_profiler._line_profiler" #define DISABLE_CALLBACK "disable_line_events" #define RAISE_IN_CALL(func_name, xc, const_msg) \ diff --git a/line_profiler/c_trace_callbacks.h b/line_profiler/c_trace_callbacks.h index aa3998ca..95823fae 100644 --- a/line_profiler/c_trace_callbacks.h +++ b/line_profiler/c_trace_callbacks.h @@ -4,50 +4,6 @@ #include "Python_wrapper.h" #include "frameobject.h" -/* - * XXX: would make better sense to declare `PyInterpreterState` in - * "Python_wrapper.h", but the file declaring it causes all sorts of - * trouble across various platforms and Python versions... so - * - Only include the file if we are actually using it here, i.e. in - * 3.12+, and - * - Undefine the `_PyGC_FINALIZED()` macro which is removed in 3.13+ - * and causes problems in 3.12 (see CPython #105268, #105350, #107348) - * - Undefine the `HAVE_STD_ATOMIC` macro, which causes problems on - * Linux in 3.12 (see CPython #108216) - * - Set `Py_ATOMIC_H` to true to circumvent the #include of - * `include/pycore_atomic.h` (in `include/pycore_interp.h`, so that - * problematic function definitions therein are replaced with dummy - * ones (see #390); note that we still need to vendor in parts - * therefrom which are used by `pycore_interp.h` (or at least mock - * them) - * Note in any case that we don't actually use `PyInterpreterState` - * directly -- we just need its memory layout so that we can refer to - * its `.last_restart_version` member - */ - -// _is -> PyInterpreterState -#if PY_VERSION_HEX >= 0x030c00b1 // 3.12.0b6 -# ifndef Py_BUILD_CORE -# define Py_BUILD_CORE 1 -# endif -# if PY_VERSION_HEX < 0x030d0000 // 3.13 -# undef _PyGC_FINALIZED -# ifdef __linux__ -# undef HAVE_STD_ATOMIC -# endif -# if (defined(_M_ARM) || defined(_M_ARM64)) && (! defined(Py_ATOMIC_H)) -# define Py_ATOMIC_H - typedef struct _Py_atomic_address { - volatile uintptr_t _value; - } _Py_atomic_address; -# define _Py_atomic_load_relaxed(foo) (0) -# define _Py_atomic_store_relaxed(foo, bar) (0) -# include "internal/pycore_interp.h" -# endif -# endif -# include "internal/pycore_interp.h" -#endif - typedef struct TraceCallback { /* Notes: From 6a8976358cef10534f26789ef92684386637197f Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Mon, 18 Aug 2025 09:10:37 +0200 Subject: [PATCH 10/23] simplify macros --- line_profiler/c_trace_callbacks.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/line_profiler/c_trace_callbacks.c b/line_profiler/c_trace_callbacks.c index 64affc00..8cd6de19 100644 --- a/line_profiler/c_trace_callbacks.c +++ b/line_profiler/c_trace_callbacks.c @@ -26,17 +26,11 @@ # ifndef Py_BUILD_CORE # define Py_BUILD_CORE 1 # endif -# ifdef _PyGC_FINALIZED -# undef _PyGC_FINALIZED -# endif +# undef _PyGC_FINALIZED # if defined(__linux__) && defined(HAVE_STD_ATOMIC) # undef HAVE_STD_ATOMIC # endif -# if PY_VERSION_HEX >= 0x030900a6 // 3.9.0a6 -# include "internal/pycore_interp.h" -# else -# include "internal/pycore_pystate.h" -# endif +# include "internal/pycore_interp.h" #endif #define CYTHON_MODULE "line_profiler._line_profiler" From bf1f22f5748f4bcb74920bac137f9f24db8d3a23 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Fri, 22 Aug 2025 21:59:41 +0200 Subject: [PATCH 11/23] roll back #392 --- line_profiler/c_trace_callbacks.c | 33 ----------------------- line_profiler/c_trace_callbacks.h | 44 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/line_profiler/c_trace_callbacks.c b/line_profiler/c_trace_callbacks.c index 8cd6de19..d036eefd 100644 --- a/line_profiler/c_trace_callbacks.c +++ b/line_profiler/c_trace_callbacks.c @@ -1,38 +1,5 @@ #include "c_trace_callbacks.h" -/* - * XXX: would make better sense to declare `PyInterpreterState` in - * "Python_wrapper.h", but the file declaring it causes all sorts of - * trouble across various platforms and Python versions... so - * - Only include the file if we are actually using it here, i.e. in - * 3.12+, and - * - Undefine the `_PyGC_FINALIZED()` macro which is removed in 3.13+ - * and causes problems in 3.12 (see CPython #105268, #105350, #107348) - * - Undefine the `HAVE_STD_ATOMIC` macro, which causes problems on - * Linux in 3.12 (see CPython #108216) - * - Set `Py_ATOMIC_H` to true to circumvent the #include of - * `include/pycore_atomic.h` (in `include/pycore_interp.h`, so that - * problematic function definitions therein are replaced with dummy - * ones (see #390); note that we still need to vendor in parts - * therefrom which are used by `pycore_interp.h` (or at least mock - * them) - * Note in any case that we don't actually use `PyInterpreterState` - * directly -- we just need its memory layout so that we can refer to - * its `.last_restart_version` member - */ - -// _is -> PyInterpreterState -#if PY_VERSION_HEX >= 0x030c00b1 // 3.12.0b6 -# ifndef Py_BUILD_CORE -# define Py_BUILD_CORE 1 -# endif -# undef _PyGC_FINALIZED -# if defined(__linux__) && defined(HAVE_STD_ATOMIC) -# undef HAVE_STD_ATOMIC -# endif -# include "internal/pycore_interp.h" -#endif - #define CYTHON_MODULE "line_profiler._line_profiler" #define DISABLE_CALLBACK "disable_line_events" #define RAISE_IN_CALL(func_name, xc, const_msg) \ diff --git a/line_profiler/c_trace_callbacks.h b/line_profiler/c_trace_callbacks.h index 95823fae..aa3998ca 100644 --- a/line_profiler/c_trace_callbacks.h +++ b/line_profiler/c_trace_callbacks.h @@ -4,6 +4,50 @@ #include "Python_wrapper.h" #include "frameobject.h" +/* + * XXX: would make better sense to declare `PyInterpreterState` in + * "Python_wrapper.h", but the file declaring it causes all sorts of + * trouble across various platforms and Python versions... so + * - Only include the file if we are actually using it here, i.e. in + * 3.12+, and + * - Undefine the `_PyGC_FINALIZED()` macro which is removed in 3.13+ + * and causes problems in 3.12 (see CPython #105268, #105350, #107348) + * - Undefine the `HAVE_STD_ATOMIC` macro, which causes problems on + * Linux in 3.12 (see CPython #108216) + * - Set `Py_ATOMIC_H` to true to circumvent the #include of + * `include/pycore_atomic.h` (in `include/pycore_interp.h`, so that + * problematic function definitions therein are replaced with dummy + * ones (see #390); note that we still need to vendor in parts + * therefrom which are used by `pycore_interp.h` (or at least mock + * them) + * Note in any case that we don't actually use `PyInterpreterState` + * directly -- we just need its memory layout so that we can refer to + * its `.last_restart_version` member + */ + +// _is -> PyInterpreterState +#if PY_VERSION_HEX >= 0x030c00b1 // 3.12.0b6 +# ifndef Py_BUILD_CORE +# define Py_BUILD_CORE 1 +# endif +# if PY_VERSION_HEX < 0x030d0000 // 3.13 +# undef _PyGC_FINALIZED +# ifdef __linux__ +# undef HAVE_STD_ATOMIC +# endif +# if (defined(_M_ARM) || defined(_M_ARM64)) && (! defined(Py_ATOMIC_H)) +# define Py_ATOMIC_H + typedef struct _Py_atomic_address { + volatile uintptr_t _value; + } _Py_atomic_address; +# define _Py_atomic_load_relaxed(foo) (0) +# define _Py_atomic_store_relaxed(foo, bar) (0) +# include "internal/pycore_interp.h" +# endif +# endif +# include "internal/pycore_interp.h" +#endif + typedef struct TraceCallback { /* Notes: From 57535cc2889ddedfcf24c5c9c97d11623f651f35 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Wed, 27 Aug 2025 10:48:34 +0200 Subject: [PATCH 12/23] vendor in `_Py_atomic_int` from `pycore_atomic.h` --- line_profiler/c_trace_callbacks.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/line_profiler/c_trace_callbacks.h b/line_profiler/c_trace_callbacks.h index aa3998ca..18584d8d 100644 --- a/line_profiler/c_trace_callbacks.h +++ b/line_profiler/c_trace_callbacks.h @@ -18,8 +18,8 @@ * `include/pycore_atomic.h` (in `include/pycore_interp.h`, so that * problematic function definitions therein are replaced with dummy * ones (see #390); note that we still need to vendor in parts - * therefrom which are used by `pycore_interp.h` (or at least mock - * them) + * therefrom which are used by `pycore_interp.h`, and its dependencies + * `pycore_ceval_state.h` and `pycore_gil.h` (or at least mock them) * Note in any case that we don't actually use `PyInterpreterState` * directly -- we just need its memory layout so that we can refer to * its `.last_restart_version` member @@ -37,9 +37,14 @@ # endif # if (defined(_M_ARM) || defined(_M_ARM64)) && (! defined(Py_ATOMIC_H)) # define Py_ATOMIC_H + // Used in `pycore_interp.h` typedef struct _Py_atomic_address { volatile uintptr_t _value; } _Py_atomic_address; + // Used in `pycore_gil.h` and `pycore_ceval_state.h` + typedef struct _Py_atomic_int { + volatile int _value; + } _Py_atomic_int; # define _Py_atomic_load_relaxed(foo) (0) # define _Py_atomic_store_relaxed(foo, bar) (0) # include "internal/pycore_interp.h" From f51e8ba8a5e0f7e7fa939078b6f3abb0e04722e2 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Wed, 27 Aug 2025 11:40:28 +0200 Subject: [PATCH 13/23] Skip unavailable platforms in CI --- .github/workflows/tests.yml | 16 ++++++---------- pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2fcf23e1..0ec42764 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -131,8 +131,10 @@ jobs: # - macOS-latest # FIXME END - windows-latest + # Since the oldest Python available on windows-11-arm on GitHub + # is 3.11.0, older wheels cannot be tested... so just skip them cibw_skip: - - '*-win32 *-win32 cp313-musllinux_i686' + - '*-win32 cp39-win_arm64 cp310-win_arm64 cp313-musllinux_i686' arch: - auto steps: @@ -347,15 +349,9 @@ jobs: # os: windows-latest # arch: auto # FIXME END - # Note: again, cibuildwheel can't target 3.8 on Window ARM64 - - python-version: '3.9' - install-extras: tests,optional - os: windows-11-arm - arch: auto - - python-version: '3.10' - install-extras: tests,optional - os: windows-11-arm - arch: auto + # Again, cibuildwheel can't target 3.8 on Window ARM64, and + # GitHub doesn't have anything below Python 3.11 on their ARM64 + # machines - python-version: '3.11' install-extras: tests,optional os: windows-11-arm diff --git a/pyproject.toml b/pyproject.toml index 50f11fe8..3c733e69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ omit =[ [tool.cibuildwheel] # FIXME START # build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" -build = "cp312-* cp313-* cp314-*" +build = "cp311-* cp312-* cp313-* cp314-*" # FIXME END skip = ["*-win32", "cp313-musllinux_i686"] build-frontend = "build" From 0a16f5c120078c6317213c79c8c3851f686a7abb Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Wed, 27 Aug 2025 12:13:07 +0200 Subject: [PATCH 14/23] Allow Cython tests to XFAIL on Windows-ARM64 --- tests/test_cython.py | 64 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/tests/test_cython.py b/tests/test_cython.py index fdbf7124..a007a334 100644 --- a/tests/test_cython.py +++ b/tests/test_cython.py @@ -10,15 +10,17 @@ from io import StringIO from operator import methodcaller from pathlib import Path +from platform import machine, system from types import ModuleType -from typing import Generator, Tuple +from typing import Generator, Tuple, Union from uuid import uuid4 import pytest from line_profiler._line_profiler import ( CANNOT_LINE_TRACE_CYTHON, find_cython_source_file) -from line_profiler.line_profiler import get_code_block, LineProfiler +from line_profiler.line_profiler import ( # type:ignore[attr-defined] + get_code_block, LineProfiler) def propose_name(prefix: str) -> Generator[str, None, None]: @@ -27,8 +29,8 @@ def propose_name(prefix: str) -> Generator[str, None, None]: def _install_cython_example( - tmp_path_factory: pytest.TempPathFactory, - editable: bool) -> Generator[Tuple[Path, str], None, None]: + tmp_path_factory: pytest.TempPathFactory, editable: bool, +) -> Generator[Tuple[Path, str, Union[Exception, None]], None, None]: """ Install the example Cython module in a name-clash-free manner. """ @@ -61,35 +63,64 @@ def _install_cython_example( else: pip_install.append(str(tmp_path)) try: - subprocess.run(pip_install).check_returncode() + xc: Union[Exception, None] = None + try: + subprocess.run(pip_install).check_returncode() + except Exception as e: + xc = e subprocess.run(pip + ['list']).check_returncode() - yield cython_source, module + yield cython_source, module, xc finally: pip_uninstall = pip + ['uninstall', '--verbose', '--yes', module] subprocess.run(pip_uninstall).check_returncode() +def _handle_not_installed(xc: Exception): + # FIXME: installation of the Cython package doesn't seem to work on + # Windows-ARM64. Not sure if it's the editable install that is + # problematic, or the package setup, or Cython itself. + # For now we just XFAIL if: + # - We're on Windows-ARM64, and + # - The `pip install` subprocess failed with a + # `subprocess.CalledProcessError`. + # Otherwise, re-raise the exception. + if ( + 'arm' in machine().lower() + and system().lower() == 'windows' + and isinstance(xc, subprocess.CalledProcessError)): + pytest.xfail('installation of the test Cython package ' + 'known to be faulty on Windows-ARM64; ' + 'exact cause unknown') + else: + raise xc + + @pytest.fixture(scope='module') def cython_example( - tmp_path_factory: pytest.TempPathFactory) -> Tuple[Path, ModuleType]: + tmp_path_factory: pytest.TempPathFactory, +) -> Generator[Tuple[Path, ModuleType, Union[Exception, None]], None, None]: """ Install the example Cython module, yield the path to the Cython source file and the corresponding module, uninstall it at teardown. """ # With editable installs, we need to refresh `sys.meta_path` before # the installed module is available - for path, mod_name in _install_cython_example(tmp_path_factory, True): + for path, mod_name, xc in _install_cython_example(tmp_path_factory, True): reload(import_module('site')) - yield (path, import_module(mod_name)) + yield (path, import_module(mod_name), xc) -def test_recover_cython_source(cython_example: Tuple[Path, str]) -> None: +def test_recover_cython_source( + cython_example: Tuple[Path, ModuleType, Union[Exception, None]], +) -> None: """ Check that Cython sources are correctly located by `line_profiler._line_profiler.find_cython_source_file()` and `line_profiler.line_profiler.get_code_block()`. """ - expected_source, module = cython_example + expected_source, module, xc = cython_example + if xc is not None: + _handle_not_installed(xc) for func in module.cos, module.sin: source = find_cython_source_file(func) assert source @@ -104,7 +135,9 @@ def test_recover_cython_source(cython_example: Tuple[Path, str]) -> None: CANNOT_LINE_TRACE_CYTHON, reason='Cannot line-trace Cython code in version ' + '.'.join(str(v) for v in sys.version_info[:3])) -def test_profile_cython_source(cython_example: Tuple[Path, str]) -> None: +def test_profile_cython_source( + cython_example: Tuple[Path, ModuleType, Union[Exception, None]], +) -> None: """ Check that calls to Cython functions (built with the appropriate compile-time options) can be profiled. @@ -112,8 +145,11 @@ def test_profile_cython_source(cython_example: Tuple[Path, str]) -> None: prof_cos = LineProfiler() prof_sin = LineProfiler() - cos = prof_cos(cython_example[1].cos) - sin = prof_sin(cython_example[1].sin) + _, module, xc = cython_example + if xc is not None: + _handle_not_installed(xc) + cos = prof_cos(module.cos) + sin = prof_sin(module.sin) assert pytest.approx(cos(.125, 10)) == math.cos(.125) assert pytest.approx(sin(2.5, 3)) == 2.5 - 2.5 ** 3 / 6 + 2.5 ** 5 / 120 From 2f164910fca45ed7209331373c2f21713892e7ef Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Wed, 27 Aug 2025 12:26:12 +0200 Subject: [PATCH 15/23] Fixed attempted import on the failing path --- tests/test_cython.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/test_cython.py b/tests/test_cython.py index a007a334..f46a140f 100644 --- a/tests/test_cython.py +++ b/tests/test_cython.py @@ -106,8 +106,13 @@ def cython_example( # With editable installs, we need to refresh `sys.meta_path` before # the installed module is available for path, mod_name, xc in _install_cython_example(tmp_path_factory, True): - reload(import_module('site')) - yield (path, import_module(mod_name), xc) + if xc is None: + reload(import_module('site')) + yield (path, import_module(mod_name), xc) + else: + # Failure path, but instead of handling it within the + # module-wide fixture we defer it to the individual tests + yield (Path('.'), ModuleType(mod_name), xc) def test_recover_cython_source( From 3d47c9020dd92cb0ef52020bdab9e8bbcbaa2443 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Wed, 27 Aug 2025 12:42:38 +0200 Subject: [PATCH 16/23] Undo eda8d0b and f407d00, restoring the rest of the pipeline --- .github/workflows/tests.yml | 253 ++++++++++++++++++------------------ pyproject.toml | 9 +- 2 files changed, 125 insertions(+), 137 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0ec42764..a857b162 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -125,14 +125,13 @@ jobs: # the standard [tool.cibuildwheel] section in pyproject.toml and set # explicitly here. os: - # FIXME START: temporarily truncate pipeline to focus on - # 3.12 on Windows - # - ubuntu-latest - # - macOS-latest - # FIXME END + - ubuntu-latest + - macOS-latest - windows-latest # Since the oldest Python available on windows-11-arm on GitHub - # is 3.11.0, older wheels cannot be tested... so just skip them + # is 3.11.0 (see https://raw.githubusercontent.com/actions/\ + # python-versions/main/versions-manifest.json), older wheels + # cannot be tested... so just skip pre-building them cibw_skip: - '*-win32 cp39-win_arm64 cp310-win_arm64 cp313-musllinux_i686' arch: @@ -218,140 +217,134 @@ jobs: # Xcookie generates an explicit list of environments that will be used # for testing instead of using the more concise matrix notation. include: - # FIXME START - # - python-version: '3.8' - # install-extras: tests-strict,runtime-strict - # os: ubuntu-latest - # arch: auto - # - python-version: '3.8' - # install-extras: tests-strict,runtime-strict - # os: macOS-latest - # arch: auto - # - python-version: '3.8' - # install-extras: tests-strict,runtime-strict - # os: windows-latest - # arch: auto - # # Note: cibuildwheel can't target 3.8 on Window ARM64 - # - python-version: '3.13' - # install-extras: tests-strict,runtime-strict,optional-strict - # os: ubuntu-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests-strict,runtime-strict,optional-strict - # os: macOS-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests-strict,runtime-strict,optional-strict - # os: windows-latest - # arch: auto - # FIXME END + - python-version: '3.8' + install-extras: tests-strict,runtime-strict + os: ubuntu-latest + arch: auto + - python-version: '3.8' + install-extras: tests-strict,runtime-strict + os: macOS-latest + arch: auto + - python-version: '3.8' + install-extras: tests-strict,runtime-strict + os: windows-latest + arch: auto + # Note: cibuildwheel can't target 3.8 on Window ARM64 + - python-version: '3.13' + install-extras: tests-strict,runtime-strict,optional-strict + os: ubuntu-latest + arch: auto + - python-version: '3.13' + install-extras: tests-strict,runtime-strict,optional-strict + os: macOS-latest + arch: auto + - python-version: '3.13' + install-extras: tests-strict,runtime-strict,optional-strict + os: windows-latest + arch: auto - python-version: '3.13' install-extras: tests-strict,runtime-strict,optional-strict os: windows-11-arm arch: auto - # FIXME START - # - python-version: '3.13' - # install-extras: tests - # os: macOS-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests - # os: windows-latest - # arch: auto - # FIXME END + - python-version: '3.13' + install-extras: tests + os: macOS-latest + arch: auto + - python-version: '3.13' + install-extras: tests + os: windows-latest + arch: auto - python-version: '3.13' install-extras: tests os: windows-11-arm arch: auto - # FIXME START - # - python-version: '3.8' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.9' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.10' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.11' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.12' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: 3.14.0-rc.1 - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.8' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.9' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.10' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.11' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.12' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: 3.14.0-rc.1 - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.8' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: '3.9' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: '3.10' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: '3.11' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: '3.12' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: 3.14.0-rc.1 - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # FIXME END + - python-version: '3.8' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.9' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.10' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.11' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.12' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.13' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: 3.14.0-rc.1 + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.8' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.9' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.10' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.11' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.12' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.13' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: 3.14.0-rc.1 + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.8' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: '3.9' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: '3.10' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: '3.11' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: '3.12' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: '3.13' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: 3.14.0-rc.1 + install-extras: tests,optional + os: windows-latest + arch: auto # Again, cibuildwheel can't target 3.8 on Window ARM64, and # GitHub doesn't have anything below Python 3.11 on their ARM64 - # machines + # machines, so just test the built wheels from 3.11+ - python-version: '3.11' install-extras: tests,optional os: windows-11-arm diff --git a/pyproject.toml b/pyproject.toml index 3c733e69..52511799 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,10 +30,7 @@ omit =[ ] [tool.cibuildwheel] -# FIXME START -# build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" -build = "cp311-* cp312-* cp313-* cp314-*" -# FIXME END +build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" skip = ["*-win32", "cp313-musllinux_i686"] build-frontend = "build" build-verbosity = 1 @@ -44,9 +41,7 @@ test-extras = ["tests-strict", "runtime-strict"] [tool.cibuildwheel.macos] archs = ["x86_64", "universal2", "arm64"] [tool.cibuildwheel.windows] -# FIXME START -archs = ['ARM64'] -# FIXME END +archs = ['AMD64', 'ARM64'] [tool.mypy] From 072106d8a0412eeaeaab25479d7372940aceff80 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Fri, 29 Aug 2025 10:52:42 +0200 Subject: [PATCH 17/23] Temp: truncate pipeline to debug test on Win-ARM64 This reverts commit 3d47c9020dd92cb0ef52020bdab9e8bbcbaa2443. --- .github/workflows/tests.yml | 253 ++++++++++++++++++------------------ pyproject.toml | 9 +- 2 files changed, 137 insertions(+), 125 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a857b162..0ec42764 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -125,13 +125,14 @@ jobs: # the standard [tool.cibuildwheel] section in pyproject.toml and set # explicitly here. os: - - ubuntu-latest - - macOS-latest + # FIXME START: temporarily truncate pipeline to focus on + # 3.12 on Windows + # - ubuntu-latest + # - macOS-latest + # FIXME END - windows-latest # Since the oldest Python available on windows-11-arm on GitHub - # is 3.11.0 (see https://raw.githubusercontent.com/actions/\ - # python-versions/main/versions-manifest.json), older wheels - # cannot be tested... so just skip pre-building them + # is 3.11.0, older wheels cannot be tested... so just skip them cibw_skip: - '*-win32 cp39-win_arm64 cp310-win_arm64 cp313-musllinux_i686' arch: @@ -217,134 +218,140 @@ jobs: # Xcookie generates an explicit list of environments that will be used # for testing instead of using the more concise matrix notation. include: - - python-version: '3.8' - install-extras: tests-strict,runtime-strict - os: ubuntu-latest - arch: auto - - python-version: '3.8' - install-extras: tests-strict,runtime-strict - os: macOS-latest - arch: auto - - python-version: '3.8' - install-extras: tests-strict,runtime-strict - os: windows-latest - arch: auto - # Note: cibuildwheel can't target 3.8 on Window ARM64 - - python-version: '3.13' - install-extras: tests-strict,runtime-strict,optional-strict - os: ubuntu-latest - arch: auto - - python-version: '3.13' - install-extras: tests-strict,runtime-strict,optional-strict - os: macOS-latest - arch: auto - - python-version: '3.13' - install-extras: tests-strict,runtime-strict,optional-strict - os: windows-latest - arch: auto + # FIXME START + # - python-version: '3.8' + # install-extras: tests-strict,runtime-strict + # os: ubuntu-latest + # arch: auto + # - python-version: '3.8' + # install-extras: tests-strict,runtime-strict + # os: macOS-latest + # arch: auto + # - python-version: '3.8' + # install-extras: tests-strict,runtime-strict + # os: windows-latest + # arch: auto + # # Note: cibuildwheel can't target 3.8 on Window ARM64 + # - python-version: '3.13' + # install-extras: tests-strict,runtime-strict,optional-strict + # os: ubuntu-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests-strict,runtime-strict,optional-strict + # os: macOS-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests-strict,runtime-strict,optional-strict + # os: windows-latest + # arch: auto + # FIXME END - python-version: '3.13' install-extras: tests-strict,runtime-strict,optional-strict os: windows-11-arm arch: auto - - python-version: '3.13' - install-extras: tests - os: macOS-latest - arch: auto - - python-version: '3.13' - install-extras: tests - os: windows-latest - arch: auto + # FIXME START + # - python-version: '3.13' + # install-extras: tests + # os: macOS-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests + # os: windows-latest + # arch: auto + # FIXME END - python-version: '3.13' install-extras: tests os: windows-11-arm arch: auto - - python-version: '3.8' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.9' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.10' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.11' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.12' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.13' - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: 3.14.0-rc.1 - install-extras: tests,optional - os: ubuntu-latest - arch: auto - - python-version: '3.8' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.9' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.10' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.11' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.12' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.13' - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: 3.14.0-rc.1 - install-extras: tests,optional - os: macOS-latest - arch: auto - - python-version: '3.8' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: '3.9' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: '3.10' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: '3.11' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: '3.12' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: '3.13' - install-extras: tests,optional - os: windows-latest - arch: auto - - python-version: 3.14.0-rc.1 - install-extras: tests,optional - os: windows-latest - arch: auto + # FIXME START + # - python-version: '3.8' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.9' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.10' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.11' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.12' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: 3.14.0-rc.1 + # install-extras: tests,optional + # os: ubuntu-latest + # arch: auto + # - python-version: '3.8' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.9' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.10' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.11' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.12' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: 3.14.0-rc.1 + # install-extras: tests,optional + # os: macOS-latest + # arch: auto + # - python-version: '3.8' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: '3.9' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: '3.10' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: '3.11' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: '3.12' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: '3.13' + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # - python-version: 3.14.0-rc.1 + # install-extras: tests,optional + # os: windows-latest + # arch: auto + # FIXME END # Again, cibuildwheel can't target 3.8 on Window ARM64, and # GitHub doesn't have anything below Python 3.11 on their ARM64 - # machines, so just test the built wheels from 3.11+ + # machines - python-version: '3.11' install-extras: tests,optional os: windows-11-arm diff --git a/pyproject.toml b/pyproject.toml index 52511799..3c733e69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,10 @@ omit =[ ] [tool.cibuildwheel] -build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" +# FIXME START +# build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" +build = "cp311-* cp312-* cp313-* cp314-*" +# FIXME END skip = ["*-win32", "cp313-musllinux_i686"] build-frontend = "build" build-verbosity = 1 @@ -41,7 +44,9 @@ test-extras = ["tests-strict", "runtime-strict"] [tool.cibuildwheel.macos] archs = ["x86_64", "universal2", "arm64"] [tool.cibuildwheel.windows] -archs = ['AMD64', 'ARM64'] +# FIXME START +archs = ['ARM64'] +# FIXME END [tool.mypy] From 8cce6367b126bb6307eab138753037820058f6a9 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Fri, 29 Aug 2025 11:36:56 +0200 Subject: [PATCH 18/23] Set MSVC arch for ARM runners --- .github/workflows/tests.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0ec42764..4164033c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -374,6 +374,11 @@ jobs: - name: Enable MSVC 64bit uses: ilammy/msvc-dev-cmd@v1 if: ${{ startsWith(matrix.os, 'windows-') }} + # Note: as noted in msvc-dev-cmd #90 (and the Action docs), it + # currently assumes `arch=x64`, so we have to manually set it + # here... + with: + arch: ${{ contains(matrix.os, 'arm') && 'arm64' || 'x64' }} - name: Set up QEMU uses: docker/setup-qemu-action@v3.0.0 if: runner.os == 'Linux' && matrix.arch != 'auto' From 3d7455f15369db3254c2532897c508f678d9d5a2 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Fri, 29 Aug 2025 11:49:41 +0200 Subject: [PATCH 19/23] Revert soft-XFAIL of Cython test This partially reverts commit 0a16f5c120078c6317213c79c8c3851f686a7abb but keeps the typing fixes introduced therein. --- tests/test_cython.py | 64 +++++++++----------------------------------- 1 file changed, 13 insertions(+), 51 deletions(-) diff --git a/tests/test_cython.py b/tests/test_cython.py index f46a140f..d54e997d 100644 --- a/tests/test_cython.py +++ b/tests/test_cython.py @@ -10,9 +10,8 @@ from io import StringIO from operator import methodcaller from pathlib import Path -from platform import machine, system from types import ModuleType -from typing import Generator, Tuple, Union +from typing import Generator, Tuple from uuid import uuid4 import pytest @@ -29,8 +28,8 @@ def propose_name(prefix: str) -> Generator[str, None, None]: def _install_cython_example( - tmp_path_factory: pytest.TempPathFactory, editable: bool, -) -> Generator[Tuple[Path, str, Union[Exception, None]], None, None]: + tmp_path_factory: pytest.TempPathFactory, + editable: bool) -> Generator[Tuple[Path, str], None, None]: """ Install the example Cython module in a name-clash-free manner. """ @@ -63,69 +62,36 @@ def _install_cython_example( else: pip_install.append(str(tmp_path)) try: - xc: Union[Exception, None] = None - try: - subprocess.run(pip_install).check_returncode() - except Exception as e: - xc = e + subprocess.run(pip_install).check_returncode() subprocess.run(pip + ['list']).check_returncode() - yield cython_source, module, xc + yield cython_source, module finally: pip_uninstall = pip + ['uninstall', '--verbose', '--yes', module] subprocess.run(pip_uninstall).check_returncode() -def _handle_not_installed(xc: Exception): - # FIXME: installation of the Cython package doesn't seem to work on - # Windows-ARM64. Not sure if it's the editable install that is - # problematic, or the package setup, or Cython itself. - # For now we just XFAIL if: - # - We're on Windows-ARM64, and - # - The `pip install` subprocess failed with a - # `subprocess.CalledProcessError`. - # Otherwise, re-raise the exception. - if ( - 'arm' in machine().lower() - and system().lower() == 'windows' - and isinstance(xc, subprocess.CalledProcessError)): - pytest.xfail('installation of the test Cython package ' - 'known to be faulty on Windows-ARM64; ' - 'exact cause unknown') - else: - raise xc - - @pytest.fixture(scope='module') def cython_example( tmp_path_factory: pytest.TempPathFactory, -) -> Generator[Tuple[Path, ModuleType, Union[Exception, None]], None, None]: +) -> Generator[Tuple[Path, ModuleType], None, None]: """ Install the example Cython module, yield the path to the Cython source file and the corresponding module, uninstall it at teardown. """ # With editable installs, we need to refresh `sys.meta_path` before # the installed module is available - for path, mod_name, xc in _install_cython_example(tmp_path_factory, True): - if xc is None: - reload(import_module('site')) - yield (path, import_module(mod_name), xc) - else: - # Failure path, but instead of handling it within the - # module-wide fixture we defer it to the individual tests - yield (Path('.'), ModuleType(mod_name), xc) + for path, mod_name in _install_cython_example(tmp_path_factory, True): + reload(import_module('site')) + yield (path, import_module(mod_name)) -def test_recover_cython_source( - cython_example: Tuple[Path, ModuleType, Union[Exception, None]], -) -> None: +def test_recover_cython_source(cython_example: Tuple[Path, ModuleType]) -> None: """ Check that Cython sources are correctly located by `line_profiler._line_profiler.find_cython_source_file()` and `line_profiler.line_profiler.get_code_block()`. """ - expected_source, module, xc = cython_example - if xc is not None: - _handle_not_installed(xc) + expected_source, module = cython_example for func in module.cos, module.sin: source = find_cython_source_file(func) assert source @@ -140,9 +106,7 @@ def test_recover_cython_source( CANNOT_LINE_TRACE_CYTHON, reason='Cannot line-trace Cython code in version ' + '.'.join(str(v) for v in sys.version_info[:3])) -def test_profile_cython_source( - cython_example: Tuple[Path, ModuleType, Union[Exception, None]], -) -> None: +def test_profile_cython_source(cython_example: Tuple[Path, ModuleType]) -> None: """ Check that calls to Cython functions (built with the appropriate compile-time options) can be profiled. @@ -150,9 +114,7 @@ def test_profile_cython_source( prof_cos = LineProfiler() prof_sin = LineProfiler() - _, module, xc = cython_example - if xc is not None: - _handle_not_installed(xc) + _, module = cython_example cos = prof_cos(module.cos) sin = prof_sin(module.sin) assert pytest.approx(cos(.125, 10)) == math.cos(.125) From 1f5384517c02f84501ffccfa3fc3da292a551901 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Fri, 29 Aug 2025 11:51:58 +0200 Subject: [PATCH 20/23] Un-truncate pipeline This reverts commit 072106d8a0412eeaeaab25479d7372940aceff80. --- .github/workflows/tests.yml | 253 ++++++++++++++++++------------------ pyproject.toml | 9 +- 2 files changed, 125 insertions(+), 137 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4164033c..994cbca2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -125,14 +125,13 @@ jobs: # the standard [tool.cibuildwheel] section in pyproject.toml and set # explicitly here. os: - # FIXME START: temporarily truncate pipeline to focus on - # 3.12 on Windows - # - ubuntu-latest - # - macOS-latest - # FIXME END + - ubuntu-latest + - macOS-latest - windows-latest # Since the oldest Python available on windows-11-arm on GitHub - # is 3.11.0, older wheels cannot be tested... so just skip them + # is 3.11.0 (see https://raw.githubusercontent.com/actions/\ + # python-versions/main/versions-manifest.json), older wheels + # cannot be tested... so just skip pre-building them cibw_skip: - '*-win32 cp39-win_arm64 cp310-win_arm64 cp313-musllinux_i686' arch: @@ -218,140 +217,134 @@ jobs: # Xcookie generates an explicit list of environments that will be used # for testing instead of using the more concise matrix notation. include: - # FIXME START - # - python-version: '3.8' - # install-extras: tests-strict,runtime-strict - # os: ubuntu-latest - # arch: auto - # - python-version: '3.8' - # install-extras: tests-strict,runtime-strict - # os: macOS-latest - # arch: auto - # - python-version: '3.8' - # install-extras: tests-strict,runtime-strict - # os: windows-latest - # arch: auto - # # Note: cibuildwheel can't target 3.8 on Window ARM64 - # - python-version: '3.13' - # install-extras: tests-strict,runtime-strict,optional-strict - # os: ubuntu-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests-strict,runtime-strict,optional-strict - # os: macOS-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests-strict,runtime-strict,optional-strict - # os: windows-latest - # arch: auto - # FIXME END + - python-version: '3.8' + install-extras: tests-strict,runtime-strict + os: ubuntu-latest + arch: auto + - python-version: '3.8' + install-extras: tests-strict,runtime-strict + os: macOS-latest + arch: auto + - python-version: '3.8' + install-extras: tests-strict,runtime-strict + os: windows-latest + arch: auto + # Note: cibuildwheel can't target 3.8 on Window ARM64 + - python-version: '3.13' + install-extras: tests-strict,runtime-strict,optional-strict + os: ubuntu-latest + arch: auto + - python-version: '3.13' + install-extras: tests-strict,runtime-strict,optional-strict + os: macOS-latest + arch: auto + - python-version: '3.13' + install-extras: tests-strict,runtime-strict,optional-strict + os: windows-latest + arch: auto - python-version: '3.13' install-extras: tests-strict,runtime-strict,optional-strict os: windows-11-arm arch: auto - # FIXME START - # - python-version: '3.13' - # install-extras: tests - # os: macOS-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests - # os: windows-latest - # arch: auto - # FIXME END + - python-version: '3.13' + install-extras: tests + os: macOS-latest + arch: auto + - python-version: '3.13' + install-extras: tests + os: windows-latest + arch: auto - python-version: '3.13' install-extras: tests os: windows-11-arm arch: auto - # FIXME START - # - python-version: '3.8' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.9' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.10' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.11' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.12' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: 3.14.0-rc.1 - # install-extras: tests,optional - # os: ubuntu-latest - # arch: auto - # - python-version: '3.8' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.9' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.10' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.11' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.12' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: 3.14.0-rc.1 - # install-extras: tests,optional - # os: macOS-latest - # arch: auto - # - python-version: '3.8' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: '3.9' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: '3.10' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: '3.11' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: '3.12' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: '3.13' - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # - python-version: 3.14.0-rc.1 - # install-extras: tests,optional - # os: windows-latest - # arch: auto - # FIXME END + - python-version: '3.8' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.9' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.10' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.11' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.12' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.13' + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: 3.14.0-rc.1 + install-extras: tests,optional + os: ubuntu-latest + arch: auto + - python-version: '3.8' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.9' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.10' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.11' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.12' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.13' + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: 3.14.0-rc.1 + install-extras: tests,optional + os: macOS-latest + arch: auto + - python-version: '3.8' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: '3.9' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: '3.10' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: '3.11' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: '3.12' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: '3.13' + install-extras: tests,optional + os: windows-latest + arch: auto + - python-version: 3.14.0-rc.1 + install-extras: tests,optional + os: windows-latest + arch: auto # Again, cibuildwheel can't target 3.8 on Window ARM64, and # GitHub doesn't have anything below Python 3.11 on their ARM64 - # machines + # machines, so just test the built wheels from 3.11+ - python-version: '3.11' install-extras: tests,optional os: windows-11-arm diff --git a/pyproject.toml b/pyproject.toml index 3c733e69..52511799 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,10 +30,7 @@ omit =[ ] [tool.cibuildwheel] -# FIXME START -# build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" -build = "cp311-* cp312-* cp313-* cp314-*" -# FIXME END +build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" skip = ["*-win32", "cp313-musllinux_i686"] build-frontend = "build" build-verbosity = 1 @@ -44,9 +41,7 @@ test-extras = ["tests-strict", "runtime-strict"] [tool.cibuildwheel.macos] archs = ["x86_64", "universal2", "arm64"] [tool.cibuildwheel.windows] -# FIXME START -archs = ['ARM64'] -# FIXME END +archs = ['AMD64', 'ARM64'] [tool.mypy] From b09acfa219d0c511d888399b03e406c75bf55926 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Fri, 29 Aug 2025 12:04:02 +0200 Subject: [PATCH 21/23] Streamline pipeline, added comments --- .github/workflows/tests.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 994cbca2..bd733c40 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -133,7 +133,7 @@ jobs: # python-versions/main/versions-manifest.json), older wheels # cannot be tested... so just skip pre-building them cibw_skip: - - '*-win32 cp39-win_arm64 cp310-win_arm64 cp313-musllinux_i686' + - '*-win32 cp3{9,10}-win_arm64 cp313-musllinux_i686' arch: - auto steps: @@ -154,9 +154,16 @@ jobs: config-file: pyproject.toml env: CIBW_SKIP: ${{ matrix.cibw_skip }} + # We're building on Windows-x64, so ARM64 wheels can't be tested + # locally by `cibuildwheel` (don't worry, we're testing them + # later though in `test_binpy_wheels`) + CIBW_TEST_SKIP: '*-win_arm64' CIBW_ARCHS_LINUX: ${{ matrix.arch }} CIBW_ENVIRONMENT: PYTHONUTF8=1 PYTHONUTF8: '1' + # `msvc-dev-cmd` sets this envvar, which intereferes with + # cross-architecture building... + # just let `cibuildwheel` handle that VSCMD_ARG_TGT_ARCH: '' - name: Show built files shell: bash @@ -367,9 +374,8 @@ jobs: - name: Enable MSVC 64bit uses: ilammy/msvc-dev-cmd@v1 if: ${{ startsWith(matrix.os, 'windows-') }} - # Note: as noted in msvc-dev-cmd #90 (and the Action docs), it - # currently assumes `arch=x64`, so we have to manually set it - # here... + # As noted in msvc-dev-cmd #90 (and the Action docs), it currently + # # assumes `arch=x64`, so we have to manually set it here... with: arch: ${{ contains(matrix.os, 'arm') && 'arm64' || 'x64' }} - name: Set up QEMU From a1ce3390da1ecb009d8ff0618e6940c5c8b210dd Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Fri, 29 Aug 2025 12:06:00 +0200 Subject: [PATCH 22/23] changelog --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e41e5c6b..f8be9b28 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,6 +10,7 @@ Changes * FIX: ref-count leaks #372 * FIX: mitigate speed regressions introduced in 5.0.0 #376 * FIX: Use import system to locate module file run by ``kernprof -m`` #389 +* FIX: Fixed build on Windows-ARM64 and now building wheels therefor in CI #391 5.0.0 ~~~~~ From 95063ef40feeaeebbbaa69d1387c81580d6fcdb0 Mon Sep 17 00:00:00 2001 From: "Terence S.-C. Tsang" Date: Thu, 9 Oct 2025 01:30:09 +0200 Subject: [PATCH 23/23] Make suggested changes Co-authored-by: Jon Crall --- .github/workflows/tests.yml | 2 +- line_profiler/c_trace_callbacks.h | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bd733c40..0bd8ef3e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -161,7 +161,7 @@ jobs: CIBW_ARCHS_LINUX: ${{ matrix.arch }} CIBW_ENVIRONMENT: PYTHONUTF8=1 PYTHONUTF8: '1' - # `msvc-dev-cmd` sets this envvar, which intereferes with + # `msvc-dev-cmd` sets this envvar, which interferes with # cross-architecture building... # just let `cibuildwheel` handle that VSCMD_ARG_TGT_ARCH: '' diff --git a/line_profiler/c_trace_callbacks.h b/line_profiler/c_trace_callbacks.h index 18584d8d..ce221020 100644 --- a/line_profiler/c_trace_callbacks.h +++ b/line_profiler/c_trace_callbacks.h @@ -45,9 +45,27 @@ typedef struct _Py_atomic_int { volatile int _value; } _Py_atomic_int; -# define _Py_atomic_load_relaxed(foo) (0) -# define _Py_atomic_store_relaxed(foo, bar) (0) -# include "internal/pycore_interp.h" + /* Stub out macros in `pycore_atomic.h` used in macros in + * `pycore_interp.h` (which aren't related to the + * `struct _is` we need). + * If any stub is referenced, fail the build with an + * unresolved external. + * This ensures we never ship wheels that "use" these + * placeholders. */ +# ifdef _MSC_VER + __declspec(dllimport) void lp_link_error__stubbed_cpython_atomic_LOAD_relaxed_was_used_this_is_a_bug(void); + __declspec(dllimport) void lp_link_error__stubbed_cpython_atomic_STORE_relaxed_was_used_this_is_a_bug(void); +# else + extern void lp_link_error__stubbed_cpython_atomic_LOAD_relaxed_was_used_this_is_a_bug(void); + extern void lp_link_error__stubbed_cpython_atomic_STORE_relaxed_was_used_this_is_a_bug(void); +# endif +# define _LP_ATOMIC_PANIC_LOAD_EXPR() (lp_link_error__stubbed_cpython_atomic_LOAD_relaxed_was_used_this_is_a_bug(), 0) +# define _LP_ATOMIC_PANIC_STORE_STMT() do { lp_link_error__stubbed_cpython_atomic_STORE_relaxed_was_used_this_is_a_bug(); } while (0) + // Panic-on-use shims (expression/statement forms) +# undef _Py_atomic_load_relaxed +# undef _Py_atomic_store_relaxed +# define _Py_atomic_load_relaxed(obj) ((void)(obj), _LP_ATOMIC_PANIC_LOAD_EXPR()) +# define _Py_atomic_store_relaxed(obj, val) do { (void)(obj); (void)(val); _LP_ATOMIC_PANIC_STORE_STMT(); } while (0) # endif # endif # include "internal/pycore_interp.h"