Skip to content

Commit

Permalink
fix: runpy.run_path(path) crashes with pathlib.Path (#1819)
Browse files Browse the repository at this point in the history
* fix: runpy.run_path(path) crashes with pathlib.Path

* Revert "fix: runpy.run_path(path) crashes with pathlib.Path"

This reverts commit 2d1eabd.

* fix: runpy.run_path(path) crashes with pathlib.Path

* test: runpy.run_path(path) with being pathlib.Path

* finish up #1819

* test both str and Path

---------

Co-authored-by: Ned Batchelder <[email protected]>
  • Loading branch information
askhl and nedbat authored Jul 19, 2024
1 parent 1da3ee1 commit 7fb846e
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 2 deletions.
6 changes: 5 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ upgrading your version of coverage.py.
Unreleased
----------

Nothing yet.
- Fix: coverage used to fail when measuring code using :func:`runpy.run_path
<python:runpy.run_path>` with a :class:`Path <python:pathlib.Path>` argument.
This is now fixed, thanks to `Ask Hjorth Larsen <pull 1819_>`_.

.. _pull 1819: https://github.com/nedbat/coveragepy/pull/1819/files


.. scriv-start-here
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Artem Dayneko
Arthur Deygin
Arthur Rio
Asher Foa
Ask Hjorth Larsen
Ben Carlsson
Ben Finney
Benjamin Parzella
Expand Down
3 changes: 2 additions & 1 deletion coverage/inorout.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@ def nope(disp: TFileDisposition, reason: str) -> TFileDisposition:
# co_filename value.
dunder_file = frame.f_globals and frame.f_globals.get("__file__")
if dunder_file:
filename = source_for_file(dunder_file)
# Danger: __file__ can (rarely?) be of type Path.
filename = source_for_file(str(dunder_file))
if original_filename and not original_filename.startswith("<"):
orig = os.path.basename(original_filename)
if orig != os.path.basename(filename):
Expand Down
21 changes: 21 additions & 0 deletions tests/test_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,24 @@ def test_source_for_file_windows(tmp_path: pathlib.Path) -> None:
# If both pyw and py exist, py is preferred
a_py.write_text("")
assert source_for_file(src + 'c') == src


class RunpyTest(CoverageTest):
"""Tests using runpy."""

@pytest.mark.parametrize("convert_to", ["str", "Path"])
def test_runpy_path(self, convert_to: str) -> None:
# Ensure runpy.run_path(path) works when path is pathlib.Path or str.
#
# runpy.run_path(pathlib.Path(...)) causes __file__ to be a Path,
# which may make source_for_file() stumble (#1819) with:
#
# AttributeError: 'PosixPath' object has no attribute 'endswith'

self.check_coverage(f"""\
import runpy
from pathlib import Path
pyfile = Path('script.py')
pyfile.write_text('')
runpy.run_path({convert_to}(pyfile))
""")

0 comments on commit 7fb846e

Please sign in to comment.