fix: runpy.run_path(path) crashes with pathlib.Path (#1819) * fix: runpy.run_path(path) crashes with pathlib.Path * Revert "fix: runpy.run_path(path) crashes with pathlib.Path" This reverts commit 2d1eabda2710415aa02166529238e7ce6257678c. * 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 <ned@nedbatchelder.com> GitOrigin-RevId: 7fb846e8c12b33f9f82964bbb1cef7cc2795d42d Change-Id: Ifddce5f971f3390fb2854f0932b7ccf8baa13d5b
diff --git a/CHANGES.rst b/CHANGES.rst index ff40f69..139d4d5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst
@@ -23,7 +23,11 @@ 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
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 728f2fb..e44920c 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt
@@ -25,6 +25,7 @@ Arthur Deygin Arthur Rio Asher Foa +Ask Hjorth Larsen Ben Carlsson Ben Finney Benjamin Parzella
diff --git a/coverage/inorout.py b/coverage/inorout.py index 5ea29ed..4df54b2 100644 --- a/coverage/inorout.py +++ b/coverage/inorout.py
@@ -321,7 +321,8 @@ # 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):
diff --git a/tests/test_python.py b/tests/test_python.py index ee0268f..6a83629 100644 --- a/tests/test_python.py +++ b/tests/test_python.py
@@ -63,3 +63,24 @@ # 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)) + """)