Skip to content

runpy.run_path mishandles Path objects #99437

Closed
@nedbat

Description

@nedbat

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.

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibPython modules in the Lib dirtopic-importlibtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions