Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fcd75ac
Narrow scopes where 3.12 hacks apply
TTsangSC Aug 17, 2025
4f13a9c
Update CI to target and test ARM64 Windows
TTsangSC Aug 17, 2025
3783b9f
Fixed expressions and unset ${VSCMD_ARG_TGT_ARCH}
TTsangSC Aug 17, 2025
1cc16ba
pre-include `pycore_atomic.h` to circumvent bad funcdefs
TTsangSC Aug 18, 2025
eda8d0b
temporarily truncate job matrix to focus on Windows-ARM64
TTsangSC Aug 18, 2025
87e7723
sidestep inclusion of `pycore_atomic.h`, just mock what we need
TTsangSC Aug 18, 2025
f407d00
temporarily stop building Windows-AMD64 and ABI3 wheels
TTsangSC Aug 18, 2025
9fc296a
Added missing #define
TTsangSC Aug 18, 2025
a974931
Try moving Python internal includes into the C file
da-woods Aug 18, 2025
6a89763
simplify macros
TTsangSC Aug 18, 2025
bf1f22f
roll back #392
TTsangSC Aug 22, 2025
57535cc
vendor in `_Py_atomic_int` from `pycore_atomic.h`
TTsangSC Aug 27, 2025
6f3a09e
Merge branch 'main' into win-arm64-fix
TTsangSC Aug 27, 2025
f51e8ba
Skip unavailable platforms in CI
TTsangSC Aug 27, 2025
0a16f5c
Allow Cython tests to XFAIL on Windows-ARM64
TTsangSC Aug 27, 2025
2f16491
Fixed attempted import on the failing path
TTsangSC Aug 27, 2025
3d47c90
Undo eda8d0b and f407d00, restoring the rest of the pipeline
TTsangSC Aug 27, 2025
072106d
Temp: truncate pipeline to debug test on Win-ARM64
TTsangSC Aug 29, 2025
8cce636
Set MSVC arch for ARM runners
TTsangSC Aug 29, 2025
3d7455f
Revert soft-XFAIL of Cython test
TTsangSC Aug 29, 2025
1f53845
Un-truncate pipeline
TTsangSC Aug 29, 2025
b09acfa
Streamline pipeline, added comments
TTsangSC Aug 29, 2025
a1ce339
changelog
TTsangSC Aug 29, 2025
95063ef
Make suggested changes
TTsangSC Oct 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,20 @@ jobs:
- ubuntu-latest
- macOS-latest
- 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
cibw_skip:
- '*-win32 *-win32 cp313-musllinux_i686'
- '*-win32 cp3{9,10}-win_arm64 cp313-musllinux_i686'
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' && ${{ 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'
Expand All @@ -150,9 +154,17 @@ 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 interferes with
# cross-architecture building...
# just let `cibuildwheel` handle that
VSCMD_ARG_TGT_ARCH: ''
- name: Show built files
shell: bash
run: ls -la wheelhouse
Expand Down Expand Up @@ -224,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
Expand All @@ -236,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
Expand All @@ -244,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
Expand Down Expand Up @@ -328,12 +349,35 @@ jobs:
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, so just test the built wheels from 3.11+
- 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-') }}
# 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'
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
~~~~~
Expand Down
52 changes: 43 additions & 9 deletions line_profiler/c_trace_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +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)
* - 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`, 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
Expand All @@ -24,17 +30,45 @@
# ifndef Py_BUILD_CORE
# define Py_BUILD_CORE 1
# endif
# ifdef _PyGC_FINALIZED
# 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
// 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;
/* 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
# 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"
# endif
# include "internal/pycore_interp.h"
#endif

typedef struct TraceCallback
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
15 changes: 9 additions & 6 deletions tests/test_cython.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

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]:
Expand Down Expand Up @@ -71,7 +72,8 @@ def _install_cython_example(

@pytest.fixture(scope='module')
def cython_example(
tmp_path_factory: pytest.TempPathFactory) -> Tuple[Path, ModuleType]:
tmp_path_factory: pytest.TempPathFactory,
) -> 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.
Expand All @@ -83,7 +85,7 @@ def cython_example(
yield (path, import_module(mod_name))


def test_recover_cython_source(cython_example: Tuple[Path, str]) -> 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
Expand All @@ -104,16 +106,17 @@ 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]) -> None:
"""
Check that calls to Cython functions (built with the appropriate
compile-time options) can be profiled.
"""
prof_cos = LineProfiler()
prof_sin = LineProfiler()

cos = prof_cos(cython_example[1].cos)
sin = prof_sin(cython_example[1].sin)
_, module = cython_example
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

Expand Down
Loading