coveragepy
coveragepy copied to clipboard
`--omit` command line flag and config values are not merged
Describe the bug I hope this is not a duplicate, I've looked for a while
I am in a situation where I do not have control over the --omit flag under which the coverage process is ran (pycharm does that for me and it is not configurable). However, I have control over the coveragerc.
Unfortunately, the --omit flag seems to overwrite both the [run] and the [report] sections' omit= keys.
Environment
`coverage debug sys`
-- sys -------------------------------------------------------
coverage_version: 6.6.0b1
coverage_module: /opt/pycroft/venv/lib/python3.10/site-packages/coverage/__init__.py
tracer: -none-
CTracer: available
plugins.file_tracers: -none-
plugins.configurers: -none-
plugins.context_switchers: -none-
configs_attempted: .coveragerc
configs_read: /opt/pycroft/app/.coveragerc
config_file: /opt/pycroft/app/.coveragerc
config_contents: b'[run]\ndebug = trace\nsource =\n pycroft\n ldap_sync\n hades_logs\n web\nomit =\n tests\n **/alembic/**\n .pycharm_helpers\n\n[report]\nomit =\n **/alembic/**\n'
data_file: -none-
python: 3.10.1 (main, Dec 8 2021, 03:30:49) [GCC 10.2.1 20210110]
platform: Linux-6.0.6-arch1-1-x86_64-with-glibc2.31
implementation: CPython
executable: /opt/pycroft/venv/bin/python3
def_encoding: utf-8
fs_encoding: utf-8
pid: 27
cwd: /opt/pycroft/app
path: /opt/pycroft/venv/bin
/usr/local/lib/python310.zip
/usr/local/lib/python3.10
/usr/local/lib/python3.10/lib-dynload
/opt/pycroft/venv/lib/python3.10/site-packages
/opt/pycroft/app
environment: HOME = /opt/pycroft
PYTHONDEVMODE = 1
PYTHON_GET_PIP_SHA256 = c518250e91a70d7b20cceb15272209a4ded2a0c263ae5776f129e0d9b5674309
PYTHON_GET_PIP_URL = https://github.com/pypa/get-pip/raw/3cb8888cc2869620f57d5d2da64da38f516078c7/public/get-pip.py
PYTHON_PIP_VERSION = 21.2.4
PYTHON_SETUPTOOLS_VERSION = 57.5.0
PYTHON_VERSION = 3.10.1
command_line: /opt/pycroft/venv/bin/coverage debug sys
sqlite3_sqlite_version: 3.34.1
sqlite3_temp_store: 0
sqlite3_compile_options: COMPILER=gcc-10.2.1 20210110, 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, USE_URI
`pip freeze` (shouldn't be relevant)
aiofiles==0.8.0
aiohttp==3.8.1
aiosignal==1.2.0
alabaster==0.7.12
alembic==1.6.5
amqp==5.0.7
aniso8601==9.0.1
async-timeout==4.0.1
attrs==21.2.0
Babel==2.9.1
backcall==0.2.0
billiard==3.6.4.0
black==22.3.0
bleach==4.1.0
blinker==1.4
boltons==21.0.0
celery==5.2.1
celery-types==0.9.3
certifi==2021.10.8
charset-normalizer==2.0.9
click==8.0.3
click-didyoumean==0.3.0
click-plugins==1.1.1
click-repl==0.2.0
cloudpickle==2.2.0
colorama==0.4.4
colored==1.4.3
commonmark==0.9.1
coverage==6.6.0b1
decorator==5.1.0
dnspython==2.1.0
docutils==0.17.1
elementpath==2.4.0
eliot==1.14.0
eliot-tree==21.0.0
email-validator==1.1.3
factory-boy==3.2.1
Faker==10.0.0
fints==3.0.1
Flask==1.1.2
Flask-Babel==2.0.0
Flask-Login==0.5.0
Flask-RESTful==0.3.9
Flask-Testing==0.8.1
Flask-WTF==1.0.0
frozenlist==1.2.0
gitdb2==2.0.6
GitPython==2.1.15
gprof2dot==2021.2.21
greenlet==1.1.2
guzzle-sphinx-theme==0.7.11
idna==3.3
imagesize==1.3.0
inflection==0.5.1
iniconfig==1.1.1
ipaddr==2.2.0
ipython==7.30.1
iso8601==1.0.2
itsdangerous==1.1.0
jedi==0.18.1
Jinja2==2.11.3
jmespath==0.10.0
jsonschema==3.2.0
kombu==5.2.2
ldap3==2.5.2
livereload==2.6.3
mac-vendor-lookup==0.1.11
Mako==1.1.6
MarkupSafe==1.1.1
marshmallow==3.18.0
matplotlib-inline==0.1.3
mt-940==4.19.0
multidict==5.2.0
mypy==0.961
mypy-extensions==0.4.3
packaging==21.3
parso==0.8.3
passlib==1.7.4
pathspec==0.9.0
pexpect==4.8.0
pickleshare==0.7.5
Pillow==8.4.0
platformdirs==2.5.2
pluggy==1.0.0
prompt-toolkit==3.0.24
psycopg2==2.8.6
psycopg2-binary==2.9.2
ptyprocess==0.7.0
py==1.11.0
py-healthcheck==1.10.1
pyasn1==0.4.8
-e git+ssh://gh/agdsn/pycroft@f9f28339668c09d4b97a455aeb8af16d9a18c333#egg=pycroft
pydot==1.4.2
Pygments==2.10.0
pyinstrument==4.1.1
pynvml==11.4.1
pyparsing==3.0.6
pyrsistent==0.18.0
pytest==7.0.0
pytest-fixture-tools==1.1.0
pytest-profiling==1.7.0
pytest-timeout==2.1.0
python-dateutil==2.8.2
python-editor==1.0.4
pytz==2021.3
reportlab==3.6.3
requests==2.26.0
rich==12.6.0
scalene==1.5.13
sentry-sdk==1.0.0
sepaxml==2.5.0
simplejson==3.11.1
six==1.16.0
smmap==5.0.0
smmap2==3.0.1
snowballstemmer==2.2.0
Sphinx==5.1.1
sphinx-autobuild==2021.3.14
sphinx-paramlinks==0.5.4
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
SQLAlchemy==1.4.37
sqlalchemy-schemadisplay==1.4.dev0
sqlalchemy2-stubs==0.0.2a23
text-unidecode==1.3
toml==0.10.2
tomli==2.0.0
toolz==0.11.2
tornado==6.1
traitlets==5.1.1
types-babel==2.9.2
types-backports==0.1.3
types-ipaddress==1.0.8
types-Jinja2==2.11.9
types-jsonschema==4.3.0
types-MarkupSafe==1.1.10
typing_extensions==4.0.1
urllib3==1.26.7
uWSGI==2.0.20
uwsgitop==0.11
vine==5.0.0
wcwidth==0.2.5
webencodings==0.5.1
Werkzeug==1.0.1
wrapt==1.12.1
WTForms==2.2.1
WTForms-SQLAlchemy==0.3
wtforms-widgets @ file:///opt/pycroft/app/deps/wtforms-widgets
xmlschema==1.9.1
yarl==1.7.2
zope.interface==5.4.0
To Reproduce
Compare the output of coverage run --debug=config test.py
Output 1
-- config ----------------------------------------------------
attempted_config_files: .coveragerc
command_line: None
concurrency: None
config_file: /opt/pycroft/app/.coveragerc
config_files_read: /opt/pycroft/app/.coveragerc
context: None
cover_pylib: False
data_file: .coverage
debug: config
disable_warnings: -none-
dynamic_context: None
exclude_list: #\s*(pragma|PRAGMA)[:\s]?\s*(no|NO)\s*(cover|COVER)
extra_css: None
fail_under: 0.0
html_dir: htmlcov
html_skip_covered: None
html_skip_empty: None
html_title: Coverage report
ignore_errors: False
json_output: coverage.json
json_pretty_print: False
json_show_contexts: False
lcov_output: coverage.lcov
note: None
parallel: False
partial_always_list: while (True|1|False|0):
if (True|1|False|0):
partial_list: #\s*(pragma|PRAGMA)[:\s]?\s*(no|NO)\s*(branch|BRANCH)
paths: OrderedDict()
plugin_options: {}
plugins: -none-
precision: 0
relative_files: False
report_contexts: None
report_include: None
report_omit: **/alembic/**
run_include: None
run_omit: tests
**/alembic/**
.pycharm_helpers
show_contexts: False
show_missing: False
sigterm: False
skip_covered: False
skip_empty: False
sort: None
source: pycroft
ldap_sync
hades_logs
web
source_pkgs: -none-
timid: False
xml_output: coverage.xml
xml_package_depth: 99
-- end -------------------------------------------------------
/opt/pycroft/venv/lib/python3.10/site-packages/coverage/control.py:799: CoverageWarning: No data was collected. (no-data-collected)
self._warn("No data was collected.", slug="no-data-collected")
Output 2
-- config ----------------------------------------------------
attempted_config_files: .coveragerc
branch: False
command_line: None
concurrency: None
config_file: /opt/pycroft/app/.coveragerc
config_files_read: /opt/pycroft/app/.coveragerc
context: None
cover_pylib: False
data_file: .coverage
debug: config
disable_warnings: -none-
dynamic_context: None
exclude_list: #\s*(pragma|PRAGMA)[:\s]?\s*(no|NO)\s*(cover|COVER)
extra_css: None
fail_under: 0.0
html_dir: htmlcov
html_skip_covered: None
html_skip_empty: None
html_title: Coverage report
ignore_errors: False
json_output: coverage.json
json_pretty_print: False
json_show_contexts: False
lcov_output: coverage.lcov
note: None
parallel: False
partial_always_list: while (True|1|False|0):
if (True|1|False|0):
partial_list: #\s*(pragma|PRAGMA)[:\s]?\s*(no|NO)\s*(branch|BRANCH)
paths: OrderedDict()
plugin_options: {}
plugins: -none-
precision: 0
relative_files: False
report_contexts: None
report_include: None
report_omit: FOOOO
run_include: None
run_omit: FOOOO
show_contexts: False
show_missing: False
sigterm: False
skip_covered: False
skip_empty: False
sort: None
source: pycroft
ldap_sync
hades_logs
web
source_pkgs: -none-
timid: False
xml_output: coverage.xml
xml_package_depth: 99
-- end -------------------------------------------------------
Expected behavior In the second command,
run_omitshould have multiple values, ending withFOOOOreport_omitshould have multiple values, ending withFOOOO
This would be a change in how the command line arguments are used. Can you tell me more about how PyCharm is setting the omit option, and how you are trying to set it? I haven't heard of it doing this before.
@nedbat I'm running „$FOO with coverage“ with a docker-compose based python interpreter.
Inside the container, a command like the following is run:
/opt/pycroft/venv/bin/python \
/opt/.pycharm_helpers/coverage_runner/run_coverage.py \
run --branch --omit="/opt/pycharm-professional/plugins/python/helpers*" \
/opt/.pycharm_helpers/pycharm/_jb_pytest_runner.py \
--target tests/ldap_sync/test_ldap_sync.py::TestMultipleUsersFilter
The run_coverage.py is a wrapper around coverage.py, which passes argv as is.
You see that it passes the pycharm helpers folder to the --omit-flag.
In my coveragerc however, I want to omit migrations; the entries are
[run]
source_pkgs = […]
omit =
**/alembic/**
.pycharm_helpers
[report]
omit =
**/alembic/**
since I don't have any control about the run_coverage.py wrapper and I can't configure any flags passed to it I'm stuck with the config.
I think I have this exact problem with the current version of PyCharm.
On Windows, the command line it builds when executing a run configuration 'with Coverage' looks like this:
python.exe "C:/Program Files (x86)/JetBrains/PyCharm 2025.1/plugins/python-ce/helpers/coverage_runner/run_coverage.py"
run "--omit=\"C:\Program Files (x86)\JetBrains\PyCharm 2025.1\plugins\python-ce\helpers*\""
"C:/Program Files (x86)/JetBrains/PyCharm 2025.1/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py"
--path E:/Code/pyprojects/<my project here>
It respects other fields set in my .coveragerc file, such as cover_pylib, but its attempt to exclude some of its own files seems to be interfering with my [omit] settings.
Technically I suppose this is a bug in Pycharm, and I'll report it there as well.
Actually, I just found that this has been logged as a PyCharm bug for years: https://youtrack.jetbrains.com/issue/PY-41334/omit-directive-from-.coveragerc-is-not-working