Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 38 additions & 16 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Set up Python 3.13 for linting
uses: actions/setup-python@v5.1.1
uses: actions/setup-python@v5.6.0
with:
python-version: '3.13'
- name: Install dependencies
Expand All @@ -49,9 +49,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Set up Python 3.13
uses: actions/setup-python@v5.1.1
uses: actions/setup-python@v5.6.0
with:
python-version: '3.13'
- name: Upgrade pip
Expand All @@ -71,6 +71,11 @@ jobs:
ls -al wheelhouse
python -m uv pip install wheelhouse/line_profiler*.tar.gz -v
- name: Test minimal loose sdist
env:
# So far not needed, but once we bump to 3.14 this needs to be
# set whenever `pytest` is run with `coverage`
# (see the `test_binpy_wheels` jobs)
COVERAGE_CORE: ctrace
run: |-
pwd
ls -al
Expand All @@ -85,6 +90,8 @@ jobs:
python -m pytest --verbose --cov=line_profiler $MOD_DPATH ../tests
cd ..
- name: Test full loose sdist
env:
COVERAGE_CORE: ctrace
run: |-
pwd
ls -al
Expand Down Expand Up @@ -130,7 +137,7 @@ jobs:
- auto
steps:
- name: Checkout source
uses: actions/checkout@v4.1.1
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') }}
Expand All @@ -140,7 +147,7 @@ jobs:
with:
platforms: all
- name: Build binary wheels
uses: pypa/cibuildwheel@v2.21.0
uses: pypa/cibuildwheel@v3.1.2
with:
output-dir: wheelhouse
config-file: pyproject.toml
Expand All @@ -153,7 +160,7 @@ jobs:
shell: bash
run: ls -la wheelhouse
- name: Set up Python 3.13 to combine coverage
uses: actions/setup-python@v5.1.1
uses: actions/setup-python@v5.6.0
if: runner.os == 'Linux'
with:
python-version: '3.13'
Expand All @@ -172,7 +179,7 @@ jobs:
echo '### The cwd should now have a coverage.xml'
ls -altr
pwd
- uses: codecov/codecov-action@v4.5.0
- uses: codecov/codecov-action@v5.4.3
name: Codecov Upload
env:
HAVE_CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN != '' }}
Expand All @@ -181,7 +188,7 @@ jobs:
with:
file: ./coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
- uses: codecov/codecov-action@v4.5.0
- uses: codecov/codecov-action@v5.4.3
name: Codecov Upload
with:
file: ./coverage.xml
Expand Down Expand Up @@ -264,6 +271,10 @@ jobs:
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
Expand All @@ -288,6 +299,10 @@ jobs:
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
Expand All @@ -312,9 +327,13 @@ jobs:
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
steps:
- name: Checkout source
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Enable MSVC 64bit
uses: ilammy/msvc-dev-cmd@v1
if: matrix.os == 'windows-latest'
Expand All @@ -324,7 +343,7 @@ jobs:
with:
platforms: all
- name: Setup Python
uses: actions/setup-python@v5.1.1
uses: actions/setup-python@v5.6.0
with:
python-version: ${{ matrix.python-version }}
- uses: actions/download-artifact@v4.1.8
Expand Down Expand Up @@ -354,9 +373,11 @@ jobs:
")
export MOD_VERSION=$(python -c "if 1:
from pkginfo import Wheel, SDist
import pathlib
fpath = '$WHEEL_FPATH'
cls = Wheel if fpath.endswith('.whl') else SDist
print(cls(fpath).version)
item = cls(fpath)
print(item.version)
")
echo "WHEEL_FPATH=$WHEEL_FPATH"
echo "INSTALL_EXTRAS=$INSTALL_EXTRAS"
Expand All @@ -367,6 +388,7 @@ jobs:
shell: bash
env:
CI_PYTHON_VERSION: py${{ matrix.python-version }}
COVERAGE_CORE: ctrace
run: |-
echo "Creating test sandbox directory"
export WORKSPACE_DNAME="testdir_${CI_PYTHON_VERSION}_${GITHUB_RUN_ID}_${RUNNER_OS}"
Expand Down Expand Up @@ -409,7 +431,7 @@ jobs:
echo '### The cwd should now have a coverage.xml'
ls -altr
pwd
- uses: codecov/codecov-action@v4.5.0
- uses: codecov/codecov-action@v5.4.3
name: Codecov Upload
with:
file: ./coverage.xml
Expand All @@ -423,7 +445,7 @@ jobs:
- build_binpy_wheels
steps:
- name: Checkout source
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- uses: actions/download-artifact@v4.1.8
name: Download wheels
with:
Expand Down Expand Up @@ -499,7 +521,7 @@ jobs:
- build_binpy_wheels
steps:
- name: Checkout source
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- uses: actions/download-artifact@v4.1.8
name: Download wheels
with:
Expand Down Expand Up @@ -576,7 +598,7 @@ jobs:
- live_deploy
steps:
- name: Checkout source
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- uses: actions/download-artifact@v4.1.8
name: Download artifacts
with:
Expand Down
2 changes: 1 addition & 1 deletion build_wheels.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ fi

#pip wheel -w wheelhouse .
# python -m build --wheel -o wheelhouse # line_profiler: +COMMENT_IF(binpy)
cibuildwheel --config-file pyproject.toml --platform linux --arch x86_64 # line_profiler: +UNCOMMENT_IF(binpy)
cibuildwheel --config-file pyproject.toml --platform linux --archs x86_64 # line_profiler: +UNCOMMENT_IF(binpy)
6 changes: 4 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@

# need to edit the conf.py

# Remove any old auto docs folder and regenerate it.
rm -rf ~/code/line_profiler/docs/source/auto
cd ~/code/line_profiler/docs
sphinx-apidoc --private --separate --force --output-dir ~/code/line_profiler/docs/source/auto ~/code/line_profiler/line_profiler
git add source/auto/*.rst

# Note: the module should importable before running this
# (e.g. install it in developer mode or munge the PYTHONPATH)
make html

git add source/auto/*.rst

Also:
To turn on PR checks

Expand Down Expand Up @@ -83,6 +84,7 @@
push events,
tag push events,
merge request events
release events

Click the "Add webhook" button.

Expand Down
64 changes: 47 additions & 17 deletions line_profiler/_line_profiler.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ cpdef _code_replace(func, co_code):
code = func.__func__.__code__
if hasattr(code, 'replace'):
# python 3.8+
code = code.replace(co_code=co_code)
code = _copy_local_sysmon_events(code, code.replace(co_code=co_code))
else:
# python <3.8
co = code
Expand All @@ -273,6 +273,30 @@ cpdef _code_replace(func, co_code):
return code


cpdef _copy_local_sysmon_events(old_code, new_code):
"""
Copy the local events from ``old_code`` over to ``new_code`` where
appropriate.

Returns:
code: ``new_code``
"""
try:
mon = sys.monitoring
except AttributeError: # Python < 3.12
return new_code
# Tool ids are integers in the range 0 to 5 inclusive.
# https://docs.python.org/3/library/sys.monitoring.html#tool-identifiers
NUM_TOOLS = 6
for tool_id in range(NUM_TOOLS):
try:
events = mon.get_local_events(tool_id, old_code)
mon.set_local_events(tool_id, new_code, events)
except ValueError: # Tool ID not in use
pass
return new_code


cpdef int _patch_events(int events, int before, int after):
"""
Patch ``events`` based on the differences between ``before`` and
Expand Down Expand Up @@ -370,22 +394,26 @@ cdef class _SysMonitoringState:
mon = sys.monitoring

# Set prior state
# Note: in 3.14.0a1+, calling `sys.monitoring.free_tool_id()`
# also calls `.clear_tool_id()`, causing existing callbacks and
# code-object-local events to be wiped... so don't call free.
# this does have the side effect of not overriding the active
# profiling tool name if one is already in use, but it's
# probably better this way
self.name = mon.get_tool(self.tool_id)
if self.name is None:
self.events = mon.events.NO_EVENTS
mon.use_tool_id(self.tool_id, 'line_profiler')
else:
self.events = mon.get_events(self.tool_id)
mon.free_tool_id(self.tool_id)
mon.use_tool_id(self.tool_id, 'line_profiler')
mon.set_events(self.tool_id, self.events | self.line_tracing_events)

# Register tracebacks
for event_id, callback in [
(mon.events.LINE, handle_line),
(mon.events.PY_RETURN, handle_return),
(mon.events.PY_YIELD, handle_yield),
(mon.events.RAISE, handle_raise),
(mon.events.RERAISE, handle_reraise)]:
# Register tracebacks and remember the existing ones
for event_id, callback in [(mon.events.LINE, handle_line),
(mon.events.PY_RETURN, handle_return),
(mon.events.PY_YIELD, handle_yield),
(mon.events.RAISE, handle_raise),
(mon.events.RERAISE, handle_reraise)]:
self.callbacks[event_id] = mon.register_callback(
self.tool_id, event_id, callback)

Expand All @@ -394,12 +422,11 @@ cdef class _SysMonitoringState:
cdef dict wrapped_callbacks = self.callbacks

# Restore prior state
mon.free_tool_id(self.tool_id)
if self.name is not None:
mon.use_tool_id(self.tool_id, self.name)
mon.set_events(self.tool_id, self.events)
self.name = None
self.events = mon.events.NO_EVENTS
mon.set_events(self.tool_id, self.events)
if self.name is None:
mon.free_tool_id(self.tool_id)
self.name = None
self.events = mon.events.NO_EVENTS

# Reset tracebacks
while wrapped_callbacks:
Expand Down Expand Up @@ -1118,7 +1145,7 @@ datamodel.html#user-defined-functions
# function (on some instance);
# (re-)pad with no-op
co_code = base_co_code + NOP_BYTES * npad
code = _code_replace(func, co_code=co_code)
code = _code_replace(func, co_code)
try:
func.__code__ = code
except AttributeError as e:
Expand Down Expand Up @@ -1155,6 +1182,9 @@ datamodel.html#user-defined-functions
code_hashes.append(code_hash)
# We can't replace the code object on Cython functions, but
# we can *store* a copy with the correct metadata
# Note: we don't use `_copy_local_sysmon_events()` here
# because Cython shim code objects don't support local
# events
code = code.replace(co_filename=cython_source)
profilers_to_update = {self}
# Update `._c_code_map` and `.code_hash_map` with the new line
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ omit =[
]

[tool.cibuildwheel]
build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-*"
build = "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*"
skip = ["*-win32", "cp313-musllinux_i686"]
build-frontend = "build"
build-verbosity = 1
Expand Down
8 changes: 4 additions & 4 deletions requirements/build.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ scikit-build>=0.11.1
cmake>=3.21.2
ninja>=1.10.2

cibuildwheel>=2.11.2 ; python_version < '4.0' and python_version >= '3.11' # Python 3.11+
cibuildwheel>=2.11.2 ; python_version < '3.11' and python_version >= '3.10' # Python 3.10
cibuildwheel>=2.11.2 ; python_version < '3.10' and python_version >= '3.9' # Python 3.9
cibuildwheel>=2.11.2 ; python_version < '3.9' and python_version >= '3.8' # Python 3.8
cibuildwheel>=3.1.2 ; python_version < '4.0' and python_version >= '3.11' # Python 3.11+
cibuildwheel>=3.1.2 ; python_version < '3.11' and python_version >= '3.10' # Python 3.10
cibuildwheel>=3.1.2 ; python_version < '3.10' and python_version >= '3.9' # Python 3.9
cibuildwheel>=3.1.2 ; python_version < '3.9' and python_version >= '3.8' # Python 3.8
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ def run_cythonize(force=False):
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Programming Language :: Python :: 3.14',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: Software Development',
]
Expand Down
Loading
Loading