Closed
Description
Bug report
runpy.run_path
will accept a Path
object, and run it, but various code inspection tools will be unhappy with it because it is not a string. Should run_path
convert its argument to a true string before execution?
Coverage.py is one of those tools; this report is based on nedbat/coveragepy#1417.
Create debugme.py:
from pathlib import Path
import runpy, sys
runme = Path(__file__).resolve().parent / sys.argv[1]
print(f"Running {runme!r}")
runpy.run_path(runme)
Create inspectme.py:
import inspect
print(inspect.stack())
print('here')
Run it:
% python3.12 debugme.py inspectme.py
Running PosixPath('/System/Volumes/Data/root/src/bugs/bug1417/inspectme.py')
Traceback (most recent call last):
File "/System/Volumes/Data/root/src/bugs/bug1417/debugme.py", line 6, in <module>
runpy.run_path(runme)
File "<frozen runpy>", line 291, in run_path
File "<frozen runpy>", line 98, in _run_module_code
File "<frozen runpy>", line 88, in _run_code
File "/System/Volumes/Data/root/src/bugs/bug1417/inspectme.py", line 3, in <module>
print(inspect.stack())
^^^^^^^^^^^^^^^
File "/usr/local/pyenv/pyenv/versions/3.12.0a1/lib/python3.12/inspect.py", line 1748, in stack
return getouterframes(sys._getframe(1), context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/pyenv/pyenv/versions/3.12.0a1/lib/python3.12/inspect.py", line 1723, in getouterframes
traceback_info = getframeinfo(frame, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/pyenv/pyenv/versions/3.12.0a1/lib/python3.12/inspect.py", line 1685, in getframeinfo
lines, lnum = findsource(frame)
^^^^^^^^^^^^^^^^^
File "/usr/local/pyenv/pyenv/versions/3.12.0a1/lib/python3.12/inspect.py", line 1060, in findsource
module = getmodule(object, file)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/pyenv/pyenv/versions/3.12.0a1/lib/python3.12/inspect.py", line 983, in getmodule
f = getabsfile(module)
^^^^^^^^^^^^^^^^^^
File "/usr/local/pyenv/pyenv/versions/3.12.0a1/lib/python3.12/inspect.py", line 952, in getabsfile
_filename = getsourcefile(object) or getfile(object)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/pyenv/pyenv/versions/3.12.0a1/lib/python3.12/inspect.py", line 928, in getsourcefile
if any(filename.endswith(s) for s in all_bytecode_suffixes):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/pyenv/pyenv/versions/3.12.0a1/lib/python3.12/inspect.py", line 928, in <genexpr>
if any(filename.endswith(s) for s in all_bytecode_suffixes):
^^^^^^^^^^^^^^^^^
AttributeError: 'PosixPath' object has no attribute 'endswith'
Coverage.py fails earlier, but for a similar reason:
% coverage run debugme.py inspectme.py
Running PosixPath('/System/Volumes/Data/root/src/bugs/bug1417/inspectme.py')
Traceback (most recent call last):
File "/System/Volumes/Data/root/src/bugs/bug1417/debugme.py", line 6, in <module>
runpy.run_path(runme)
File "/usr/local/pyenv/pyenv/versions/3.9.15/lib/python3.9/runpy.py", line 288, in run_path
return _run_module_code(code, init_globals, run_name,
File "/usr/local/pyenv/pyenv/versions/3.9.15/lib/python3.9/runpy.py", line 97, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "/usr/local/pyenv/pyenv/versions/3.9.15/lib/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/usr/local/virtualenvs/tmp-6c4153bbeaa11b2/lib/python3.9/site-packages/coverage/control.py", line 344, in _should_trace
disp = self._inorout.should_trace(filename, frame)
File "/usr/local/virtualenvs/tmp-6c4153bbeaa11b2/lib/python3.9/site-packages/coverage/inorout.py", line 335, in should_trace
filename = source_for_file(dunder_file)
File "/usr/local/virtualenvs/tmp-6c4153bbeaa11b2/lib/python3.9/site-packages/coverage/python.py", line 105, in source_for_file
if filename.endswith(".py"):
AttributeError: 'PosixPath' object has no attribute 'endswith'
Using coverage.py's --timid
flag uses a Python trace function and also shows the error:
% coverage run --timid debugme.py inspectme.py
Running PosixPath('/System/Volumes/Data/root/src/bugs/bug1417/inspectme.py')
Traceback (most recent call last):
File "/System/Volumes/Data/root/src/bugs/bug1417/debugme.py", line 6, in <module>
runpy.run_path(runme)
File "/usr/local/pyenv/pyenv/versions/3.9.15/lib/python3.9/runpy.py", line 288, in run_path
return _run_module_code(code, init_globals, run_name,
File "/usr/local/pyenv/pyenv/versions/3.9.15/lib/python3.9/runpy.py", line 97, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "/usr/local/pyenv/pyenv/versions/3.9.15/lib/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/System/Volumes/Data/root/src/bugs/bug1417/inspectme.py", line 1, in <module>
import inspect
File "/usr/local/virtualenvs/tmp-6c4153bbeaa11b2/lib/python3.9/site-packages/coverage/pytracer.py", line 166, in _trace
disp = self.should_trace(filename, frame)
File "/usr/local/virtualenvs/tmp-6c4153bbeaa11b2/lib/python3.9/site-packages/coverage/control.py", line 344, in _should_trace
disp = self._inorout.should_trace(filename, frame)
File "/usr/local/virtualenvs/tmp-6c4153bbeaa11b2/lib/python3.9/site-packages/coverage/inorout.py", line 335, in should_trace
filename = source_for_file(dunder_file)
File "/usr/local/virtualenvs/tmp-6c4153bbeaa11b2/lib/python3.9/site-packages/coverage/python.py", line 105, in source_for_file
if filename.endswith(".py"):
AttributeError: 'PosixPath' object has no attribute 'endswith'
I don't understand why a simpler trace example gets a string for co_filename? Create traceme.py:
import sys
def foo():
print("FOO")
def trace(frame, event, arg):
if "traceme" in str(frame.f_code.co_filename):
print(type(frame.f_code.co_filename))
print(f"{frame.f_code.co_filename=}")
sys.settrace(trace)
foo()
print('here')
and run it:
% python debugme.py traceme.py
Running PosixPath('/System/Volumes/Data/root/src/bugs/bug1417/traceme.py')
<class 'str'>
frame.f_code.co_filename='/System/Volumes/Data/root/src/bugs/bug1417/traceme.py'
FOO
here
Your environment
I'm on a Mac, and this behavior seems consistent on versions 3.7 through 3.12.0a1.