Open webknjaz opened 1 month ago
I've tested that adding
omit = .tox/**
is a functional workaround, following the suggestions in other issues.
Nope. It only appeared to be a full workaround, but it's not. It does what I expected in the local HTML/XML reports, but excludes all of the awx_plugins
namespace files from the XML report in CI, making Codecov not show anything. I checked that codecov receives XML files with tests/
paths while locally I also have src/
paths. The coveragepy version is the same and other things should be as well, due to how I pin the environment deps. This is very weird...
I ended up changing that to a granular
omit =
.tox/*/lib/pypy*/site-packages/awx_plugins/interfaces/**
.tox/*/lib/python*/site-packages/awx_plugins/interfaces/**
.tox\*\Lib\site-packages\awx_plugins\interfaces\**
for now, but I don't understand why running the same command in the CI and locally would produce different coverage reports. It seems like the environment somehow influences how omit
works, which is rather confusing.
Describe the bug
I have a case when I get unexpected coverage measurements from a tox-managed virtualenv existing within the source tree. Coveragepy is invoked via
pytest-cov
but all configuration is in coveragerc so I'm pretty sure this issue belongs here.This reminds me of #876 and #905. Having stared at https://github.com/nedbat/coveragepy/commit/0285af966a3942d8bd63489bd285328e96221126 and https://github.com/nedbat/coveragepy/commit/5c2f614e01d35271f7907d85050115071cf24e87, I concluded that the fixes are still imperfect.
The reproducers in those issues showcased regular non-namespaces packages, which is why it wasn't on anybody's radar, I think. But I'm sure my case is legit too.
In the example below,
awx_plugins
is the namespace. The dependency is theawx_plugins.interfaces
importable and the project itself containsawx_plugins.credentials
andawx_plugins.inventory
. The project's files are undersrc/awx_plugins/{credentials,inventory}/*.py
andtests/*.py
. The dependecy hassrc/awx_plugins/interfaces/*.py
in the repo, but all are installed side-by-side as.tox/py/lib/python3.13/site-packages/awx_plugins/{credentials,interfaces,inventory}/*.py
..tox/py/lib/python3.13/site-packages/awx_plugins/__init__.py
does not exist..tox/py/lib/python3.13/site-packages/awx_plugins/{credentials,interfaces,inventory}/__init__.py
do not exist either.The project is configured with
which maps all the project-local source files properly (which is visible in the report correctly). The third-party ones remain unmatched and show up with site-packages paths.
There's also
The generic paths and namespaces effectively give me the ability to copy the good coveragerc file over into similar packages of the same namespace and folder layout. This is intentional.
I'm almost sure changing
source_pkgs
to listawx_plugins.credentials
andawx_plugins.inventory
would limit what ends up in the report but that's not something I want given that I wish to have a reusable config across an ecosystem of similar projects (i.e. plugins to something else).I've tested that adding
is a functional workaround, following the suggestions in other issues.
But ultimately, I believe that this is a bug fixable within coveragepy and I shouldn't have to keep the
omit
settings in my configs.To Reproduce
What version of coverage.py shows the problem?
👉 click to unfold 👈
```console $ .tox/py/bin/python -m coverage debug sys -- sys ------------------------------------------------------- coverage_version: 7.6.1 coverage_module: ~/src/github/ansible/awx-plugins/.tox/py/lib/python3.13/site-packages/coverage/__init__.py core: -none- CTracer: available plugins.file_tracers: -none- plugins.configurers: covdefaults.CovDefaults plugins.context_switchers: -none- configs_attempted: ~/src/github/ansible/awx-plugins/.coveragerc configs_read: ~/src/github/ansible/awx-plugins/.coveragerc config_file: ~/src/github/ansible/awx-plugins/.coveragerc config_contents: b'[html]\nshow_contexts = true\nskip_covered = false\n\n[paths]\n_site-packages-to-src-mapping =\n src\n */src\n *\\src\n */lib/pypy*/site-packages\n */lib/python*/site-packages\n *\\Lib\\site-packages\n\n[report]\n# `fail_under` is set here temporarily until it can be dropped:\nfail_under = 39.27\nskip_covered = true\nskip_empty = true\nshow_missing = true\nexclude_also =\n ^\\s*@pytest\\.mark\\.xfail\n\n[run]\nbranch = true\ncover_pylib = false\n# https://coverage.rtfd.io/en/latest/contexts.html#dynamic-contexts\n# dynamic_context = test_function # conflicts with `pytest-cov` if set here\nomit =\n .tox/**\nparallel = true\nplugins =\n covdefaults\nrelative_files = true\nsource =\n .\nsource_pkgs =\n awx_plugins\n' data_file: -none- python: 3.13.0b2 (main, Jun 23 2024, 13:25:09) [GCC 13.2.1 20240113] platform: Linux-6.6.13-gentoo-dist-x86_64-Intel-R-_Core-TM-_i7-9850H_CPU_@_2.60GHz-with-glibc2.38 implementation: CPython gil_enabled: True executable: ~/src/github/ansible/awx-plugins/.tox/py/bin/python def_encoding: utf-8 fs_encoding: utf-8 pid: 31740 cwd: ~/src/github/ansible/awx-plugins path: ~/src/github/ansible/awx-plugins ~/.pyenv/versions/3.13.0b2/lib/python313.zip ~/.pyenv/versions/3.13.0b2/lib/python3.13 ~/.pyenv/versions/3.13.0b2/lib/python3.13/lib-dynload ~/src/github/ansible/awx-plugins/.tox/py/lib/python3.13/site-packages ~/src/github/ansible/awx-plugins/src environment: HOME = ~ PYENV_ROOT = ~/.pyenv PYENV_SHELL = zsh PYENV_VIRTUALENV_INIT = 1 command_line: ~/src/github/ansible/awx-plugins/.tox/py/lib/python3.13/site-packages/coverage/__main__.py debug sys sqlite3_sqlite_version: 3.44.2 sqlite3_temp_store: 0 sqlite3_compile_options: ATOMIC_INTRINSICS=1, COMPILER=gcc-13.2.1 20240113, DEFAULT_AUTOVACUUM, DEFAULT_CACHE_SIZE=-2000, DEFAULT_FILE_FORMAT=4, DEFAULT_JOURNAL_SIZE_LIMIT=-1, DEFAULT_MMAP_SIZE=0, DEFAULT_PAGE_SIZE=4096, DEFAULT_PCACHE_INITSZ=20, DEFAULT_RECURSIVE_TRIGGERS, DEFAULT_SECTOR_SIZE=4096, DEFAULT_SYNCHRONOUS=2, DEFAULT_WAL_AUTOCHECKPOINT=1000, DEFAULT_WAL_SYNCHRONOUS=2, DEFAULT_WORKER_THREADS=0, ENABLE_API_ARMOR, ENABLE_BYTECODE_VTAB, ENABLE_COLUMN_METADATA, ENABLE_DBPAGE_VTAB, ENABLE_DBSTAT_VTAB, ENABLE_EXPLAIN_COMMENTS, ENABLE_FTS3, ENABLE_FTS3_PARENTHESIS, ENABLE_FTS4, ENABLE_FTS5, ENABLE_GEOPOLY, ENABLE_HIDDEN_COLUMNS, ENABLE_ICU, ENABLE_MATH_FUNCTIONS, ENABLE_MEMSYS5, ENABLE_NORMALIZE, ENABLE_OFFSET_SQL_FUNC, ENABLE_PREUPDATE_HOOK, ENABLE_RBU, ENABLE_RTREE, ENABLE_SESSION, ENABLE_STMTVTAB, ENABLE_STMT_SCANSTATUS, ENABLE_UNKNOWN_SQL_FUNCTION, ENABLE_UNLOCK_NOTIFY, ENABLE_UPDATE_DELETE_LIMIT, HAVE_ISNAN, MALLOC_SOFT_LIMIT=1024, MAX_ATTACHED=10, MAX_COLUMN=2000, MAX_COMPOUND_SELECT=500, MAX_DEFAULT_PAGE_SIZE=8192, MAX_EXPR_DEPTH=1000, MAX_FUNCTION_ARG=127, MAX_LENGTH=1000000000, MAX_LIKE_PATTERN_LENGTH=50000, MAX_MMAP_SIZE=0x7fff0000, MAX_PAGE_COUNT=1073741823, MAX_PAGE_SIZE=65536, MAX_SQL_LENGTH=1000000000, MAX_TRIGGER_DEPTH=1000, MAX_VARIABLE_NUMBER=32766, MAX_VDBE_OP=250000000, MAX_WORKER_THREADS=8, MUTEX_PTHREADS, SOUNDEX, SYSTEM_MALLOC, TEMP_STORE=1, THREADSAFE=1, USE_URI ```What versions of what packages do you have installed?
👉 click to unfold 👈
```console $ .tox/py/bin/python -m pip freeze adal==1.2.7 attrs==24.2.0 awx-plugins-core @ file://~/src/github/ansible/awx-plugins/.tox/.tmp/package/97/awx_plugins_core-0.0.1a5.dev213%2Bg8ea07661f9.d20241004-0.editable-py3-none-any.whl#sha256=3ca7389cb589da068511245e32662a41eefebf9ecfbbdfa7c41025be26f55c12 awx_plugins.interfaces @ git+https://github.com/ansible/awx_plugins.interfaces.git@3a78f59ffe922638f37bf63b4243aac41ed8abd8 azure-core==1.31.0 azure-identity==1.18.0 azure-keyvault==4.2.0 azure-keyvault-certificates==4.8.0 azure-keyvault-keys==4.9.0 azure-keyvault-secrets==4.8.0 boto3==1.35.31 botocore==1.35.31 certifi==2024.8.30 cffi==1.17.1 charset-normalizer==3.3.2 covdefaults==2.3.0 coverage==7.6.1 coverage-enable-subprocess==1.0 cryptography==43.0.1 execnet==2.1.1 hypothesis==6.112.2 idna==3.10 iniconfig==2.0.0 isodate==0.6.1 jmespath==1.0.1 msal==1.31.0 msal-extensions==1.2.0 msrest==0.7.1 msrestazure==0.6.4.post1 oauthlib==3.2.2 packaging==24.1 pluggy==1.5.0 portalocker==2.10.1 pycparser==2.22 PyJWT==2.9.0 pytest==8.3.3 pytest-cov==5.0.0 pytest-mock==3.14.0 pytest-xdist==3.6.1 python-dateutil==2.9.0.post0 python-dsv-sdk==1.0.4 python-tss-sdk==1.2.3 PyYAML==6.0.2 requests==2.32.3 requests-oauthlib==2.0.0 s3transfer==0.10.2 six==1.16.0 sortedcontainers==2.4.0 typing_extensions==4.12.2 urllib3==2.2.3 ```That shows a couple of files under
.tox/py/lib/python3.13/site-packages/awx_plugins/interfaces/**
. They should not be listed.Expected behavior
Coveragepy should not collect coverage in third-party modules from the same implicit namespace, installed in the same virtualenv.
Additional context
The concrete example is inspectable at https://app.codecov.io/gh/ansible/awx-plugins/commit/8ea07661f9da09dedaa52b569978c448fb871931/tree?flags%5B0%5D=pytest. The pre-selected
pytest
flag is what you want to have selected at all times since there's also MyPy coverage that's overlayed if you deselect it.