diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 15a028dd..5e91adf8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog ========= +* Avoid HTML coverage reports trying to parse non-Python source files such as + Jinja templates. See `#748 `_. + 7.1.0 (2026-03-21) ------------------ diff --git a/src/pytest_cov/engine.py b/src/pytest_cov/engine.py index a6a465fa..ea52b4f1 100644 --- a/src/pytest_cov/engine.py +++ b/src/pytest_cov/engine.py @@ -186,7 +186,19 @@ def summary(self, stream): # Produce html report if wanted. if 'html' in self.cov_report: output = self.cov_report['html'] - self.cov.html_report(ignore_errors=True, directory=output) + html_options = {} + if ( + self.cov.config.source is None + and not self.cov.config.source_pkgs + and not self.cov.config.run_include + and self.cov.config.report_include is None + ): + # Coverage data can include executable code compiled from + # non-Python sources, such as Jinja templates. Restrict the + # default HTML report to Python files so the report generator + # does not try to parse those sources as Python. + html_options['include'] = ['*.py'] + self.cov.html_report(ignore_errors=True, directory=output, **html_options) stream.write(f'Coverage HTML written to dir {self.cov.config.html_dir if output is None else output}\n') # Produce xml report if wanted. diff --git a/tests/test_pytest_cov.py b/tests/test_pytest_cov.py index b291f432..0a990320 100644 --- a/tests/test_pytest_cov.py +++ b/tests/test_pytest_cov.py @@ -257,6 +257,27 @@ def test_html(testdir): assert result.ret == 0 +def test_html_ignores_non_python_sources(testdir): + template = testdir.makefile('.jinja2', template='{% invalid jinja %}') + script = testdir.makepyfile( + f""" +def test_template(): + exec(compile('value = 1\\n', {str(template)!r}, 'exec')) +""" + ) + + result = testdir.runpytest('-v', '--cov', '--cov-report=html', script) + + result.stdout.fnmatch_lines( + [ + '*_ coverage: platform *, python * _*', + 'Coverage HTML written to dir htmlcov', + '*1 passed*', + ] + ) + assert result.ret == 0 + + def test_html_output_dir(testdir): script = testdir.makepyfile(SCRIPT)