Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
77e6bab
Basic TOML facilities
TTsangSC Apr 19, 2025
4afce8c
Packaging updates
TTsangSC Apr 19, 2025
db3e0b0
WIP: `kernprof` refactoring
TTsangSC Apr 19, 2025
0707290
`kernprof` refactoring (reading configs)
TTsangSC Apr 19, 2025
2bb5de0
Feature: read config file from the env
TTsangSC Apr 19, 2025
4c7a368
Reorganized code: `line_profiler.cli_utils`
TTsangSC Apr 19, 2025
71e1932
Made `line_profiler.line_profiler` configurable
TTsangSC Apr 19, 2025
e63cbe4
Refactored `line_profiler.toml_config`
TTsangSC Apr 19, 2025
6c27c45
Moved code around
TTsangSC Apr 19, 2025
c042e24
Made `.explicit_profiler` configurable
TTsangSC Apr 19, 2025
84649f2
TOML tests
TTsangSC Apr 19, 2025
4ca90af
Config test in `tests/test_explicit_profile.py`
TTsangSC Apr 19, 2025
7bed993
Config test in `tests/test_autoprofile.py`
TTsangSC Apr 19, 2025
0ad634c
Added changelog entry
TTsangSC Apr 19, 2025
35f8918
CI fixes
TTsangSC Apr 20, 2025
cf30d3f
`line_profiler_rc.toml` -> `line_profiler.toml`
TTsangSC May 3, 2025
39b6b46
Updated comments in TOML file
TTsangSC May 3, 2025
4430459
Reduce code run during import-time
TTsangSC May 3, 2025
bc0bf64
Added the `--no-config` flag
TTsangSC May 3, 2025
6f53cff
Centralized code for `config = <bool>`
TTsangSC May 4, 2025
0cd8581
Fixed MANIFEST
TTsangSC May 4, 2025
f005278
Better boolean-option parsing
TTsangSC May 7, 2025
9387cec
`line_profiler` minor refactoring
TTsangSC May 7, 2025
f2fa45d
Refactoring in `kernprof.py`
TTsangSC May 7, 2025
3e12ee8
Tests for `line_profiler.cli_utils.add_argument`
TTsangSC May 7, 2025
838069c
Lint
TTsangSC May 31, 2025
90d9603
Merge branch 'main' into toml-config
TTsangSC Jul 7, 2025
0622869
.
TTsangSC Jul 7, 2025
3c87e15
Bug fixes
TTsangSC Jul 7, 2025
f02b7f5
Merge branch 'main' into toml-config
TTsangSC Jul 18, 2025
8a7c935
Add example of using TOML config to docs
Erotemic Jul 20, 2025
5e34701
Fix malformed f-string
TTsangSC Jul 20, 2025
da1757e
Use `global` for accessing global vars
TTsangSC Jul 20, 2025
9f49928
format and install fixes
Erotemic Jul 21, 2025
f9d6007
small tweak
Erotemic Jul 21, 2025
f23afa1
Merge pull request #4 from Erotemic/toml-config-docs
TTsangSC Jul 21, 2025
01dfbd3
Refactoring of `line_profiler.toml_config`
TTsangSC Jul 21, 2025
f1c137d
Doc fixes
TTsangSC Jul 21, 2025
5ec16f9
CLI fixes
TTsangSC Jul 21, 2025
a7032a5
`kernprof` fixes
TTsangSC Jul 21, 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
7 changes: 6 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Changes
* FIX: Fixed explicit profiling of class methods; added handling for profiling static, bound, and partial methods, ``functools.partial`` objects, (cached) properties, and async generator functions
* FIX: Fixed namespace bug when running ``kernprof -m`` on certain modules (e.g. ``calendar`` on Python 3.12+).
* FIX: Fixed ``@contextlib.contextmanager`` bug where the cleanup code (e.g. restoration of ``sys`` attributes) is not run if exceptions occurred inside the context
* ENH: Added CLI arguments ``-c`` to ``kernprof`` for (auto-)profiling inline-script execution instead of that of script files; passing ``'-'`` as the script-file name now also reads from and profiles ``stdin``
* ENH: Added CLI arguments ``-c`` to ``kernprof`` for (auto-)profiling module/package/inline-script execution instead of that of script files; passing ``'-'`` as the script-file name now also reads from and profiles ``stdin``
* ENH: In Python >=3.11, profiled objects are reported using their qualified name.
* ENH: Highlight final summary using rich if enabled
* ENH: Made it possible to use multiple profiler instances simultaneously
Expand Down Expand Up @@ -43,6 +43,11 @@ Changes
callbacks during profiling
* Now allowing switching back to the "legacy" trace system on Python 3.12+,
controlled by an environment variable
* ENH: Added capability to parse TOML config files for defaults (#335):

* ``kernprof`` and ``python -m line_profiler`` CLI options
* ``GlobalProfiler`` configurations, and
* profiler output (e.g. ``LineProfiler.print_stats()``) formatting

4.2.0
~~~~~
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
graft line_profiler/rc
include *.md
include *.rst
include *.py
Expand Down
7 changes: 7 additions & 0 deletions docs/source/auto/line_profiler.cli_utils.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
line\_profiler.cli\_utils module
================================

.. automodule:: line_profiler.cli_utils
:members:
:undoc-members:
:show-inheritance:
2 changes: 2 additions & 0 deletions docs/source/auto/line_profiler.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ Submodules

line_profiler.__main__
line_profiler._line_profiler
line_profiler.cli_utils
line_profiler.explicit_profiler
line_profiler.ipython_extension
line_profiler.line_profiler
line_profiler.profiler_mixin
line_profiler.scoping_policy
line_profiler.toml_config

Module contents
---------------
Expand Down
7 changes: 7 additions & 0 deletions docs/source/auto/line_profiler.toml_config.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
line\_profiler.toml\_config module
================================

.. automodule:: line_profiler.toml_config
:members:
:undoc-members:
:show-inheritance:
221 changes: 221 additions & 0 deletions docs/source/manual/examples/example_toml_config.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
Using the line-profiler TOML configuration
------------------------------------------

This tutorial walks the user through setting up a toy Python project and then
interacting with it via the new line-profiler TOML configuration.

First, we need to setup a small project, for which we will use ``uv``. We will
also use the ``tomlkit`` package to edit the config file programatically. If
you don't have these installed, first run:

.. code:: bash

pip install uv tomlkit


Next, we are going to setup a small package for this demonstration.

.. code:: bash

TEMP_DIR=$(mktemp -d --suffix=demo_pkg)
mkdir -p $TEMP_DIR
cd $TEMP_DIR

uv init --lib --name demo_pkg

# helper to prevent indentation errors
codeblock(){
echo "$1" | python -c "import sys; from textwrap import dedent; print(dedent(sys.stdin.read()).strip('\n'))"
}

codeblock "
import time
from demo_pkg.utils import leq
from demo_pkg import utils

def fib(n):
if leq(n, 1):
return n
part1 = fib(n - 1)
part2 = fib(n - 2)
result = utils.add(part1, part2)
return result

def sleep_loop(n):
for _ in range(n):
time.sleep(0.01)
" > src/demo_pkg/core.py

codeblock "
def leq(a, b):
return a <= b

def add(a, b):
return a + b
" > src/demo_pkg/utils.py

codeblock "
from demo_pkg import core
import uuid

def main():
run_uuid = uuid.uuid4()
print('The UUID of this run is', run_uuid)
print('compute fib 10')
result = core.fib(10)
print('result', result)
print('sleeping 5')
core.sleep_loop(5)
print('done')

if __name__ == '__main__':
main()
" > src/demo_pkg/__main__.py

# Run `uv pip install -e .` to install the project locally:
uv pip install -e .


Test that the main entrypoint works.

.. code:: bash

python -m demo_pkg


Running kernprof with a main script that uses your package behaves as in 4.x in that no defaults are modified.

.. code:: bash

kernprof -m demo_pkg


However, you can modify pyproject.toml to specify new defaults. After doing
this, running kernprof will use defaults specified in your pyproject.toml (You
may also pass ``--config`` to tell kernprof to use a different file to load the
default config).

.. code:: bash

# Edit the `pyproject.toml` file to modify default behavior
update_pyproject_toml(){
python -c "if 1:
import pathlib
import tomllib
import tomlkit
import sys
config_path = pathlib.Path('pyproject.toml')
config = tomllib.loads(config_path.read_text())

# Add in new values
from textwrap import dedent
new_text = dedent(sys.argv[1])

new_parts = tomllib.loads(new_text)
config.update(new_parts)

new_text = tomlkit.dumps(config)
config_path.write_text(new_text)
" "$1"
}

update_pyproject_toml "
# New Config
[tool.line_profiler.kernprof]
line-by-line = true
rich = true
verbose = true
skip-zero = true
prof-mod = ['demo_pkg']
"

# Now, running kernprof uses the new defaults
kernprof -m demo_pkg


You will now see how long each function took, and what the line-by line breakdown is

.. code::

# line-by-line breakdown omitted here

0.05 seconds - /tmp/tmp.vKpODQr6wndemo_pkg/src/demo_pkg/__main__.py:4 - main
0.00 seconds - /tmp/tmp.vKpODQr6wndemo_pkg/src/demo_pkg/core.py:5 - fib
0.05 seconds - /tmp/tmp.vKpODQr6wndemo_pkg/src/demo_pkg/core.py:13 - sleep_loop
0.00 seconds - /tmp/tmp.vKpODQr6wndemo_pkg/src/demo_pkg/utils.py:1 - leq
0.00 seconds - /tmp/tmp.vKpODQr6wndemo_pkg/src/demo_pkg/utils.py:4 - add


Note that by specifying ``prof-mod``, every function within the package is
automatically profiled without any need for the ``@profile`` decorator.

It is worth noting, there is no requirement that the module you are profiling
is part of your package. You can specify any module name as part of
``prof-mod``. For example, lets profile the stdlib uuid module.


.. code:: bash

update_pyproject_toml "
# New Config
[tool.line_profiler.kernprof]
line-by-line = true
rich = true
verbose = 0
skip-zero = true
prof-mod = ['uuid']
"

# Now, running kernprof uses the new defaults
kernprof -m demo_pkg
python -m line_profiler -rmtz demo_pkg.lprof


This results in only showing calls in the uuid package:

.. code::

# line-by-line breakdown omitted here

0.00 seconds - .pyenv/versions/3.13.2/lib/python3.13/uuid.py:142 - UUID.__init__
0.00 seconds - .pyenv/versions/3.13.2/lib/python3.13/uuid.py:283 - UUID.__str__
0.00 seconds - .pyenv/versions/3.13.2/lib/python3.13/uuid.py:277 - UUID.__repr__
0.00 seconds - .pyenv/versions/3.13.2/lib/python3.13/uuid.py:710 - uuid4


You can list exact functions to profile as long as they are addressable by
dotted names. The above only profiles the ``fib`` function in our package:

.. code:: bash

update_pyproject_toml "
# New Config
[tool.line_profiler.kernprof]
line-by-line = true
rich = true
verbose = 0
skip-zero = true
prof-mod = ['demo_pkg.core.fib']
"

# Now, running kernprof uses the new defaults
kernprof -m demo_pkg
python -m line_profiler -rmtz demo_pkg.lprof


The output is:

.. code::

Line # Hits Time Per Hit % Time Line Contents
==============================================================
5 def fib(n):
6 177 145.1 0.8 42.5 if leq(n, 1):
7 89 29.7 0.3 8.7 return n
8 88 29.1 0.3 8.5 part1 = fib(n - 1)
9 88 27.7 0.3 8.1 part2 = fib(n - 2)
10 88 78.0 0.9 22.8 result = utils.add(part1, part2)
11 88 32.2 0.4 9.4 return result


0.00 seconds - /tmp/tmp.vKpODQr6wndemo_pkg/src/demo_pkg/core.py:5 - fib
4 changes: 3 additions & 1 deletion docs/source/manual/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ Examples of line profiler usage:

+ `Basic Usage <../../index.html#line-profiler-basic-usage>`_

+ `kernprof invocations <example_kernprof.rst>`_
+ `Kernprof Usage <example_kernprof.rst>`_

+ `Auto Profiling <../../auto/line_profiler.autoprofile.html#auto-profiling>`_

+ `Explicit Profiler <../../auto/line_profiler.explicit_profiler.html#module-line_profiler.explicit_profiler>`_

+ `Timing Units <example_units.rst>`_

+ `TOML Config Usage <example_toml_config.rst>`_
Loading
Loading