diff-cover 9.5.0__tar.gz → 9.7.0__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-9.5.0 → diff_cover-9.7.0}/PKG-INFO +2 -2
- {diff_cover-9.5.0 → diff_cover-9.7.0}/README.rst +1 -1
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/command_runner.py +9 -9
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/config_parser.py +2 -5
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/diff_cover_tool.py +11 -1
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/diff_quality_tool.py +15 -16
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/diff_reporter.py +7 -4
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/git_diff.py +1 -1
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/git_path.py +2 -1
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/report_generator.py +26 -7
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/snippets.py +6 -11
- diff_cover-9.7.0/diff_cover/templates/github_coverage_annotations.txt +10 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/util.py +4 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/violationsreporters/base.py +12 -6
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/violationsreporters/java_violations_reporter.py +10 -11
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/violationsreporters/violations_reporter.py +149 -134
- {diff_cover-9.5.0 → diff_cover-9.7.0}/pyproject.toml +56 -31
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_diff_reporter.py +59 -68
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_git_diff.py +4 -1
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_git_path.py +4 -1
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_integration.py +111 -12
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_java_violations_reporter.py +4 -1
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_report_generator.py +60 -2
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_util.py +4 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_violations_reporter.py +69 -16
- diff_cover-9.5.0/tests/fixtures/dotnet_coverage_console_report.txt +0 -10
- {diff_cover-9.5.0 → diff_cover-9.7.0}/LICENSE +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/NOTICE +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/__init__.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/hook.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/hookspecs.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/console_coverage_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/console_quality_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/external_style.css +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/html_coverage_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/html_quality_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/markdown_coverage_report.md +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/markdown_quality_report.md +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/snippet_content.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/snippet_content.md +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/snippet_content.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/templates/snippet_style.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/violationsreporters/__init__.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/__init__.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/add_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/add_html_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/add_json_report.json +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/add_markdown_report.md +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/changed_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/changed_html_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/coverage.xml +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/coverage1.xml +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/coverage2.xml +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/coverage_missing_lines.xml +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/cpp_functions_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/cpp_functions_coverage.lcov +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/delete_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/delete_html_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/dotnet_coverage.xml +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/empty.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/empty_pycodestyle_violations.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/expand_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/external_css_html_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/external_style.css +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_add.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_changed.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_code_dupe.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_cpp.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_cpp_functions.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_delete.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_dotnet.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_external_css.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_lua.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_moved.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_mult.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_python.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_subdir.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_typescript.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_typescript_branches.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_unicode.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_violations.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/git_diff_violations_two_files.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/hello.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/hi.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/html_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/html_report_empty.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/html_report_one_snippet.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/html_report_two_snippets.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/lcov.info +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/lua_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/luacoverage.xml +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/markdown_report_one_snippet.md +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/markdown_report_two_snippets.md +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/moved_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/moved_coverage.xml +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/moved_html_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/mult_inputs_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/mult_inputs_html_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pycodestyle_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pycodestyle_violations_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pycodestyle_violations_report.json +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pycodestyle_violations_report.md +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pycodestyle_violations_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pycodestyle_violations_report_external_css.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pyflakes_two_files.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pyflakes_violations_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pyflakes_violations_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pylint_dupe.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pylint_dupe_violations_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pylint_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pylint_violations_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pylint_violations_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pylint_violations_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/pylintrc +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/real_cpp_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/real_cpp_coverage.lcov +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/real_python_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/real_python_coverage.lcov +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/real_typescript_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/real_typescript_coverage.lcov +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/show_uncovered_lines_console.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet.css +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_8859.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_arabic_output.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_default.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_invalid_violations.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_list.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_list.md +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_list2.md +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_list3.md +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_no_filename_ext.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_src.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_src2.cpp +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_src3.cpp +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_unicode.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_unicode.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/snippet_unicode_html_output.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/subdir_coverage_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/subdir_coverage_html_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/test_src.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/typescript_branches_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/typescript_branches_coverage.lcov +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/unicode_console_report.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/unicode_coverage.xml +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/unicode_html_report.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/unicode_test_src.txt +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/fixtures/violations_test_file.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/helpers.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/snippet_list_unicode.html +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_clover_violations_reporter/test.xml +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_clover_violations_reporter.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_config_parser.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_diff_cover_main.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_diff_cover_tool.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_diff_quality_main.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_git_diff_file.py +0 -0
- {diff_cover-9.5.0 → diff_cover-9.7.0}/tests/test_snippets.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: diff_cover
|
|
3
|
-
Version: 9.
|
|
3
|
+
Version: 9.7.0
|
|
4
4
|
Summary: Run coverage and linting reports on diffs
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Author: See Contributors
|
|
@@ -161,7 +161,7 @@ You can use diff-cover to see quality reports on the diff as well by running
|
|
|
161
161
|
diff-quality --violations=<tool>
|
|
162
162
|
|
|
163
163
|
Where ``tool`` is the quality checker to use. Currently ``pycodestyle``, ``pyflakes``,
|
|
164
|
-
``flake8``, ``pylint``, ``checkstyle``, ``checkstylexml``, ``ruff
|
|
164
|
+
``flake8``, ``pylint``, ``checkstyle``, ``checkstylexml``, ``ruff.check``, ``clang`` are supported, but more
|
|
165
165
|
checkers can (and should!) be supported. See the section "Adding `diff-quality``
|
|
166
166
|
Support for a New Quality Checker".
|
|
167
167
|
|
|
@@ -129,7 +129,7 @@ You can use diff-cover to see quality reports on the diff as well by running
|
|
|
129
129
|
diff-quality --violations=<tool>
|
|
130
130
|
|
|
131
131
|
Where ``tool`` is the quality checker to use. Currently ``pycodestyle``, ``pyflakes``,
|
|
132
|
-
``flake8``, ``pylint``, ``checkstyle``, ``checkstylexml``, ``ruff
|
|
132
|
+
``flake8``, ``pylint``, ``checkstyle``, ``checkstylexml``, ``ruff.check``, ``clang`` are supported, but more
|
|
133
133
|
checkers can (and should!) be supported. See the section "Adding `diff-quality``
|
|
134
134
|
Support for a New Quality Checker".
|
|
135
135
|
|
|
@@ -24,12 +24,12 @@ def execute(command, exit_codes=None):
|
|
|
24
24
|
exit_codes = [0]
|
|
25
25
|
|
|
26
26
|
stdout_pipe = subprocess.PIPE
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
with subprocess.Popen(command, stdout=stdout_pipe, stderr=stdout_pipe) as process:
|
|
28
|
+
try:
|
|
29
|
+
stdout, stderr = process.communicate()
|
|
30
|
+
except OSError:
|
|
31
|
+
sys.stderr.write(" ".join(_ensure_unicode(cmd) for cmd in command))
|
|
32
|
+
raise
|
|
33
33
|
|
|
34
34
|
stderr = _ensure_unicode(stderr)
|
|
35
35
|
if process.returncode not in exit_codes:
|
|
@@ -43,10 +43,10 @@ def run_command_for_code(command):
|
|
|
43
43
|
Returns command's exit code.
|
|
44
44
|
"""
|
|
45
45
|
try:
|
|
46
|
-
|
|
46
|
+
with subprocess.Popen(
|
|
47
47
|
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
48
|
-
)
|
|
49
|
-
|
|
48
|
+
) as process:
|
|
49
|
+
process.communicate()
|
|
50
50
|
except FileNotFoundError:
|
|
51
51
|
return 1
|
|
52
52
|
return process.returncode
|
|
@@ -6,15 +6,12 @@ try:
|
|
|
6
6
|
|
|
7
7
|
_HAS_TOML = True
|
|
8
8
|
except ImportError: # pragma: no cover
|
|
9
|
-
_HAS_TOML = False
|
|
10
|
-
|
|
11
|
-
if not _HAS_TOML:
|
|
12
9
|
try:
|
|
13
10
|
import tomllib as toml
|
|
14
11
|
|
|
15
12
|
_HAS_TOML = True
|
|
16
|
-
except ImportError:
|
|
17
|
-
|
|
13
|
+
except ImportError:
|
|
14
|
+
_HAS_TOML = False
|
|
18
15
|
|
|
19
16
|
|
|
20
17
|
class Tool(enum.Enum):
|
|
@@ -12,6 +12,7 @@ from diff_cover.diff_reporter import GitDiffReporter
|
|
|
12
12
|
from diff_cover.git_diff import GitDiffFileTool, GitDiffTool
|
|
13
13
|
from diff_cover.git_path import GitPathTool
|
|
14
14
|
from diff_cover.report_generator import (
|
|
15
|
+
GitHubAnnotationsReportGenerator,
|
|
15
16
|
HtmlReportGenerator,
|
|
16
17
|
JsonReportGenerator,
|
|
17
18
|
MarkdownReportGenerator,
|
|
@@ -266,9 +267,18 @@ def generate_coverage_report(
|
|
|
266
267
|
if "markdown" in report_formats:
|
|
267
268
|
markdown_report = report_formats["markdown"] or MARKDOWN_REPORT_DEFAULT_PATH
|
|
268
269
|
reporter = MarkdownReportGenerator(coverage, diff)
|
|
269
|
-
with
|
|
270
|
+
with open_file(markdown_report, "wb") as output_file:
|
|
270
271
|
reporter.generate_report(output_file)
|
|
271
272
|
|
|
273
|
+
if "github-annotations" in report_formats:
|
|
274
|
+
# Github annotations are always written to stdout, but we can use different types
|
|
275
|
+
reporter = GitHubAnnotationsReportGenerator(
|
|
276
|
+
coverage,
|
|
277
|
+
diff,
|
|
278
|
+
report_formats["github-annotations"],
|
|
279
|
+
)
|
|
280
|
+
reporter.generate_report(sys.stdout.buffer)
|
|
281
|
+
|
|
272
282
|
# Generate the report for stdout
|
|
273
283
|
reporter = StringReportGenerator(coverage, diff, show_uncovered)
|
|
274
284
|
output_file = io.BytesIO() if quiet else sys.stdout.buffer
|
|
@@ -3,6 +3,7 @@ Implement the command-line tool interface for diff_quality.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import argparse
|
|
6
|
+
import contextlib
|
|
6
7
|
import io
|
|
7
8
|
import logging
|
|
8
9
|
import os
|
|
@@ -56,6 +57,7 @@ from diff_cover.violationsreporters.violations_reporter import (
|
|
|
56
57
|
PylintDriver,
|
|
57
58
|
flake8_driver,
|
|
58
59
|
jshint_driver,
|
|
60
|
+
mypy_driver,
|
|
59
61
|
pycodestyle_driver,
|
|
60
62
|
pydocstyle_driver,
|
|
61
63
|
pyflakes_driver,
|
|
@@ -66,6 +68,7 @@ from diff_cover.violationsreporters.violations_reporter import (
|
|
|
66
68
|
QUALITY_DRIVERS = {
|
|
67
69
|
"clang": ClangFormatDriver(),
|
|
68
70
|
"cppcheck": CppcheckDriver(),
|
|
71
|
+
"mypy": mypy_driver,
|
|
69
72
|
"pycodestyle": pycodestyle_driver,
|
|
70
73
|
"pyflakes": pyflakes_driver,
|
|
71
74
|
"pylint": PylintDriver(),
|
|
@@ -81,8 +84,8 @@ QUALITY_DRIVERS = {
|
|
|
81
84
|
"shellcheck": shellcheck_driver,
|
|
82
85
|
}
|
|
83
86
|
|
|
84
|
-
VIOLATION_CMD_HELP =
|
|
85
|
-
sorted(QUALITY_DRIVERS)
|
|
87
|
+
VIOLATION_CMD_HELP = (
|
|
88
|
+
f"Which code quality tool to use ({'/'.join(sorted(QUALITY_DRIVERS))})"
|
|
86
89
|
)
|
|
87
90
|
INPUT_REPORTS_HELP = "Which violations reports to use"
|
|
88
91
|
OPTIONS_HELP = "Options to be passed to the violations tool"
|
|
@@ -315,20 +318,24 @@ def main(argv=None, directory=None):
|
|
|
315
318
|
plugin_manager.add_hookspecs(hookspecs)
|
|
316
319
|
plugin_manager.load_setuptools_entrypoints("diff_cover")
|
|
317
320
|
|
|
318
|
-
hooks =
|
|
319
|
-
plugin_manager.hook.diff_cover_report_quality # pylint: disable=no-member
|
|
320
|
-
)
|
|
321
|
+
hooks = plugin_manager.hook.diff_cover_report_quality
|
|
321
322
|
for hookimpl in hooks.get_hookimpls():
|
|
322
323
|
if hookimpl.plugin_name == tool:
|
|
323
324
|
reporter_factory_fn = hookimpl.function
|
|
324
325
|
break
|
|
325
326
|
|
|
326
|
-
|
|
327
|
-
|
|
327
|
+
# If none of the reporter, driver, or reporter_factory_fn are set
|
|
328
|
+
if not any((reporter, driver, reporter_factory_fn)):
|
|
329
|
+
LOGGER.error("Quality tool not recognized: '%s'", tool)
|
|
330
|
+
return 1
|
|
331
|
+
|
|
332
|
+
with contextlib.ExitStack() as stack:
|
|
328
333
|
try:
|
|
334
|
+
input_reports = []
|
|
329
335
|
for path in arg_dict["input_reports"]:
|
|
330
336
|
try:
|
|
331
|
-
|
|
337
|
+
file_handle = stack.enter_context(open(path, "rb"))
|
|
338
|
+
input_reports.append(file_handle)
|
|
332
339
|
except OSError:
|
|
333
340
|
LOGGER.error("Could not load report '%s'", path)
|
|
334
341
|
return 1
|
|
@@ -373,14 +380,6 @@ def main(argv=None, directory=None):
|
|
|
373
380
|
except OSError as exc:
|
|
374
381
|
LOGGER.error("Failure: '%s'", str(exc))
|
|
375
382
|
return 1
|
|
376
|
-
# Close any reports we opened
|
|
377
|
-
finally:
|
|
378
|
-
for file_handle in input_reports:
|
|
379
|
-
file_handle.close()
|
|
380
|
-
|
|
381
|
-
else:
|
|
382
|
-
LOGGER.error("Quality tool not recognized: '%s'", tool)
|
|
383
|
-
return 1
|
|
384
383
|
|
|
385
384
|
|
|
386
385
|
if __name__ == "__main__":
|
|
@@ -9,6 +9,7 @@ import re
|
|
|
9
9
|
from abc import ABC, abstractmethod
|
|
10
10
|
|
|
11
11
|
from diff_cover.git_diff import GitDiffError
|
|
12
|
+
from diff_cover.util import to_unix_path, to_unix_paths
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class BaseDiffReporter(ABC):
|
|
@@ -85,7 +86,7 @@ class BaseDiffReporter(ABC):
|
|
|
85
86
|
include = self._include
|
|
86
87
|
if include:
|
|
87
88
|
for pattern in include:
|
|
88
|
-
if path in glob.glob(pattern, recursive=True):
|
|
89
|
+
if path in to_unix_paths(glob.glob(pattern, recursive=True)):
|
|
89
90
|
break # file is included
|
|
90
91
|
else:
|
|
91
92
|
return True
|
|
@@ -200,7 +201,7 @@ class GitDiffReporter(BaseDiffReporter):
|
|
|
200
201
|
|
|
201
202
|
# Look up the modified lines for the source file
|
|
202
203
|
# If no lines modified, return an empty list
|
|
203
|
-
return diff_dict.get(src_path, [])
|
|
204
|
+
return diff_dict.get(to_unix_path(src_path), [])
|
|
204
205
|
|
|
205
206
|
def _get_included_diff_results(self):
|
|
206
207
|
"""
|
|
@@ -237,12 +238,13 @@ class GitDiffReporter(BaseDiffReporter):
|
|
|
237
238
|
diff_dict = self._parse_diff_str(diff_str)
|
|
238
239
|
|
|
239
240
|
for src_path, (added_lines, deleted_lines) in diff_dict.items():
|
|
241
|
+
src_path = to_unix_path(src_path)
|
|
240
242
|
if not self._validate_path_to_diff(src_path):
|
|
241
243
|
continue
|
|
242
244
|
|
|
243
245
|
# Remove any lines from the dict that have been deleted
|
|
244
246
|
# Include any lines that have been added
|
|
245
|
-
result_dict[src_path] = [
|
|
247
|
+
result_dict[to_unix_path(src_path)] = [
|
|
246
248
|
line
|
|
247
249
|
for line in result_dict.get(src_path, [])
|
|
248
250
|
if line not in deleted_lines
|
|
@@ -332,6 +334,7 @@ class GitDiffReporter(BaseDiffReporter):
|
|
|
332
334
|
|
|
333
335
|
# Parse the diff string into sections by source file
|
|
334
336
|
for line in diff_str.split("\n"):
|
|
337
|
+
line = line.rstrip()
|
|
335
338
|
# If the line starts with "diff --git"
|
|
336
339
|
# or "diff --cc" (in the case of a merge conflict)
|
|
337
340
|
# then it is the start of a new source file
|
|
@@ -501,7 +504,7 @@ class GitDiffReporter(BaseDiffReporter):
|
|
|
501
504
|
number is included once and the lines are ordered sequentially.
|
|
502
505
|
"""
|
|
503
506
|
|
|
504
|
-
if
|
|
507
|
+
if not line_numbers:
|
|
505
508
|
return []
|
|
506
509
|
|
|
507
510
|
# Ensure lines are unique by putting them in a set
|
|
@@ -132,7 +132,7 @@ class GitDiffFileTool(GitDiffTool):
|
|
|
132
132
|
Raises a `GitDiffError` if the file cannot be read.
|
|
133
133
|
"""
|
|
134
134
|
try:
|
|
135
|
-
with open(self.diff_file_path, "r") as file:
|
|
135
|
+
with open(self.diff_file_path, "r", encoding="utf-8") as file:
|
|
136
136
|
return file.read()
|
|
137
137
|
except OSError as e:
|
|
138
138
|
error_message = (
|
|
@@ -6,6 +6,7 @@ import os
|
|
|
6
6
|
import sys
|
|
7
7
|
|
|
8
8
|
from diff_cover.command_runner import execute
|
|
9
|
+
from diff_cover.util import to_unix_path
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class GitPathTool:
|
|
@@ -51,7 +52,7 @@ class GitPathTool:
|
|
|
51
52
|
# and src_path is `other_package/some_file.py`
|
|
52
53
|
# search for `/home/user/work/diff-cover/other_package/some_file.py`
|
|
53
54
|
|
|
54
|
-
return os.path.join(cls._root, src_path)
|
|
55
|
+
return to_unix_path(os.path.join(cls._root, src_path))
|
|
55
56
|
|
|
56
57
|
@classmethod
|
|
57
58
|
def _git_root(cls):
|
|
@@ -4,13 +4,13 @@ Classes for generating diff coverage reports.
|
|
|
4
4
|
|
|
5
5
|
import contextlib
|
|
6
6
|
import json
|
|
7
|
-
import os
|
|
8
7
|
from abc import ABC, abstractmethod
|
|
9
8
|
from gettext import gettext, ngettext
|
|
10
9
|
|
|
11
10
|
from jinja2 import Environment, PackageLoader, select_autoescape
|
|
12
11
|
|
|
13
12
|
from diff_cover.snippets import Snippet
|
|
13
|
+
from diff_cover.util import to_unix_path
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class DiffViolations:
|
|
@@ -149,10 +149,7 @@ class BaseReportGenerator(ABC):
|
|
|
149
149
|
"""
|
|
150
150
|
|
|
151
151
|
return sum(
|
|
152
|
-
|
|
153
|
-
len(summary.measured_lines)
|
|
154
|
-
for summary in self._diff_violations().values()
|
|
155
|
-
]
|
|
152
|
+
len(summary.measured_lines) for summary in self._diff_violations().values()
|
|
156
153
|
)
|
|
157
154
|
|
|
158
155
|
def total_num_violations(self):
|
|
@@ -193,13 +190,14 @@ class BaseReportGenerator(ABC):
|
|
|
193
190
|
|
|
194
191
|
To make this efficient, we cache and reuse the result.
|
|
195
192
|
"""
|
|
193
|
+
|
|
196
194
|
src_paths_changed = self._diff.src_paths_changed()
|
|
197
195
|
if not self._diff_violations_dict:
|
|
198
196
|
try:
|
|
199
197
|
violations = self._violations.violations_batch(src_paths_changed)
|
|
200
198
|
self._diff_violations_dict = {
|
|
201
|
-
|
|
202
|
-
violations.get(
|
|
199
|
+
to_unix_path(src_path): DiffViolations(
|
|
200
|
+
violations.get(to_unix_path(src_path), []),
|
|
203
201
|
self._violations.measured_lines(src_path),
|
|
204
202
|
self._diff.lines_changed(src_path),
|
|
205
203
|
)
|
|
@@ -420,6 +418,27 @@ class StringReportGenerator(TemplateReportGenerator):
|
|
|
420
418
|
self.include_snippets = show_uncovered
|
|
421
419
|
|
|
422
420
|
|
|
421
|
+
class GitHubAnnotationsReportGenerator(TemplateReportGenerator):
|
|
422
|
+
"""
|
|
423
|
+
Generate a diff coverage report for GitHub annotations.
|
|
424
|
+
https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message
|
|
425
|
+
https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-notice-message
|
|
426
|
+
https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message
|
|
427
|
+
https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
|
|
428
|
+
"""
|
|
429
|
+
|
|
430
|
+
template_path = "github_coverage_annotations.txt"
|
|
431
|
+
|
|
432
|
+
def __init__(self, violations_reporter, diff_reporter, annotations_type):
|
|
433
|
+
super().__init__(violations_reporter, diff_reporter)
|
|
434
|
+
self.annotations_type = annotations_type
|
|
435
|
+
|
|
436
|
+
def _context(self):
|
|
437
|
+
context = super().report_dict()
|
|
438
|
+
context.update({"annotations_type": self.annotations_type})
|
|
439
|
+
return context
|
|
440
|
+
|
|
441
|
+
|
|
423
442
|
class HtmlReportGenerator(TemplateReportGenerator):
|
|
424
443
|
"""
|
|
425
444
|
Generate an HTML formatted diff coverage report.
|
|
@@ -128,21 +128,16 @@ class Snippet:
|
|
|
128
128
|
if i in self._violation_lines:
|
|
129
129
|
notice = "!"
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
text += format_string.format(notice, i, line)
|
|
131
|
+
text += f"{notice} {i:>{line_number_length}} {line}"
|
|
133
132
|
|
|
134
|
-
header = "Lines
|
|
133
|
+
header = f"Lines {self._start_line}-{self._last_line}\n\n"
|
|
135
134
|
if self._lexer_name in self.LEXER_TO_MARKDOWN_CODE_HINT:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
+ "\n"
|
|
140
|
-
+ text
|
|
141
|
-
+ "\n```\n"
|
|
142
|
-
)
|
|
135
|
+
code_hint = self.LEXER_TO_MARKDOWN_CODE_HINT[self._lexer_name]
|
|
136
|
+
code_block = f"""```{code_hint}\n{text}\n```\n"""
|
|
137
|
+
return header + code_block
|
|
143
138
|
|
|
144
139
|
# unknown programming language, return a non-decorated fenced code block:
|
|
145
|
-
return "```\n
|
|
140
|
+
return f"""```\n{text}\n```\n"""
|
|
146
141
|
|
|
147
142
|
def terminal(self):
|
|
148
143
|
"""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{% if src_stats %}
|
|
2
|
+
{% for src_path, stats in src_stats|dictsort %}
|
|
3
|
+
{% if stats.percent_covered < 100 %}
|
|
4
|
+
{% for line in stats.violation_lines %}
|
|
5
|
+
{% set splitLines = line.split("-") %}
|
|
6
|
+
::{{ annotations_type }} file={{ src_path }},line={{ splitLines[0] }}{% if splitLines[1] %},endLine={{ splitLines[1] }}{% endif %},title=Missing Coverage::Line {{ line }} missing coverage
|
|
7
|
+
{% endfor %}
|
|
8
|
+
{% endif %}
|
|
9
|
+
{% endfor %}
|
|
10
|
+
{% endif %}
|
|
@@ -47,6 +47,10 @@ def to_unix_path(path):
|
|
|
47
47
|
return posixpath.normpath(os.path.normcase(path).replace("\\", "/"))
|
|
48
48
|
|
|
49
49
|
|
|
50
|
+
def to_unix_paths(paths):
|
|
51
|
+
return [to_unix_path(path) for path in paths]
|
|
52
|
+
|
|
53
|
+
|
|
50
54
|
def to_unescaped_filename(filename: str) -> str:
|
|
51
55
|
"""Try to unescape the given filename.
|
|
52
56
|
|
|
@@ -6,6 +6,7 @@ from abc import ABC, abstractmethod
|
|
|
6
6
|
from collections import defaultdict, namedtuple
|
|
7
7
|
|
|
8
8
|
from diff_cover.command_runner import execute, run_command_for_code
|
|
9
|
+
from diff_cover.util import to_unix_path
|
|
9
10
|
|
|
10
11
|
Violation = namedtuple("Violation", "line, message")
|
|
11
12
|
|
|
@@ -60,7 +61,7 @@ class BaseViolationReporter(ABC):
|
|
|
60
61
|
"""
|
|
61
62
|
# An existing quality plugin "sqlfluff" depends on this
|
|
62
63
|
# being not abstract and returning None
|
|
63
|
-
|
|
64
|
+
del src_path
|
|
64
65
|
|
|
65
66
|
def name(self):
|
|
66
67
|
"""
|
|
@@ -156,6 +157,10 @@ class QualityReporter(BaseViolationReporter):
|
|
|
156
157
|
self.violations_dict = self.driver.parse_reports(self.reports)
|
|
157
158
|
return self.violations_dict[src_path]
|
|
158
159
|
|
|
160
|
+
if not os.path.exists(src_path):
|
|
161
|
+
self.violations_dict[src_path] = []
|
|
162
|
+
return self.violations_dict[src_path]
|
|
163
|
+
|
|
159
164
|
if self.driver_tool_installed is None:
|
|
160
165
|
self.driver_tool_installed = self.driver.installed()
|
|
161
166
|
if not self.driver_tool_installed:
|
|
@@ -165,8 +170,7 @@ class QualityReporter(BaseViolationReporter):
|
|
|
165
170
|
if self.options:
|
|
166
171
|
for arg in self.options.split():
|
|
167
172
|
command.append(arg)
|
|
168
|
-
|
|
169
|
-
command.append(src_path.encode(sys.getfilesystemencoding()))
|
|
173
|
+
command.append(src_path.encode(sys.getfilesystemencoding()))
|
|
170
174
|
|
|
171
175
|
stdout, stderr = execute(command, self.driver.exit_codes)
|
|
172
176
|
output = stderr if self.driver.output_stderr else stdout
|
|
@@ -229,13 +233,15 @@ class RegexBasedDriver(QualityDriver):
|
|
|
229
233
|
if self.expression.flags & re.MULTILINE:
|
|
230
234
|
matches = (match for match in re.finditer(self.expression, report))
|
|
231
235
|
else:
|
|
232
|
-
matches = (
|
|
236
|
+
matches = (
|
|
237
|
+
self.expression.match(line.rstrip()) for line in report.split("\n")
|
|
238
|
+
)
|
|
233
239
|
for match in matches:
|
|
234
240
|
if match is not None:
|
|
235
241
|
src, line_number, message = match.groups()
|
|
236
242
|
# Transform src to a relative path, if it isn't already
|
|
237
|
-
src = os.path.relpath(src)
|
|
238
|
-
violation = Violation(int(line_number), message)
|
|
243
|
+
src = to_unix_path(os.path.relpath(src))
|
|
244
|
+
violation = Violation(int(line_number), message.rstrip())
|
|
239
245
|
violations_dict[src].append(violation)
|
|
240
246
|
return violations_dict
|
|
241
247
|
|
{diff_cover-9.5.0 → diff_cover-9.7.0}/diff_cover/violationsreporters/java_violations_reporter.py
RENAMED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
Classes for querying the information in a test coverage report.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import os
|
|
6
5
|
import xml.etree.ElementTree as etree
|
|
7
6
|
from collections import defaultdict
|
|
8
7
|
|
|
9
8
|
from diff_cover.command_runner import run_command_for_code
|
|
10
9
|
from diff_cover.git_path import GitPathTool
|
|
10
|
+
from diff_cover.util import to_unix_path
|
|
11
11
|
from diff_cover.violationsreporters.base import (
|
|
12
12
|
QualityDriver,
|
|
13
13
|
RegexBasedDriver,
|
|
@@ -66,12 +66,11 @@ class CheckstyleXmlDriver(QualityDriver):
|
|
|
66
66
|
for file_tree in files:
|
|
67
67
|
for error in file_tree.findall("error"):
|
|
68
68
|
line_number = error.get("line")
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
)
|
|
72
|
-
violation = Violation(int(line_number), error_str)
|
|
69
|
+
severity = error.get("severity")
|
|
70
|
+
message = error.get("message")
|
|
71
|
+
violation = Violation(int(line_number), f"{severity}: {message}")
|
|
73
72
|
filename = GitPathTool.relative_path(file_tree.get("name"))
|
|
74
|
-
violations_dict[filename].append(violation)
|
|
73
|
+
violations_dict[to_unix_path(filename)].append(violation)
|
|
75
74
|
return violations_dict
|
|
76
75
|
|
|
77
76
|
def installed(self):
|
|
@@ -113,7 +112,7 @@ class FindbugsXmlDriver(QualityDriver):
|
|
|
113
112
|
error_str = f"{category}: {short_message}"
|
|
114
113
|
violation = Violation(line_number, error_str)
|
|
115
114
|
filename = GitPathTool.relative_path(line.get("sourcepath"))
|
|
116
|
-
violations_dict[filename].append(violation)
|
|
115
|
+
violations_dict[to_unix_path(filename)].append(violation)
|
|
117
116
|
|
|
118
117
|
return violations_dict
|
|
119
118
|
|
|
@@ -149,11 +148,11 @@ class PmdXmlDriver(QualityDriver):
|
|
|
149
148
|
for node_file in node_files:
|
|
150
149
|
for error in node_file.findall("violation"):
|
|
151
150
|
line_number = error.get("beginline")
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
rule = error.get("rule")
|
|
152
|
+
message = error.text.strip()
|
|
153
|
+
violation = Violation(int(line_number), f"{rule}: {message}")
|
|
154
154
|
filename = GitPathTool.relative_path(node_file.get("name"))
|
|
155
|
-
filename
|
|
156
|
-
violations_dict[filename].append(violation)
|
|
155
|
+
violations_dict[to_unix_path(filename)].append(violation)
|
|
157
156
|
|
|
158
157
|
return violations_dict
|
|
159
158
|
|