Skip to content

Update trace from CPython 3.11.2 #4586

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 28, 2023
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
38 changes: 27 additions & 11 deletions Lib/test/test_trace.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import os
from pickle import dump
import sys
from test.support import captured_stdout
from test.support.os_helper import TESTFN, TESTFN_UNICODE, FS_NONASCII, rmtree, unlink
from test.support.os_helper import (TESTFN, rmtree, unlink)
from test.support.script_helper import assert_python_ok, assert_python_failure
import textwrap
import unittest
Expand All @@ -11,6 +12,11 @@

from test.tracedmodules import testmod

##
## See also test_sys_settrace.py, which contains tests that cover
## tracing of many more code blocks.
##

#------------------------------- Utilities -----------------------------------#

def fix_ext_py(filename):
Expand Down Expand Up @@ -191,7 +197,7 @@ def test_trace_list_comprehension(self):
firstlineno_called = get_firstlineno(traced_doubler)
expected = {
(self.my_py_filename, firstlineno_calling + 1): 1,
# List compehentions work differently in 3.x, so the count
# List comprehensions work differently in 3.x, so the count
# below changed compared to 2.x.
(self.my_py_filename, firstlineno_calling + 2): 12,
(self.my_py_filename, firstlineno_calling + 3): 1,
Expand All @@ -212,9 +218,9 @@ def test_traced_decorated_function(self):
(self.my_py_filename, firstlineno + 4): 1,
(self.my_py_filename, firstlineno + 5): 1,
(self.my_py_filename, firstlineno + 6): 1,
(self.my_py_filename, firstlineno + 7): 1,
(self.my_py_filename, firstlineno + 8): 1,
(self.my_py_filename, firstlineno + 9): 1,
(self.my_py_filename, firstlineno + 7): 2,
(self.my_py_filename, firstlineno + 8): 2,
(self.my_py_filename, firstlineno + 9): 2,
(self.my_py_filename, firstlineno + 10): 1,
(self.my_py_filename, firstlineno + 11): 1,
}
Expand Down Expand Up @@ -297,9 +303,8 @@ def test_simple_caller(self):
def test_arg_errors(self):
res = self.tracer.runfunc(traced_capturer, 1, 2, self=3, func=4)
self.assertEqual(res, ((1, 2), {'self': 3, 'func': 4}))
with self.assertWarns(DeprecationWarning):
res = self.tracer.runfunc(func=traced_capturer, arg=1)
self.assertEqual(res, ((), {'arg': 1}))
with self.assertRaises(TypeError):
self.tracer.runfunc(func=traced_capturer, arg=1)
with self.assertRaises(TypeError):
self.tracer.runfunc()

Expand Down Expand Up @@ -406,7 +411,7 @@ def test_coverage(self):

def test_coverage_ignore(self):
# Ignore all files, nothing should be traced nor printed
libpath = os.path.normpath(os.path.dirname(os.__file__))
libpath = os.path.normpath(os.path.dirname(os.path.dirname(__file__)))
# sys.prefix does not work when running from a checkout
tracer = trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix,
libpath], trace=0, count=1)
Expand Down Expand Up @@ -439,6 +444,15 @@ def test_issue9936(self):
self.assertIn(modname, coverage)
self.assertEqual(coverage[modname], (5, 100))

def test_coverageresults_update(self):
# Update empty CoverageResults with a non-empty infile.
infile = TESTFN + '-infile'
with open(infile, 'wb') as f:
dump(({}, {}, {'caller': 1}), f, protocol=1)
self.addCleanup(unlink, infile)
results = trace.CoverageResults({}, {}, infile, {})
self.assertEqual(results.callers, {'caller': 1})

### Tests that don't mess with sys.settrace and can be traced
### themselves TODO: Skip tests that do mess with sys.settrace when
### regrtest is invoked with -T option.
Expand Down Expand Up @@ -547,7 +561,8 @@ def test_sys_argv_list(self):
fd.write("print(type(sys.argv))\n")

status, direct_stdout, stderr = assert_python_ok(TESTFN)
status, trace_stdout, stderr = assert_python_ok('-m', 'trace', '-l', TESTFN)
status, trace_stdout, stderr = assert_python_ok('-m', 'trace', '-l', TESTFN,
PYTHONIOENCODING='utf-8')
self.assertIn(direct_stdout.strip(), trace_stdout)

# TODO: RUSTPYTHON
Expand All @@ -569,7 +584,8 @@ def f():
for i in range(10):
f()
"""))
status, stdout, _ = assert_python_ok('-m', 'trace', '-cs', filename)
status, stdout, _ = assert_python_ok('-m', 'trace', '-cs', filename,
PYTHONIOENCODING='utf-8')
stdout = stdout.decode()
self.assertEqual(status, 0)
self.assertIn('lines cov% module (path)', stdout)
Expand Down
22 changes: 3 additions & 19 deletions Lib/trace.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def names(self, filename, modulename):
return 0

def _modname(path):
"""Return a plausible module name for the patch."""
"""Return a plausible module name for the path."""

base = os.path.basename(path)
filename, ext = os.path.splitext(base)
Expand Down Expand Up @@ -172,7 +172,7 @@ def __init__(self, counts=None, calledfuncs=None, infile=None,
try:
with open(self.infile, 'rb') as f:
counts, calledfuncs, callers = pickle.load(f)
self.update(self.__class__(counts, calledfuncs, callers))
self.update(self.__class__(counts, calledfuncs, callers=callers))
except (OSError, EOFError, ValueError) as err:
print(("Skipping counts file %r: %s"
% (self.infile, err)), file=sys.stderr)
Expand Down Expand Up @@ -453,22 +453,7 @@ def runctx(self, cmd, globals=None, locals=None):
sys.settrace(None)
threading.settrace(None)

def runfunc(*args, **kw):
if len(args) >= 2:
self, func, *args = args
elif not args:
raise TypeError("descriptor 'runfunc' of 'Trace' object "
"needs an argument")
elif 'func' in kw:
func = kw.pop('func')
self, *args = args
import warnings
warnings.warn("Passing 'func' as keyword argument is deprecated",
DeprecationWarning, stacklevel=2)
else:
raise TypeError('runfunc expected at least 1 positional argument, '
'got %d' % (len(args)-1))

def runfunc(self, func, /, *args, **kw):
result = None
if not self.donothing:
sys.settrace(self.globaltrace)
Expand All @@ -478,7 +463,6 @@ def runfunc(*args, **kw):
if not self.donothing:
sys.settrace(None)
return result
runfunc.__text_signature__ = '($self, func, /, *args, **kw)'

def file_module_function_of(self, frame):
code = frame.f_code
Expand Down