nedbat / coveragepy

The code coverage tool for Python
https://coverage.readthedocs.io
Apache License 2.0
3k stars 428 forks source link

Support pathlib PosixPath #1417

Closed Jacob-Stevens-Haas closed 1 year ago

Jacob-Stevens-Haas commented 2 years ago

Describe the bug When a test uses runpy.run_path with a Path argument (e.g. a PosixPath), coverage tries to treat it as a string, raising an AttributeError. Could be considered a feature request, but since error appears with builtin modules coverage aims to support (python~=3.6), it feels like a bug.

To Reproduce How can we reproduce the problem? Please be specific. Don't link to a failing CI job. Answer the questions below:

  1. What version of Python are you using? 3.7.5
  2. What version of coverage.py shows the problem? The output of coverage debug sys is helpful. 6.4.1.
`coverage debug sys` ``` -- sys ------------------------------------------------------- coverage_version: 6.4.1 coverage_module: /home/jmsh/github/pysindy/env/lib/python3.7/site-packages/coverage/__init__.py tracer: -none- CTracer: available plugins.file_tracers: -none- plugins.configurers: -none- plugins.context_switchers: -none- configs_attempted: .coveragerc setup.cfg tox.ini pyproject.toml configs_read: -none- config_file: None config_contents: -none- data_file: -none- python: 3.7.5 (default, Dec 9 2021, 17:04:37) [GCC 8.4.0] platform: Linux-4.15.0-173-generic-x86_64-with-Ubuntu-18.04-bionic implementation: CPython executable: /home/jmsh/github/pysindy/env/bin/python def_encoding: utf-8 fs_encoding: utf-8 pid: 55497 cwd: /home/jmsh/github/pysindy/.vscode path: /home/jmsh/github/pysindy/env/bin /usr/lib/python37.zip /usr/lib/python3.7 /usr/lib/python3.7/lib-dynload /home/jmsh/github/pysindy/env/lib/python3.7/site-packages /home/jmsh/github/derivative /home/jmsh/github/pysindy environment: HOME = /home/jmsh command_line: /home/jmsh/github/pysindy/env/bin/coverage debug sys sqlite3_version: 2.6.0 sqlite3_sqlite_version: 3.22.0 sqlite3_temp_store: 0 sqlite3_compile_options: COMPILER=gcc-7.5.0, ENABLE_COLUMN_METADATA, ENABLE_DBSTAT_VTAB, ENABLE_FTS3, ENABLE_FTS3_PARENTHESIS, ENABLE_FTS3_TOKENIZER, ENABLE_FTS4, ENABLE_FTS5, ENABLE_JSON1, ENABLE_LOAD_EXTENSION, ENABLE_PREUPDATE_HOOK, ENABLE_RTREE, ENABLE_SESSION, ENABLE_STMTVTAB, ENABLE_UNLOCK_NOTIFY, ENABLE_UPDATE_DELETE_LIMIT, HAVE_ISNAN, LIKE_DOESNT_MATCH_BLOBS, MAX_SCHEMA_RETRY=25, MAX_VARIABLE_NUMBER=250000, OMIT_LOOKASIDE, SECURE_DELETE, SOUNDEX, TEMP_STORE=1, THREADSAFE=1 ```
  1. What versions of what packages do you have installed? The output of pip freeze is helpful. No other packages used in example, but here's pip freeze:
`pip freeze` ``` alabaster==0.7.12 anyio==3.6.1 argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 attrs==21.4.0 Babel==2.10.2 backcall==0.2.0 beautifulsoup4==4.11.1 black==22.3.0 bleach==5.0.0 certifi==2022.5.18.1 cffi==1.15.0 cfgv==3.3.1 charset-normalizer==2.0.12 click==8.1.3 cmake==3.22.5 codecov==2.1.12 colorama==0.4.4 coverage==6.4.1 cvxpy==1.2.1 cycler==0.11.0 debugpy==1.6.0 decorator==5.1.1 defusedxml==0.7.1 -e git+https://github.com/Jacob-Stevens-Haas/derivative@5649f0865febe662063e58df995aaa597f15ca23#egg=derivative distlib==0.3.4 docutils==0.17.1 ecos==2.0.10 entrypoints==0.4 exceptiongroup==1.0.0rc8 fastjsonschema==2.15.3 filelock==3.7.1 flake8==3.9.2 flake8-builtins-unleashed==1.3.1 fonttools==4.33.3 gitdb==4.0.9 GitPython==3.1.27 gurobipy==9.5.1 hypothesis==6.47.2 identify==2.5.1 idna==3.3 imagesize==1.3.0 importlib-metadata==4.11.4 importlib-resources==5.7.1 iniconfig==1.1.1 ipykernel==6.14.0 ipython==7.34.0 ipython-genutils==0.2.0 ipywidgets==7.7.0 jedi==0.18.1 Jinja2==3.1.2 joblib==1.1.0 jsonschema==4.6.0 jupyter==1.0.0 jupyter-client==7.3.4 jupyter-console==6.4.3 jupyter-contrib-core==0.3.3 jupyter-contrib-nbextensions==0.5.1 jupyter-core==4.10.0 jupyter-highlight-selected-word==0.2.0 jupyter-latex-envs==1.4.6 jupyter-nbextensions-configurator==0.4.1 jupyter-server==1.17.1 jupyter-server-mathjax==0.2.5 jupyterlab-pygments==0.2.2 jupyterlab-widgets==1.1.0 jupytext==1.14.0 kiwisolver==1.4.3 lxml==4.9.0 markdown-it-py==2.1.0 MarkupSafe==2.1.1 matplotlib==3.5.2 matplotlib-inline==0.1.3 mccabe==0.6.1 mdit-py-plugins==0.3.0 mdurl==0.1.1 mistune==0.8.4 mypy-extensions==0.4.3 nbclient==0.6.4 nbconvert==6.5.0 nbdime==3.1.1 nbformat==5.4.0 nest-asyncio==1.5.5 nodeenv==1.6.0 notebook==6.4.12 numpy==1.21.6 osqp==0.6.2.post5 packaging==21.3 pandas==1.3.5 pandocfilters==1.5.0 parso==0.8.3 pathspec==0.9.0 pbr==5.9.0 pexpect==4.8.0 pickleshare==0.7.5 Pillow==9.1.1 pip-licenses==3.5.4 platformdirs==2.5.2 pluggy==1.0.0 pre-commit==2.19.0 prometheus-client==0.14.1 prompt-toolkit==3.0.29 psutil==5.9.1 PTable==0.9.2 ptyprocess==0.7.0 py==1.11.0 pycodestyle==2.7.0 pycparser==2.21 pyflakes==2.3.1 Pygments==2.12.0 pyparsing==3.0.9 pyrsistent==0.18.1 -e git+https://github.com/Jacob-Stevens-Haas/pysindy@3645b558bab1b588ce14cf7bf40de44f0dfc827a#egg=pysindy pytest==7.1.2 pytest-cov==3.0.0 pytest-lazy-fixture==0.6.3 python-dateutil==2.8.2 pytz==2022.1 PyYAML==6.0 pyzmq==23.1.0 qdldl==0.1.5.post2 qtconsole==5.3.1 QtPy==2.1.0 requests==2.28.0 scikit-learn==1.0.2 scipy==1.7.3 scs==2.1.4 seaborn==0.11.2 Send2Trash==1.8.0 setuptools-scm==6.4.2 setuptools-scm-git-archive==1.1 six==1.16.0 sklearn==0.0 smmap==5.0.0 sniffio==1.2.0 snowballstemmer==2.2.0 sortedcontainers==2.4.0 soupsieve==2.3.2.post1 Sphinx==5.0.1 sphinx-nbexamples==0.4.1 sphinx-rtd-theme==1.0.0 sphinxcontrib-apidoc==0.3.0 sphinxcontrib-applehelp==1.0.2 sphinxcontrib-devhelp==1.0.2 sphinxcontrib-htmlhelp==2.0.0 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 terminado==0.15.0 threadpoolctl==3.1.0 tinycss2==1.1.1 toml==0.10.2 tomli==2.0.1 tornado==6.1 traitlets==5.2.2.post1 typed-ast==1.5.4 typing_extensions==4.2.0 urllib3==1.26.9 virtualenv==20.14.1 wcwidth==0.2.5 webencodings==0.5.1 websocket-client==1.3.2 widgetsnbextension==3.6.0 zipp==3.8.0 ```
  1. What code shows the problem? Give us a specific commit of a specific repo that we can check out. If you've already worked around the problem, please provide a commit before that fix. This is the line that errors
  2. What commands did you run? Actual error appeared in CI. Here's a minimal working example.
    coverage run debugme.py

    File 1 (debugme.py):

    
    from pathlib import Path
    import runpy

mydir = Path(file).resolve().parent

runpy.run_path(mydir / "debugme2.py")

File 2 (debugme2.py)
```python
print('here')

Result:

Traceback (most recent call last):
  File "debugme.py", line 6, in <module>
    runpy.run_path(mydir / "debugme2.py")
  File "/usr/lib/python3.7/runpy.py", line 263, in run_path
    pkg_name=pkg_name, script_name=fname)
  File "/usr/lib/python3.7/runpy.py", line 96, in _run_module_code
    mod_name, mod_spec, pkg_name, script_name)
  File "/usr/lib/python3.7/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/jmsh/github/pysindy/env/lib/python3.7/site-packages/coverage/control.py", line 344, in _should_trace
    disp = self._inorout.should_trace(filename, frame)
  File "/home/jmsh/github/pysindy/env/lib/python3.7/site-packages/coverage/inorout.py", line 335, in should_trace
    filename = source_for_file(dunder_file)
  File "/home/jmsh/github/pysindy/env/lib/python3.7/site-packages/coverage/python.py", line 105, in source_for_file
    if filename.endswith(".py"):
AttributeError: 'PosixPath' object has no attribute 'endswith'

Expected behavior Execute without error

Additional context Thanks for your help!

nedbat commented 1 year ago

Thanks, and sorry for letting this wait for so long.

This is an interesting report, but I think the fault is with run_path, not with coverage.py. I've written a bug report against CPython: https://github.com/python/cpython/issues/99437. There you can see that also the inspect module fails in a similar way.

I'll leave this issue open until we see how CPython responds.

You probably already found the workaround, which is to change the path to a string:

runpy.run_path(str(mydir / "debugme2.py"))
Jacob-Stevens-Haas commented 1 year ago

Thanks @nedbat, really appreciate the follow up and investigation :)