diff-cover 10.3.0__tar.gz → 10.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {diff_cover-10.3.0 → diff_cover-10.4.1}/PKG-INFO +1 -1
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/diff_cover_tool.py +17 -1
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/snippets.py +20 -3
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/violationsreporters/violations_reporter.py +46 -16
- {diff_cover-10.3.0 → diff_cover-10.4.1}/pyproject.toml +1 -1
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_diff_cover_tool.py +10 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_snippets.py +39 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_violations_reporter.py +69 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/LICENSE +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/NOTICE +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/README.rst +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/__init__.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/command_runner.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/config_parser.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/diff_quality_tool.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/diff_reporter.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/git_diff.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/git_path.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/hook.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/hookspecs.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/report_generator.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/console_coverage_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/console_quality_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/external_style.css +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/github_coverage_annotations.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/html_coverage_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/html_quality_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/markdown_coverage_report.md +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/markdown_quality_report.md +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/snippet_content.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/snippet_content.md +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/snippet_content.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/snippet_style.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/util.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/violationsreporters/__init__.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/violationsreporters/base.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/violationsreporters/java_violations_reporter.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/__init__.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/conftest.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/add_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/add_html_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/add_json_report.json +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/add_json_report_float.json +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/add_markdown_report.md +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/changed_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/changed_html_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/coverage.xml +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/coverage1.xml +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/coverage2.xml +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/coverage_missing_lines.xml +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/cpp_functions_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/cpp_functions_coverage.lcov +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/delete_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/delete_html_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/dotnet_coverage.xml +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/empty.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/empty_pycodestyle_violations.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/expand_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/external_css_html_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/external_style.css +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_add.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_changed.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_code_dupe.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_cpp.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_cpp_functions.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_delete.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_dotnet.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_external_css.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_lua.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_moved.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_mult.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_python.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_subdir.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_typescript.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_typescript_branches.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_unicode.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_violations.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/git_diff_violations_two_files.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/hello.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/hi.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/html_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/html_report_empty.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/html_report_one_snippet.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/html_report_two_snippets.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/lcov.info +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/lua_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/luacoverage.xml +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/markdown_report_one_snippet.md +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/markdown_report_two_snippets.md +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/moved_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/moved_coverage.xml +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/moved_html_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/mult_inputs_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/mult_inputs_html_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pycodestyle_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pycodestyle_violations_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pycodestyle_violations_report.json +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pycodestyle_violations_report.md +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pycodestyle_violations_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pycodestyle_violations_report_external_css.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pycodestyle_violations_report_float.json +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pyflakes_two_files.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pyflakes_violations_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pyflakes_violations_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pylint_dupe.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pylint_dupe_violations_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pylint_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pylint_violations_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pylint_violations_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pylint_violations_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pylintrc +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/real_cpp_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/real_cpp_coverage.lcov +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/real_python_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/real_python_coverage.lcov +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/real_typescript_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/real_typescript_coverage.lcov +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/show_uncovered_lines_console.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet.css +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_8859.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_arabic_output.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_default.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_invalid_violations.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_list.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_list.md +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_list2.md +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_list3.md +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_no_filename_ext.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_src.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_src2.cpp +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_src3.cpp +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_unicode.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_unicode.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/snippet_unicode_html_output.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/subdir_coverage_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/subdir_coverage_html_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/test_src.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/typescript_branches_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/typescript_branches_coverage.lcov +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/unicode_console_report.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/unicode_coverage.xml +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/unicode_html_report.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/unicode_test_src.txt +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/violations_test_file.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/helpers.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/snippet_list_unicode.html +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_clover_violations_reporter/test.xml +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_clover_violations_reporter.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_config_parser.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_diff_cover_main.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_diff_quality_main.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_diff_reporter.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_git_diff.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_git_diff_file.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_git_path.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_integration.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_java_violations_reporter.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_report_generator.py +0 -0
- {diff_cover-10.3.0 → diff_cover-10.4.1}/tests/test_util.py +0 -0
|
@@ -52,6 +52,10 @@ SHOW_COVERED_HELP = (
|
|
|
52
52
|
EXPAND_COVERAGE_REPORT = (
|
|
53
53
|
"Append missing lines in coverage reports based on the hits of the previous line."
|
|
54
54
|
)
|
|
55
|
+
BRANCH_COVERAGE_HELP = (
|
|
56
|
+
"Treat partially covered branches as uncovered. Requires a coverage report "
|
|
57
|
+
'with branch coverage data (Cobertura branch="true" condition-coverage).'
|
|
58
|
+
)
|
|
55
59
|
INCLUDE_UNTRACKED_HELP = "Include untracked files"
|
|
56
60
|
CONFIG_FILE_HELP = "The configuration file to use"
|
|
57
61
|
DIFF_FILE_HELP = "The diff file to use"
|
|
@@ -117,6 +121,13 @@ def parse_coverage_args(argv):
|
|
|
117
121
|
help=EXPAND_COVERAGE_REPORT,
|
|
118
122
|
)
|
|
119
123
|
|
|
124
|
+
parser.add_argument(
|
|
125
|
+
"--branch-coverage",
|
|
126
|
+
action="store_true",
|
|
127
|
+
default=None,
|
|
128
|
+
help=BRANCH_COVERAGE_HELP,
|
|
129
|
+
)
|
|
130
|
+
|
|
120
131
|
parser.add_argument(
|
|
121
132
|
"--external-css-file",
|
|
122
133
|
metavar="FILENAME",
|
|
@@ -215,6 +226,7 @@ def parse_coverage_args(argv):
|
|
|
215
226
|
"diff_range_notation": "...",
|
|
216
227
|
"quiet": False,
|
|
217
228
|
"expand_coverage_report": False,
|
|
229
|
+
"branch_coverage": False,
|
|
218
230
|
"total_percent_float": False,
|
|
219
231
|
}
|
|
220
232
|
|
|
@@ -237,6 +249,7 @@ def generate_coverage_report(
|
|
|
237
249
|
show_uncovered=False,
|
|
238
250
|
show_covered=False,
|
|
239
251
|
expand_coverage_report=False,
|
|
252
|
+
branch_coverage=False,
|
|
240
253
|
total_percent_float=False,
|
|
241
254
|
):
|
|
242
255
|
"""
|
|
@@ -265,7 +278,9 @@ def generate_coverage_report(
|
|
|
265
278
|
if xml_roots and lcov_roots:
|
|
266
279
|
raise ValueError("Mixing LCov and XML reports is not supported yet")
|
|
267
280
|
if xml_roots:
|
|
268
|
-
coverage = XmlCoverageReporter(
|
|
281
|
+
coverage = XmlCoverageReporter(
|
|
282
|
+
xml_roots, src_roots, expand_coverage_report, branch_coverage
|
|
283
|
+
)
|
|
269
284
|
else:
|
|
270
285
|
coverage = LcovCoverageReporter(lcov_roots, src_roots)
|
|
271
286
|
|
|
@@ -417,6 +432,7 @@ def main(argv=None, directory=None):
|
|
|
417
432
|
show_uncovered=arg_dict["show_uncovered"],
|
|
418
433
|
show_covered=arg_dict["show_covered"],
|
|
419
434
|
expand_coverage_report=arg_dict["expand_coverage_report"],
|
|
435
|
+
branch_coverage=arg_dict["branch_coverage"],
|
|
420
436
|
total_percent_float=arg_dict["total_percent_float"],
|
|
421
437
|
)
|
|
422
438
|
|
|
@@ -17,6 +17,17 @@ from pygments.util import ClassNotFound
|
|
|
17
17
|
|
|
18
18
|
from diff_cover.git_path import GitPathTool
|
|
19
19
|
|
|
20
|
+
# Below this, chardet is essentially guessing. Short files with only a
|
|
21
|
+
# handful of non-ascii bytes decode cleanly under every single byte
|
|
22
|
+
# encoding, so which one comes back is down to the detector's internals
|
|
23
|
+
# (chardet 7 answers MacRoman at 0.16 confidence for latin-1 text that
|
|
24
|
+
# chardet 5 called ISO-8859-1 at 0.73).
|
|
25
|
+
MIN_DETECTION_CONFIDENCE = 0.5
|
|
26
|
+
|
|
27
|
+
# What to try before an unconfident guess. cp1252 is the de facto default
|
|
28
|
+
# for undeclared western text and is a superset of latin-1 in practice.
|
|
29
|
+
FALLBACK_ENCODING = "cp1252"
|
|
30
|
+
|
|
20
31
|
|
|
21
32
|
class Snippet:
|
|
22
33
|
"""
|
|
@@ -284,9 +295,15 @@ class Snippet:
|
|
|
284
295
|
contents = src_file.read()
|
|
285
296
|
|
|
286
297
|
if isinstance(contents, bytes):
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
298
|
+
detected = chardet.detect(contents)
|
|
299
|
+
candidates = [detected.get("encoding") or "utf-8"]
|
|
300
|
+
if (detected.get("confidence") or 0) < MIN_DETECTION_CONFIDENCE:
|
|
301
|
+
candidates.insert(0, FALLBACK_ENCODING)
|
|
302
|
+
|
|
303
|
+
for encoding in candidates:
|
|
304
|
+
with contextlib.suppress(UnicodeDecodeError, LookupError):
|
|
305
|
+
contents = contents.decode(encoding)
|
|
306
|
+
break
|
|
290
307
|
|
|
291
308
|
if isinstance(contents, bytes):
|
|
292
309
|
# We failed to decode the file.
|
{diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/violationsreporters/violations_reporter.py
RENAMED
|
@@ -24,7 +24,13 @@ class XmlCoverageReporter(BaseViolationReporter):
|
|
|
24
24
|
Query information from a Cobertura|Clover|JaCoCo XML coverage report.
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
|
-
def __init__(
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
xml_roots,
|
|
30
|
+
src_roots=None,
|
|
31
|
+
expand_coverage_report=False,
|
|
32
|
+
branch_coverage=False,
|
|
33
|
+
):
|
|
28
34
|
"""
|
|
29
35
|
Load the XML coverage report represented
|
|
30
36
|
by the cElementTree with root element `xml_root`.
|
|
@@ -42,6 +48,11 @@ class XmlCoverageReporter(BaseViolationReporter):
|
|
|
42
48
|
|
|
43
49
|
self._src_roots = src_roots or [""]
|
|
44
50
|
self._expand_coverage_report = expand_coverage_report
|
|
51
|
+
self._branch_coverage = branch_coverage
|
|
52
|
+
|
|
53
|
+
# Pulls the "(covered/total)" pair out of Cobertura's
|
|
54
|
+
# condition-coverage attribute, e.g. "50% (1/2)".
|
|
55
|
+
self._cobertura_condition_coverage_re = re.compile(r"\((\d+)/(\d+)\)")
|
|
45
56
|
|
|
46
57
|
def _get_xml_classes(self, xml_document):
|
|
47
58
|
"""
|
|
@@ -239,23 +250,19 @@ class XmlCoverageReporter(BaseViolationReporter):
|
|
|
239
250
|
{_hits: last_hit_number, _number: line_number}
|
|
240
251
|
)
|
|
241
252
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if int(line.get(_hits, 0)) == 0
|
|
248
|
-
}
|
|
253
|
+
new_violations = {
|
|
254
|
+
Violation(int(line.get(_number)), None)
|
|
255
|
+
for line in line_nodes
|
|
256
|
+
if self._is_violation(line, _hits)
|
|
257
|
+
}
|
|
249
258
|
|
|
250
|
-
#
|
|
251
|
-
#
|
|
252
|
-
#
|
|
259
|
+
# The first report defines the violations set. Each subsequent
|
|
260
|
+
# report narrows it, since we only keep violations that show up
|
|
261
|
+
# in every report.
|
|
262
|
+
if violations is None:
|
|
263
|
+
violations = new_violations
|
|
253
264
|
else:
|
|
254
|
-
violations = violations &
|
|
255
|
-
Violation(int(line.get(_number)), None)
|
|
256
|
-
for line in line_nodes
|
|
257
|
-
if int(line.get(_hits, 0)) == 0
|
|
258
|
-
}
|
|
265
|
+
violations = violations & new_violations
|
|
259
266
|
|
|
260
267
|
# Measured is the union of itself and the new measured
|
|
261
268
|
measured = measured | {int(line.get(_number)) for line in line_nodes}
|
|
@@ -267,6 +274,29 @@ class XmlCoverageReporter(BaseViolationReporter):
|
|
|
267
274
|
|
|
268
275
|
self._info_cache[src_path] = (violations, measured)
|
|
269
276
|
|
|
277
|
+
def _is_violation(self, line, hits_attr):
|
|
278
|
+
"""
|
|
279
|
+
Return whether a coverage `line` node counts as a violation.
|
|
280
|
+
|
|
281
|
+
A line is a violation if it was never executed, or -- when branch
|
|
282
|
+
coverage is enabled -- if it is a partially covered branch.
|
|
283
|
+
"""
|
|
284
|
+
if int(line.get(hits_attr, 0)) == 0:
|
|
285
|
+
return True
|
|
286
|
+
return self._branch_coverage and self._is_partial_branch(line)
|
|
287
|
+
|
|
288
|
+
def _is_partial_branch(self, line):
|
|
289
|
+
"""Return whether a Cobertura `line` node is a partially covered branch."""
|
|
290
|
+
if line.get("branch") != "true":
|
|
291
|
+
return False
|
|
292
|
+
match = self._cobertura_condition_coverage_re.search(
|
|
293
|
+
line.get("condition-coverage", "")
|
|
294
|
+
)
|
|
295
|
+
if not match:
|
|
296
|
+
return False
|
|
297
|
+
covered, total = int(match.group(1)), int(match.group(2))
|
|
298
|
+
return covered < total
|
|
299
|
+
|
|
270
300
|
def violations(self, src_path):
|
|
271
301
|
"""
|
|
272
302
|
See base class comments.
|
|
@@ -47,6 +47,16 @@ def test_show_covered_flag():
|
|
|
47
47
|
assert arg_dict["show_covered"] is True
|
|
48
48
|
|
|
49
49
|
|
|
50
|
+
def test_branch_coverage_defaults_false():
|
|
51
|
+
arg_dict = parse_coverage_args(["reports/coverage.xml"])
|
|
52
|
+
assert arg_dict["branch_coverage"] is False
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_branch_coverage_flag():
|
|
56
|
+
arg_dict = parse_coverage_args(["reports/coverage.xml", "--branch-coverage"])
|
|
57
|
+
assert arg_dict["branch_coverage"] is True
|
|
58
|
+
|
|
59
|
+
|
|
50
60
|
def test_parse_with_multiple_reports():
|
|
51
61
|
argv = [
|
|
52
62
|
"reports/coverage.xml",
|
|
@@ -429,3 +429,42 @@ def test_latin_one_undeclared(tmp_path):
|
|
|
429
429
|
|
|
430
430
|
contents = Snippet.load_contents(str(file))
|
|
431
431
|
assert contents == "I am some latin 1 Â encoded text"
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def test_unconfident_detection_falls_back(tmp_path, mocker):
|
|
435
|
+
# Which single byte encoding chardet picks for a short file varies by
|
|
436
|
+
# version (5 said ISO-8859-1, 6 WINDOWS-1252, 7 MacRoman) so pin the
|
|
437
|
+
# low confidence branch rather than depending on the installed one.
|
|
438
|
+
mocker.patch(
|
|
439
|
+
"diff_cover.snippets.chardet.detect",
|
|
440
|
+
return_value={"encoding": "MacRoman", "confidence": 0.16},
|
|
441
|
+
)
|
|
442
|
+
file = tmp_path / "tmp"
|
|
443
|
+
file.write_bytes("I am some latin 1 Â encoded text".encode("latin1"))
|
|
444
|
+
|
|
445
|
+
contents = Snippet.load_contents(str(file))
|
|
446
|
+
assert contents == "I am some latin 1 Â encoded text"
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def test_confident_detection_is_trusted(tmp_path, mocker):
|
|
450
|
+
mocker.patch(
|
|
451
|
+
"diff_cover.snippets.chardet.detect",
|
|
452
|
+
return_value={"encoding": "MacRoman", "confidence": 0.99},
|
|
453
|
+
)
|
|
454
|
+
file = tmp_path / "tmp"
|
|
455
|
+
file.write_bytes("I am some latin 1 Â encoded text".encode("latin1"))
|
|
456
|
+
|
|
457
|
+
contents = Snippet.load_contents(str(file))
|
|
458
|
+
assert contents == "I am some latin 1 ¬ encoded text"
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def test_detection_returns_no_encoding(tmp_path, mocker):
|
|
462
|
+
mocker.patch(
|
|
463
|
+
"diff_cover.snippets.chardet.detect",
|
|
464
|
+
return_value={"encoding": None, "confidence": None},
|
|
465
|
+
)
|
|
466
|
+
file = tmp_path / "tmp"
|
|
467
|
+
file.write_bytes("I am some latin 1 Â encoded text".encode("latin1"))
|
|
468
|
+
|
|
469
|
+
contents = Snippet.load_contents(str(file))
|
|
470
|
+
assert contents == "I am some latin 1 Â encoded text"
|
|
@@ -333,6 +333,75 @@ class TestXmlCoverageReporterTest:
|
|
|
333
333
|
|
|
334
334
|
assert set() == coverage.violations("file1.java")
|
|
335
335
|
|
|
336
|
+
def test_partial_branch_is_violation_when_branch_coverage_enabled(self):
|
|
337
|
+
# A line that executed (hits=1) but only exercised 1 of its 2
|
|
338
|
+
# branches. With branch coverage enabled this should count as a
|
|
339
|
+
# violation, even though the statement itself ran.
|
|
340
|
+
xml = etree.fromstring("""<?xml version="1.0"?>
|
|
341
|
+
<coverage>
|
|
342
|
+
<packages><classes>
|
|
343
|
+
<class filename="file1.py">
|
|
344
|
+
<lines>
|
|
345
|
+
<line number="1" hits="1"/>
|
|
346
|
+
<line number="2" hits="1" branch="true"
|
|
347
|
+
condition-coverage="50% (1/2)"/>
|
|
348
|
+
<line number="3" hits="1" branch="true"
|
|
349
|
+
condition-coverage="100% (2/2)"/>
|
|
350
|
+
</lines>
|
|
351
|
+
</class>
|
|
352
|
+
</classes></packages>
|
|
353
|
+
</coverage>
|
|
354
|
+
""")
|
|
355
|
+
|
|
356
|
+
coverage = XmlCoverageReporter([xml], branch_coverage=True)
|
|
357
|
+
|
|
358
|
+
# Line 2 is a partially covered branch -> violation.
|
|
359
|
+
# Line 3 is a fully covered branch, line 1 a plain statement -> covered.
|
|
360
|
+
assert coverage.violations("file1.py") == {Violation(2, None)}
|
|
361
|
+
assert coverage.measured_lines("file1.py") == {1, 2, 3}
|
|
362
|
+
|
|
363
|
+
def test_partial_branch_ignored_by_default(self):
|
|
364
|
+
# Without branch coverage enabled, an executed-but-partially-covered
|
|
365
|
+
# branch stays covered, preserving the historical behaviour.
|
|
366
|
+
xml = etree.fromstring("""<?xml version="1.0"?>
|
|
367
|
+
<coverage>
|
|
368
|
+
<packages><classes>
|
|
369
|
+
<class filename="file1.py">
|
|
370
|
+
<lines>
|
|
371
|
+
<line number="1" hits="1"/>
|
|
372
|
+
<line number="2" hits="1" branch="true"
|
|
373
|
+
condition-coverage="50% (1/2)"/>
|
|
374
|
+
</lines>
|
|
375
|
+
</class>
|
|
376
|
+
</classes></packages>
|
|
377
|
+
</coverage>
|
|
378
|
+
""")
|
|
379
|
+
|
|
380
|
+
coverage = XmlCoverageReporter([xml])
|
|
381
|
+
|
|
382
|
+
assert coverage.violations("file1.py") == set()
|
|
383
|
+
assert coverage.measured_lines("file1.py") == {1, 2}
|
|
384
|
+
|
|
385
|
+
def test_uncovered_branch_line_is_single_violation(self):
|
|
386
|
+
# A line that is both never executed (hits=0) and a partial branch is
|
|
387
|
+
# reported once, not twice.
|
|
388
|
+
xml = etree.fromstring("""<?xml version="1.0"?>
|
|
389
|
+
<coverage>
|
|
390
|
+
<packages><classes>
|
|
391
|
+
<class filename="file1.py">
|
|
392
|
+
<lines>
|
|
393
|
+
<line number="1" hits="0" branch="true"
|
|
394
|
+
condition-coverage="0% (0/2)"/>
|
|
395
|
+
</lines>
|
|
396
|
+
</class>
|
|
397
|
+
</classes></packages>
|
|
398
|
+
</coverage>
|
|
399
|
+
""")
|
|
400
|
+
|
|
401
|
+
coverage = XmlCoverageReporter([xml], branch_coverage=True)
|
|
402
|
+
|
|
403
|
+
assert coverage.violations("file1.py") == {Violation(1, None)}
|
|
404
|
+
|
|
336
405
|
def _coverage_xml(self, file_paths, violations, measured, source_paths=None):
|
|
337
406
|
"""
|
|
338
407
|
Build an XML tree with source files specified by `file_paths`.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/templates/github_coverage_annotations.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{diff_cover-10.3.0 → diff_cover-10.4.1}/diff_cover/violationsreporters/java_violations_reporter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/pycodestyle_violations_report_float.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{diff_cover-10.3.0 → diff_cover-10.4.1}/tests/fixtures/typescript_branches_console_report.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|