Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Changes
* 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 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.

4.2.0
~~~~~
Expand Down
10 changes: 7 additions & 3 deletions line_profiler/_line_profiler.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,18 @@ else:

def label(code):
"""
Return a (filename, first_lineno, func_name) tuple for a given code object.
Return a (filename, first_lineno, qual_name) tuple for a given code object.
Comment thread
Erotemic marked this conversation as resolved.
Outdated

This is the same labelling as used by the cProfile module in Python 2.5.
This is the similar labelling as used by the cProfile module in Python 2.5.
"""
if isinstance(code, str):
return ('~', 0, code) # built-in functions ('~' sorts at the end)
else:
return (code.co_filename, code.co_firstlineno, code.co_name)
try:
Comment thread
Erotemic marked this conversation as resolved.
Outdated
# Python >=3.11a1
return (code.co_filename, code.co_firstlineno, code.co_qualname)
except AttributeError:
return (code.co_filename, code.co_firstlineno, code.co_name)


cpdef _code_replace(func, co_code):
Expand Down
15 changes: 7 additions & 8 deletions tests/test_line_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def foo(cls) -> str:
output = strip(sio.getvalue())
print(output)
# Check that we have profiled `Object.foo()`
assert output.endswith('- foo')
assert output.endswith('foo')
line, = (line for line in output.splitlines() if line.endswith('* 2'))
# Check that it has been run twice
assert int(line.split()[1]) == 2
Expand Down Expand Up @@ -291,7 +291,7 @@ def foo(x: int) -> int:
output = strip(sio.getvalue())
print(output)
# Check that we have profiled `Object.foo()`
assert output.endswith('- foo')
assert output.endswith('foo')
line, = (line for line in output.splitlines() if line.endswith('* 2'))
# Check that it has been run twice
assert int(line.split()[1]) == 2
Expand Down Expand Up @@ -332,7 +332,7 @@ def foo(self, x: int) -> int:
output = strip(sio.getvalue())
print(output)
# Check that we have profiled `Object.foo()`
assert output.endswith('- foo')
assert output.endswith('foo')
line, = (line for line in output.splitlines() if line.endswith('* x'))
# Check that the wrapped methods has been run twice in total
assert int(line.split()[1]) == 2
Expand Down Expand Up @@ -368,7 +368,7 @@ def foo(self, x: int) -> int:
output = strip(sio.getvalue())
print(output)
# Check that we have profiled `Object.foo()` (via `.bar()`)
assert output.endswith('- foo')
assert output.endswith('foo')
line, = (line for line in output.splitlines() if line.endswith('* x'))
# Check that the wrapped method has been run once
assert int(line.split()[1]) == 1
Expand Down Expand Up @@ -408,7 +408,7 @@ def foo(x: int, y: int) -> int:
output = strip(sio.getvalue())
print(output)
# Check that we have profiled `foo()`
assert output.endswith('- foo')
assert output.endswith('foo')
line, = (line for line in output.splitlines() if line.endswith('x + y'))
# Check that the wrapped partials has been run twice in total
assert int(line.split()[1]) == 2
Expand Down Expand Up @@ -457,7 +457,7 @@ def foo(self, foo) -> None:
output = strip(sio.getvalue())
print(output)
# Check that we have profiled `Object.foo`
assert output.endswith('- foo')
assert output.endswith('foo')
getter_line, = (line for line in output.splitlines()
if line.endswith('* 2'))
setter_line, = (line for line in output.splitlines()
Expand Down Expand Up @@ -498,9 +498,8 @@ def foo(self) -> int:
with io.StringIO() as sio:
profile.print_stats(stream=sio, summarize=True)
output = strip(sio.getvalue())
print(output)
# Check that we have profiled `Object.foo`
assert output.endswith('- foo')
assert output.endswith('foo')
line, = (line for line in output.splitlines() if line.endswith('* 2'))
# Check that the getter has been run once
assert int(line.split()[1]) == 1
Expand Down
Loading