diff --git a/diff_cover/git_diff.py b/diff_cover/git_diff.py
index 8bc6c1fa..cd46bbc7 100644
--- a/diff_cover/git_diff.py
+++ b/diff_cover/git_diff.py
@@ -72,14 +72,10 @@ def diff_committed(self, compare_branch="origin/main"):
)[0]
except CommandError as e:
if "unknown revision" in str(e):
- raise ValueError(
- dedent(
- f"""
+ raise ValueError(dedent(f"""
Could not find the branch to compare to. Does '{compare_branch}' exist?
the `--compare-branch` argument allows you to set a different branch.
- """
- )
- ) from e
+ """)) from e
raise
def diff_unstaged(self):
diff --git a/diff_cover/violationsreporters/violations_reporter.py b/diff_cover/violationsreporters/violations_reporter.py
index bfe61ca1..585cdc6e 100644
--- a/diff_cover/violationsreporters/violations_reporter.py
+++ b/diff_cover/violationsreporters/violations_reporter.py
@@ -831,7 +831,7 @@ def parse_reports(self, reports):
# Ignore any line that isn't matched
# (for example, snippets from the source code)
if match is not None:
- (cppcheck_src_path, line_number, message) = match.groups()
+ cppcheck_src_path, line_number, message = match.groups()
violation = Violation(int(line_number), message)
violations_dict[util.to_unix_path(cppcheck_src_path)].append(
diff --git a/poetry.lock b/poetry.lock
index 0696c20e..b6739a9e 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand.
[[package]]
name = "astroid"
@@ -17,46 +17,46 @@ typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""}
[[package]]
name = "black"
-version = "25.12.0"
+version = "26.1.0"
description = "The uncompromising code formatter."
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "black-25.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f85ba1ad15d446756b4ab5f3044731bf68b777f8f9ac9cdabd2425b97cd9c4e8"},
- {file = "black-25.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:546eecfe9a3a6b46f9d69d8a642585a6eaf348bcbbc4d87a19635570e02d9f4a"},
- {file = "black-25.12.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:17dcc893da8d73d8f74a596f64b7c98ef5239c2cd2b053c0f25912c4494bf9ea"},
- {file = "black-25.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:09524b0e6af8ba7a3ffabdfc7a9922fb9adef60fed008c7cd2fc01f3048e6e6f"},
- {file = "black-25.12.0-cp310-cp310-win_arm64.whl", hash = "sha256:b162653ed89eb942758efeb29d5e333ca5bb90e5130216f8369857db5955a7da"},
- {file = "black-25.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d0cfa263e85caea2cff57d8f917f9f51adae8e20b610e2b23de35b5b11ce691a"},
- {file = "black-25.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a2f578ae20c19c50a382286ba78bfbeafdf788579b053d8e4980afb079ab9be"},
- {file = "black-25.12.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e1b65634b0e471d07ff86ec338819e2ef860689859ef4501ab7ac290431f9b"},
- {file = "black-25.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a3fa71e3b8dd9f7c6ac4d818345237dfb4175ed3bf37cd5a581dbc4c034f1ec5"},
- {file = "black-25.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:51e267458f7e650afed8445dc7edb3187143003d52a1b710c7321aef22aa9655"},
- {file = "black-25.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:31f96b7c98c1ddaeb07dc0f56c652e25bdedaac76d5b68a059d998b57c55594a"},
- {file = "black-25.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05dd459a19e218078a1f98178c13f861fe6a9a5f88fc969ca4d9b49eb1809783"},
- {file = "black-25.12.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1f68c5eff61f226934be6b5b80296cf6939e5d2f0c2f7d543ea08b204bfaf59"},
- {file = "black-25.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:274f940c147ddab4442d316b27f9e332ca586d39c85ecf59ebdea82cc9ee8892"},
- {file = "black-25.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:169506ba91ef21e2e0591563deda7f00030cb466e747c4b09cb0a9dae5db2f43"},
- {file = "black-25.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a05ddeb656534c3e27a05a29196c962877c83fa5503db89e68857d1161ad08a5"},
- {file = "black-25.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9ec77439ef3e34896995503865a85732c94396edcc739f302c5673a2315e1e7f"},
- {file = "black-25.12.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e509c858adf63aa61d908061b52e580c40eae0dfa72415fa47ac01b12e29baf"},
- {file = "black-25.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:252678f07f5bac4ff0d0e9b261fbb029fa530cfa206d0a636a34ab445ef8ca9d"},
- {file = "black-25.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:bc5b1c09fe3c931ddd20ee548511c64ebf964ada7e6f0763d443947fd1c603ce"},
- {file = "black-25.12.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:0a0953b134f9335c2434864a643c842c44fba562155c738a2a37a4d61f00cad5"},
- {file = "black-25.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2355bbb6c3b76062870942d8cc450d4f8ac71f9c93c40122762c8784df49543f"},
- {file = "black-25.12.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9678bd991cc793e81d19aeeae57966ee02909877cb65838ccffef24c3ebac08f"},
- {file = "black-25.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:97596189949a8aad13ad12fcbb4ae89330039b96ad6742e6f6b45e75ad5cfd83"},
- {file = "black-25.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:778285d9ea197f34704e3791ea9404cd6d07595745907dd2ce3da7a13627b29b"},
- {file = "black-25.12.0-py3-none-any.whl", hash = "sha256:48ceb36c16dbc84062740049eef990bb2ce07598272e673c17d1a7720c71c828"},
- {file = "black-25.12.0.tar.gz", hash = "sha256:8d3dd9cea14bff7ddc0eb243c811cdb1a011ebb4800a5f0335a01a68654796a7"},
+ {file = "black-26.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ca699710dece84e3ebf6e92ee15f5b8f72870ef984bf944a57a777a48357c168"},
+ {file = "black-26.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e8e75dabb6eb83d064b0db46392b25cabb6e784ea624219736e8985a6b3675d"},
+ {file = "black-26.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb07665d9a907a1a645ee41a0df8a25ffac8ad9c26cdb557b7b88eeeeec934e0"},
+ {file = "black-26.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:7ed300200918147c963c87700ccf9966dceaefbbb7277450a8d646fc5646bf24"},
+ {file = "black-26.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:c5b7713daea9bf943f79f8c3b46f361cc5229e0e604dcef6a8bb6d1c37d9df89"},
+ {file = "black-26.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3cee1487a9e4c640dc7467aaa543d6c0097c391dc8ac74eb313f2fbf9d7a7cb5"},
+ {file = "black-26.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d62d14ca31c92adf561ebb2e5f2741bf8dea28aef6deb400d49cca011d186c68"},
+ {file = "black-26.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb1dafbbaa3b1ee8b4550a84425aac8874e5f390200f5502cf3aee4a2acb2f14"},
+ {file = "black-26.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:101540cb2a77c680f4f80e628ae98bd2bd8812fb9d72ade4f8995c5ff019e82c"},
+ {file = "black-26.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:6f3977a16e347f1b115662be07daa93137259c711e526402aa444d7a88fdc9d4"},
+ {file = "black-26.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6eeca41e70b5f5c84f2f913af857cf2ce17410847e1d54642e658e078da6544f"},
+ {file = "black-26.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dd39eef053e58e60204f2cdf059e2442e2eb08f15989eefe259870f89614c8b6"},
+ {file = "black-26.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9459ad0d6cd483eacad4c6566b0f8e42af5e8b583cee917d90ffaa3778420a0a"},
+ {file = "black-26.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a19915ec61f3a8746e8b10adbac4a577c6ba9851fa4a9e9fbfbcf319887a5791"},
+ {file = "black-26.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:643d27fb5facc167c0b1b59d0315f2674a6e950341aed0fc05cf307d22bf4954"},
+ {file = "black-26.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ba1d768fbfb6930fc93b0ecc32a43d8861ded16f47a40f14afa9bb04ab93d304"},
+ {file = "black-26.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2b807c240b64609cb0e80d2200a35b23c7df82259f80bef1b2c96eb422b4aac9"},
+ {file = "black-26.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1de0f7d01cc894066a1153b738145b194414cc6eeaad8ef4397ac9abacf40f6b"},
+ {file = "black-26.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:91a68ae46bf07868963671e4d05611b179c2313301bd756a89ad4e3b3db2325b"},
+ {file = "black-26.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:be5e2fe860b9bd9edbf676d5b60a9282994c03fbbd40fe8f5e75d194f96064ca"},
+ {file = "black-26.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9dc8c71656a79ca49b8d3e2ce8103210c9481c57798b48deeb3a8bb02db5f115"},
+ {file = "black-26.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b22b3810451abe359a964cc88121d57f7bce482b53a066de0f1584988ca36e79"},
+ {file = "black-26.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53c62883b3f999f14e5d30b5a79bd437236658ad45b2f853906c7cbe79de00af"},
+ {file = "black-26.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:f016baaadc423dc960cdddf9acae679e71ee02c4c341f78f3179d7e4819c095f"},
+ {file = "black-26.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:66912475200b67ef5a0ab665011964bf924745103f51977a78b4fb92a9fc1bf0"},
+ {file = "black-26.1.0-py3-none-any.whl", hash = "sha256:1054e8e47ebd686e078c0bb0eaf31e6ce69c966058d122f2c0c950311f9f3ede"},
+ {file = "black-26.1.0.tar.gz", hash = "sha256:d294ac3340eef9c9eb5d29288e96dc719ff269a88e27b396340459dd85da4c58"},
]
[package.dependencies]
click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
packaging = ">=22.0"
-pathspec = ">=0.9.0"
+pathspec = ">=1.0.0"
platformdirs = ">=2"
pytokens = ">=0.3.0"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
@@ -102,7 +102,7 @@ description = "Cross-platform colored terminal text."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
groups = ["dev"]
-markers = "platform_system == \"Windows\" or sys_platform == \"win32\""
+markers = "sys_platform == \"win32\" or platform_system == \"Windows\""
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
@@ -270,7 +270,7 @@ description = "Backport of PEP 654 (exception groups)"
optional = false
python-versions = ">=3.7"
groups = ["dev"]
-markers = "python_version == \"3.10\""
+markers = "python_version < \"3.11\""
files = [
{file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"},
{file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"},
@@ -487,16 +487,22 @@ files = [
[[package]]
name = "pathspec"
-version = "0.12.1"
+version = "1.0.4"
description = "Utility library for gitignore style pattern matching of file paths."
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
groups = ["dev"]
files = [
- {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
- {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
+ {file = "pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723"},
+ {file = "pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645"},
]
+[package.extras]
+hyperscan = ["hyperscan (>=0.7)"]
+optional = ["typing-extensions (>=4)"]
+re2 = ["google-re2 (>=1.1)"]
+tests = ["pytest (>=9)", "typing-extensions (>=4.15)"]
+
[[package]]
name = "pbr"
version = "6.1.1"
@@ -911,7 +917,7 @@ files = [
{file = "tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a"},
{file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"},
]
-markers = {main = "extra == \"toml\"", dev = "python_version == \"3.10\""}
+markers = {main = "extra == \"toml\"", dev = "python_version < \"3.11\""}
[[package]]
name = "tomlkit"
@@ -932,7 +938,7 @@ description = "Backported and Experimental Type Hints for Python 3.9+"
optional = false
python-versions = ">=3.9"
groups = ["dev"]
-markers = "python_version == \"3.10\""
+markers = "python_version < \"3.11\""
files = [
{file = "typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76"},
{file = "typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36"},
@@ -944,4 +950,4 @@ toml = ["tomli"]
[metadata]
lock-version = "2.1"
python-versions = ">=3.10"
-content-hash = "b663351213d46fa0eeedf0dca90ae71c81d0cf896f5a850624c25e152e3b195c"
+content-hash = "4db2a878260bf9f7d53c6f038153b6a223bf21319a6e1bfb9001c55be069d27d"
diff --git a/pyproject.toml b/pyproject.toml
index a86a99ea..9c6c33b1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -58,7 +58,7 @@ pyflakes = "^3.3.2"
pylint = ">=3.3.4,<5.0.0"
pylint-pytest = "^1.1.8"
pydocstyle = "^6.1.1"
-black = "^25.1.0"
+black = "^26.1.0"
isort = ">=6.0.1,<8.0.0"
doc8 = "2.0.0"
ruff = ">=0.11.10,<0.15.0"
diff --git a/tests/test_diff_reporter.py b/tests/test_diff_reporter.py
index 5e50e810..fa523cd2 100644
--- a/tests/test_diff_reporter.py
+++ b/tests/test_diff_reporter.py
@@ -246,8 +246,7 @@ def test_ignore_lines_outside_src(diff, git_diff):
def test_one_line_file(diff, git_diff):
# Files with only one line have a special format
# in which the "length" part of the hunk is not specified
- diff_str = dedent(
- """
+ diff_str = dedent("""
diff --git a/diff_cover/one_line.txt b/diff_cover/one_line.txt
index 0867e73..9daeafb 100644
--- a/diff_cover/one_line.txt
@@ -256,8 +255,7 @@ def test_one_line_file(diff, git_diff):
test
-test
-test
- """
- ).strip()
+ """).strip()
# Configure the git diff output
_set_git_diff_output(diff, git_diff, diff_str, "", "")
@@ -291,8 +289,7 @@ def test_git_deleted_lines(diff, git_diff):
def test_git_unicode_filename(diff, git_diff):
# Filenames with unicode characters have double quotes surrounding them
# in the git diff output.
- diff_str = dedent(
- """
+ diff_str = dedent("""
diff --git "a/unic\303\270\342\210\202e\314\201.txt" "b/unic\303\270\342\210\202e\314\201.txt"
new file mode 100644
index 0000000..248ebea
@@ -302,8 +299,7 @@ def test_git_unicode_filename(diff, git_diff):
+μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος
+οὐλομένην, ἣ μυρί᾽ Ἀχαιοῖς ἄλγε᾽ ἔθηκε,
+πολλὰς δ᾽ ἰφθίμους ψυχὰς Ἄϊδι προΐαψεν
- """
- ).strip()
+ """).strip()
_set_git_diff_output(diff, git_diff, diff_str, "", "")
# Get the lines changed in the diff
@@ -429,28 +425,22 @@ def test_git_diff_error(
diff,
git_diff,
):
- invalid_hunk_str = dedent(
- """
+ invalid_hunk_str = dedent("""
diff --git a/subdir/file1.py b/subdir/file1.py
@@ invalid @@ Text
- """
- ).strip()
+ """).strip()
no_src_line_str = "@@ -33,10 +34,13 @@ Text"
- non_numeric_lines = dedent(
- """
+ non_numeric_lines = dedent("""
diff --git a/subdir/file1.py b/subdir/file1.py
@@ -1,2 +a,b @@
- """
- ).strip()
+ """).strip()
- missing_line_num = dedent(
- """
+ missing_line_num = dedent("""
diff --git a/subdir/file1.py b/subdir/file1.py
@@ -1,2 + @@
- """
- ).strip()
+ """).strip()
missing_src_str = "diff --git "
@@ -478,16 +468,14 @@ def test_git_diff_error(
def test_plus_sign_in_hunk_bug(diff, git_diff):
# This was a bug that caused a parse error
- diff_str = dedent(
- """
+ diff_str = dedent("""
diff --git a/file.py b/file.py
@@ -16,16 +16,7 @@ 1 + 2
+ test
+ test
+ test
+ test
- """
- )
+ """)
_set_git_diff_output(diff, git_diff, diff_str, "", "")
@@ -498,16 +486,14 @@ def test_plus_sign_in_hunk_bug(diff, git_diff):
def test_terminating_chars_in_hunk(diff, git_diff):
# Check what happens when there's an @@ symbol after the
# first terminating @@ symbol
- diff_str = dedent(
- """
+ diff_str = dedent("""
diff --git a/file.py b/file.py
@@ -16,16 +16,7 @@ and another +23,2 @@ symbol
+ test
+ test
+ test
+ test
- """
- )
+ """)
_set_git_diff_output(diff, git_diff, diff_str, "", "")
@@ -518,8 +504,7 @@ def test_terminating_chars_in_hunk(diff, git_diff):
def test_merge_conflict_diff(diff, git_diff):
# Handle different git diff format when in the middle
# of a merge conflict
- diff_str = dedent(
- """
+ diff_str = dedent("""
diff --cc subdir/src.py
index d2034c0,e594d54..0000000
diff --cc subdir/src.py
@@ -531,8 +516,7 @@ def test_merge_conflict_diff(diff, git_diff):
++<<<<<< HEAD
+ test
++=======
- """
- )
+ """)
_set_git_diff_output(diff, git_diff, diff_str, "", "")
diff --git a/tests/test_integration.py b/tests/test_integration.py
index 07b50d6d..4f21816b 100644
--- a/tests/test_integration.py
+++ b/tests/test_integration.py
@@ -2,6 +2,7 @@
# pylint: disable=use-implicit-booleaness-not-comparison
"""High-level integration tests of diff-cover tool."""
+
import json
import os
import os.path
@@ -383,8 +384,7 @@ def test_dot_net_diff(self, mocker, runbin, patch_git_command, capsys):
mocker.patch.object(GitPathTool, "_git_root", return_value="/code/samplediff/")
patch_git_command.set_stdout("git_diff_dotnet.txt")
assert runbin(["dotnet_coverage.xml"]) == 0
- expected = textwrap.dedent(
- f"""\
+ expected = textwrap.dedent(f"""\
-------------
Diff Coverage
Diff: origin/main...HEAD, staged and unstaged changes
@@ -395,8 +395,7 @@ def test_dot_net_diff(self, mocker, runbin, patch_git_command, capsys):
Missing: 3 lines
Coverage: 0%
-------------
- """
- )
+ """)
assert capsys.readouterr().out.strip() == expected.strip()
def test_unicode_html(self, runbin, patch_git_command):
@@ -469,22 +468,19 @@ def test_github_silent(self, runbin, patch_git_command, capsys):
assert (
runbin(["coverage.xml", "--format", "github-annotations:notice", "-q"]) == 0
)
- expected = textwrap.dedent(
- """\
+ expected = textwrap.dedent("""\
::notice file=test_src.txt,line=2,title=Missing Coverage::Line 2 missing coverage
::notice file=test_src.txt,line=4,title=Missing Coverage::Line 4 missing coverage
::notice file=test_src.txt,line=6,title=Missing Coverage::Line 6 missing coverage
::notice file=test_src.txt,line=8,title=Missing Coverage::Line 8 missing coverage
::notice file=test_src.txt,line=10,title=Missing Coverage::Line 10 missing coverage
- """
- )
+ """)
assert capsys.readouterr().out == expected
@pytest.mark.usefixtures("patch_git_command")
def test_github_fully_covered(self, runbin, capsys):
assert runbin(["coverage2.xml", "--format", "github-annotations:notice"]) == 0
- expected = textwrap.dedent(
- """\
+ expected = textwrap.dedent("""\
-------------
Diff Coverage
Diff: origin/main...HEAD, staged and unstaged changes
@@ -492,15 +488,13 @@ def test_github_fully_covered(self, runbin, capsys):
No lines with coverage information in this diff.
-------------
- """
- )
+ """)
assert capsys.readouterr().out == expected
def test_github_empty_diff(self, runbin, patch_git_command, capsys):
patch_git_command.set_stdout("")
assert runbin(["coverage.xml", "--format", "github-annotations:notice"]) == 0
- expected = textwrap.dedent(
- """\
+ expected = textwrap.dedent("""\
-------------
Diff Coverage
Diff: origin/main...HEAD, staged and unstaged changes
@@ -508,8 +502,7 @@ def test_github_empty_diff(self, runbin, patch_git_command, capsys):
No lines with coverage information in this diff.
-------------
- """
- )
+ """)
assert capsys.readouterr().out == expected
def test_real_world_cpp_lcov_coverage(self, runbin, patch_git_command, capsys):
diff --git a/tests/test_java_violations_reporter.py b/tests/test_java_violations_reporter.py
index fd1f18fc..443f89c4 100644
--- a/tests/test_java_violations_reporter.py
+++ b/tests/test_java_violations_reporter.py
@@ -62,14 +62,10 @@ def test_quality(self, process_patcher):
# Patch the output of `checkstyle`
process_patcher(
(
- dedent(
- """
+ dedent("""
[WARN] ../new_file.java:1:1: Line contains a tab character.
[WARN] ../new_file.java:13: 'if' construct must use '{}'s.
- """
- )
- .strip()
- .encode("ascii"),
+ """).strip().encode("ascii"),
"",
)
)
@@ -127,8 +123,7 @@ def test_quality(self, process_patcher):
# Patch the output of `checkstyle`
process_patcher(
(
- dedent(
- """
+ dedent("""
@@ -144,10 +139,7 @@ def test_quality(self, process_patcher):
- """
- )
- .strip()
- .encode("ascii"),
+ """).strip().encode("ascii"),
"",
)
)
@@ -187,16 +179,14 @@ def test_quality_error(self, mocker, process_patcher):
# Patch the output stderr/stdout and returncode of `checkstyle`
process_patcher(
(
- dedent(
- """
+ dedent("""
- """
- ),
+ """),
b"oops",
),
status_code=1,
@@ -216,9 +206,7 @@ def test_quality_pregenerated_report(self):
# When the user provides us with a pre-generated checkstyle report
# then use that instead of calling checkstyle directly.
checkstyle_reports = [
- BytesIO(
- dedent(
- """
+ BytesIO(dedent("""
@@ -231,14 +219,8 @@ def test_quality_pregenerated_report(self):
- """
- )
- .strip()
- .encode("utf-8")
- ),
- BytesIO(
- dedent(
- """
+ """).strip().encode("utf-8")),
+ BytesIO(dedent("""
@@ -248,11 +230,7 @@ def test_quality_pregenerated_report(self):
- """
- )
- .strip()
- .encode("utf-8")
- ),
+ """).strip().encode("utf-8")),
]
# Generate the violation report
@@ -307,9 +285,7 @@ def test_quality_pregenerated_report(self):
# When the user provides us with a pre-generated findbugs report
# then use that instead of calling findbugs directly.
findbugs_reports = [
- BytesIO(
- dedent(
- """
+ BytesIO(dedent("""
@@ -333,14 +309,8 @@ def test_quality_pregenerated_report(self):
- """
- )
- .strip()
- .encode("utf-8")
- ),
- BytesIO(
- dedent(
- """
+ """).strip().encode("utf-8")),
+ BytesIO(dedent("""
@@ -364,15 +334,9 @@ def test_quality_pregenerated_report(self):
- """
- )
- .strip()
- .encode("utf-8")
- ),
+ """).strip().encode("utf-8")),
# this is a violation which is not bounded to a specific line. We'll skip those
- BytesIO(
- dedent(
- """
+ BytesIO(dedent("""
@@ -383,11 +347,7 @@ def test_quality_pregenerated_report(self):
- """
- )
- .strip()
- .encode("utf-8")
- ),
+ """).strip().encode("utf-8")),
]
# Generate the violation report
@@ -441,10 +401,7 @@ def test_no_java_file(self):
def test_quality_pregenerated_report(self):
# When the user provides us with a pre-generated findbugs report
# then use that instead of calling findbugs directly.
- pmd_reports = [
- BytesIO(
- dedent(
- """
+ pmd_reports = [BytesIO(dedent("""
@@ -458,12 +415,7 @@ def test_quality_pregenerated_report(self):
- """
- )
- .strip()
- .encode("utf-8")
- )
- ]
+ """).strip().encode("utf-8"))]
pmd_xml_driver = PmdXmlDriver()
# Generate the violation report
diff --git a/tests/test_report_generator.py b/tests/test_report_generator.py
index a1e7792a..2136ce99 100644
--- a/tests/test_report_generator.py
+++ b/tests/test_report_generator.py
@@ -368,8 +368,7 @@ def report(self, coverage, diff):
@pytest.mark.usefixtures("use_default_values")
def test_generate_report(self):
# Verify that we got the expected string
- expected = dedent(
- """
+ expected = dedent("""
-------------
Diff Coverage
Diff: main
@@ -381,8 +380,7 @@ def test_generate_report(self):
Missing: 4 lines
Coverage: 66%
-------------
- """
- ).strip()
+ """).strip()
self.assert_report(expected)
@@ -395,8 +393,7 @@ def test_hundred_percent(
coverage_violations.update({"file.py": []})
coverage_measured_lines.update({"file.py": [2]})
- expected = dedent(
- """
+ expected = dedent("""
-------------
Diff Coverage
Diff: main
@@ -407,8 +404,7 @@ def test_hundred_percent(
Missing: 0 lines
Coverage: 100%
-------------
- """
- ).strip()
+ """).strip()
self.assert_report(expected)
@@ -416,16 +412,14 @@ def test_empty_report(self):
# Have the dependencies return an empty report
# (this is the default)
- expected = dedent(
- """
+ expected = dedent("""
-------------
Diff Coverage
Diff: main
-------------
No lines with coverage information in this diff.
-------------
- """
- ).strip()
+ """).strip()
self.assert_report(expected)
@@ -448,12 +442,10 @@ def report(self, coverage, diff):
@pytest.mark.usefixtures("use_default_values")
def test_generate_report(self):
# Verify that we got the expected string
- expected = dedent(
- """
+ expected = dedent("""
::warning file=file1.py,line=10,endLine=11,title=Missing Coverage::Line 10-11 missing coverage
::warning file=subdir/file2.py,line=10,endLine=11,title=Missing Coverage::Line 10-11 missing coverage
- """
- ).strip()
+ """).strip()
self.assert_report(expected)
@@ -466,11 +458,9 @@ def test_single_line(
coverage_measured_lines.update({"file.py": [2]})
# Verify that we got the expected string
- expected = dedent(
- """
+ expected = dedent("""
::warning file=file.py,line=10,title=Missing Coverage::Line 10 missing coverage
- """
- ).strip()
+ """).strip()
self.assert_report(expected)
@@ -549,8 +539,7 @@ def test_generate_report(self):
# Generate a default report
# Verify that we got the expected string
- expected = dedent(
- """
+ expected = dedent("""
# Diff Coverage
## Diff: main
@@ -562,8 +551,7 @@ def test_generate_report(self):
- **Total**: 12 lines
- **Missing**: 4 lines
- **Coverage**: 66%
- """
- ).strip()
+ """).strip()
self.assert_report(expected)
@@ -576,8 +564,7 @@ def test_hundred_percent(
coverage_violations.update({"file.py": []})
coverage_measured_lines.update({"file.py": [2]})
- expected = dedent(
- """
+ expected = dedent("""
# Diff Coverage
## Diff: main
@@ -588,8 +575,7 @@ def test_hundred_percent(
- **Total**: 1 line
- **Missing**: 0 lines
- **Coverage**: 100%
- """
- ).strip()
+ """).strip()
self.assert_report(expected)
@@ -597,14 +583,12 @@ def test_empty_report(self):
# Have the dependencies return an empty report
# (this is the default)
- expected = dedent(
- """
+ expected = dedent("""
# Diff Coverage
## Diff: main
No lines with coverage information in this diff.
- """
- ).strip()
+ """).strip()
self.assert_report(expected)
diff --git a/tests/test_violations_reporter.py b/tests/test_violations_reporter.py
index 6be46d42..4b6ccba9 100644
--- a/tests/test_violations_reporter.py
+++ b/tests/test_violations_reporter.py
@@ -151,15 +151,13 @@ def test_non_python_violations_empty_path(self):
In the wild empty sources can happen. See https://github.com/Bachmann1234/diff-cover/issues/88
Best I can tell its mostly irrelevant but I mostly don't want it crashing
"""
- xml = etree.fromstring(
- """
+ xml = etree.fromstring("""
- """
- )
+ """)
coverage = XmlCoverageReporter([xml])
@@ -1099,17 +1097,11 @@ class TestPycodestyleQualityReporterTest:
def test_quality(self, mocker, process_patcher):
# Patch the output of `pycodestyle`
mocker.patch.object(Popen, "communicate")
- return_string = (
- "\n"
- + dedent(
- """
+ return_string = "\n" + dedent("""
../new_file.py:1:17: E231 whitespace
../new_file.py:3:13: E225 whitespace
../new_file.py:7:1: E302 blank lines
- """
- ).strip()
- + "\n"
- )
+ """).strip() + "\n"
process_patcher((return_string.encode("utf-8"), b""))
# Parse the report
@@ -1179,31 +1171,15 @@ def test_quality_pregenerated_report(self):
# When the user provides us with a pre-generated pycodestyle report
# then use that instead of calling pycodestyle directly.
pycodestyle_reports = [
- BytesIO(
- (
- "\n"
- + dedent(
- """
+ BytesIO(("\n" + dedent("""
path/to/file.py:1:17: E231 whitespace
path/to/file.py:3:13: E225 whitespace
another/file.py:7:1: E302 blank lines
- """
- ).strip()
- + "\n"
- ).encode("utf-8")
- ),
- BytesIO(
- (
- "\n"
- + dedent(
- """
+ """).strip() + "\n").encode("utf-8")),
+ BytesIO(("\n" + dedent("""
path/to/file.py:24:2: W123 \u9134\u1912
another/file.py:50:1: E302 blank lines
- """
- ).strip()
- + "\n"
- ).encode("utf-8")
- ),
+ """).strip() + "\n").encode("utf-8")),
]
# Parse the report
@@ -1236,16 +1212,10 @@ class TestPyflakesQualityReporterTest:
def test_quality(self, process_patcher):
# Patch the output of `pyflakes`
- return_string = (
- "\n"
- + dedent(
- """
+ return_string = "\n" + dedent("""
../new_file.py:328: undefined name '_thing'
../new_file.py:418: 'random' imported but unused
- """
- ).strip()
- + "\n"
- )
+ """).strip() + "\n"
process_patcher((return_string.encode("utf-8"), b""))
# Parse the report
@@ -1312,31 +1282,15 @@ def test_quality_pregenerated_report(self):
# When the user provides us with a pre-generated pyflakes report
# then use that instead of calling pyflakes directly.
pyflakes_reports = [
- BytesIO(
- (
- "\n"
- + dedent(
- """
+ BytesIO(("\n" + dedent("""
path/to/file.py:1: undefined name 'this'
path/to/file.py:3: 'random' imported but unused
another/file.py:7: 'os' imported but unused
- """
- ).strip()
- + "\n"
- ).encode("utf-8")
- ),
- BytesIO(
- (
- "\n"
- + dedent(
- """
+ """).strip() + "\n").encode("utf-8")),
+ BytesIO(("\n" + dedent("""
path/to/file.py:24: undefined name 'that'
another/file.py:50: undefined name 'another'
- """
- ).strip()
- + "\n"
- ).encode("utf-8")
- ),
+ """).strip() + "\n").encode("utf-8")),
]
# Parse the report
@@ -1365,10 +1319,7 @@ def test_quality_pregenerated_report(self):
class TestFlake8QualityReporterTest:
def test_quality(self, process_patcher):
# Patch the output of `flake8`
- return_string = (
- "\n"
- + dedent(
- """
+ return_string = "\n" + dedent("""
../new_file.py:1:17: E231 whitespace
../new_file.py:3:13: E225 whitespace
../new_file.py:7:1: E302 blank lines
@@ -1383,10 +1334,7 @@ def test_quality(self, process_patcher):
../new_file.py:100:0: S100 Snippet found
../new_file.py:110:0: Q000 Remove Single quotes
../new_file.py:120:0: ABCXYZ000 Dummy
- """
- ).strip()
- + "\n"
- )
+ """).strip() + "\n"
process_patcher((return_string.encode("utf-8"), b""))
# Parse the report
@@ -1475,31 +1423,15 @@ def test_quality_pregenerated_report(self):
# When the user provides us with a pre-generated flake8 report
# then use that instead of calling flake8 directly.
flake8_reports = [
- BytesIO(
- (
- "\n"
- + dedent(
- """
+ BytesIO(("\n" + dedent("""
path/to/file.py:1:17: E231 whitespace
path/to/file.py:3:13: E225 whitespace
another/file.py:7:1: E302 blank lines
- """
- ).strip()
- + "\n"
- ).encode("utf-8")
- ),
- BytesIO(
- (
- "\n"
- + dedent(
- """
+ """).strip() + "\n").encode("utf-8")),
+ BytesIO(("\n" + dedent("""
path/to/file.py:24:2: W123 \u9134\u1912
another/file.py:50:1: E302 blank lines
- """
- ).strip()
- + "\n"
- ).encode("utf-8")
- ),
+ """).strip() + "\n").encode("utf-8")),
]
# Parse the report
@@ -1548,16 +1480,12 @@ def test_quality(self, process_patcher):
# Patch the output of `pydocstye`
process_patcher(
(
- dedent(
- """
+ dedent("""
../new_file.py:1 at module level:
D100: Missing docstring in public module
../new_file.py:13 in public function `gather`:
D103: Missing docstring in public function
- """
- )
- .strip()
- .encode("ascii"),
+ """).strip().encode("ascii"),
"",
)
)
@@ -1609,8 +1537,7 @@ def test_quality(self, process_patcher):
# Patch the output of `pylint`
process_patcher(
(
- dedent(
- """
+ dedent("""
file1.py:1: [C0111] Missing docstring
file1.py:1: [C0111, func_1] Missing docstring
file1.py:2: [W0612, cls_name.func] Unused variable 'd'
@@ -1632,10 +1559,7 @@ def test_quality(self, process_patcher):
import foo
import bar
path/to/file2.py:100: [W0212, openid_login_complete] Access to a protected member
- """
- )
- .strip()
- .encode("ascii"),
+ """).strip().encode("ascii"),
"",
)
)
@@ -1677,12 +1601,10 @@ def test_quality(self, process_patcher):
def test_unicode(self, process_patcher):
process_patcher(
(
- dedent(
- """
+ dedent("""
file_\u6729.py:616: [W1401] Anomalous backslash in string: '\u5922'. String constant might be missing an r prefix.
file.py:2: [W0612, cls_name.func_\u9492] Unused variable '\u2920'
- """
- ).encode("utf-8"),
+ """).encode("utf-8"),
"",
),
0,
@@ -1713,12 +1635,10 @@ def test_unicode_continuation_char(self, process_patcher):
def test_non_integer_line_num(self, process_patcher):
process_patcher(
(
- dedent(
- """
+ dedent("""
file.py:not_a_number: C0111: Missing docstring
file.py:\u8911: C0111: Missing docstring
- """
- ).encode("utf-8"),
+ """).encode("utf-8"),
"",
),
0,
@@ -1782,9 +1702,7 @@ def test_quality_pregenerated_report(self):
# When the user provides us with a pre-generated pylint report
# then use that instead of calling pylint directly.
pylint_reports = [
- BytesIO(
- dedent(
- """
+ BytesIO(dedent("""
path/to/file.py:1: [C0111] Missing docstring
path/to/file.py:57: [W0511] TODO the name of this method is a little bit confusing
another/file.py:41: [W1201, assign_default_role] Specify string format arguments as logging function parameters
@@ -1793,21 +1711,11 @@ def test_quality_pregenerated_report(self):
^
Unicode: \u9404 \u1239
another/file.py:259: [C0103, bar] Invalid name "\u4920" for type variable (should match [a-z_][a-z0-9_]{2,30}$)
- """
- )
- .strip()
- .encode("utf-8")
- ),
- BytesIO(
- dedent(
- """
+ """).strip().encode("utf-8")),
+ BytesIO(dedent("""
path/to/file.py:183: [C0103, Foo.bar.gettag] Invalid name "\u3240" for type argument (should match [a-z_][a-z0-9_]{2,30}$)
another/file.py:183: [C0111, Foo.bar.gettag] Missing docstring
- """
- )
- .strip()
- .encode("utf-8")
- ),
+ """).strip().encode("utf-8")),
]
# Generate the violation report
@@ -1884,16 +1792,10 @@ def test_quality(self):
Test basic scenarios, including special characters that would appear in JavaScript and mixed quotation marks
"""
# Patch the output of the linter cmd
- return_string = (
- "\n"
- + dedent(
- """
+ return_string = "\n" + dedent("""
../test_file.js: line 3, col 9, Missing "use strict" statement.
../test_file.js: line 10, col 17, '$hi' is defined but never used.
- """
- ).strip()
- + "\n"
- )
+ """).strip() + "\n"
self.subproc_mock.communicate.return_value = (
return_string.encode("utf-8"),
b"",
@@ -1967,31 +1869,15 @@ def test_quality_pregenerated_report(self):
# When the user provides us with a pre-generated linter report
# then use that instead of calling linter directly.
reports = [
- BytesIO(
- (
- "\n"
- + dedent(
- """
+ BytesIO(("\n" + dedent("""
path/to/file.js: line 3, col 9, Missing "use strict" statement.
path/to/file.js: line 10, col 130, Line is too long.
another/file.js: line 1, col 1, 'require' is not defined.
- """
- ).strip()
- + "\n"
- ).encode("utf-8")
- ),
- BytesIO(
- (
- "\n"
- + dedent(
- """
+ """).strip() + "\n").encode("utf-8")),
+ BytesIO(("\n" + dedent("""
path/to/file.js: line 12, col 14, \u9134\u1912
path/to/file.js: line 10, col 17, '$hi' is defined but never used.
- """
- ).strip()
- + "\n"
- ).encode("utf-8")
- ),
+ """).strip() + "\n").encode("utf-8")),
]
# Parse the report
@@ -2089,14 +1975,10 @@ def test_quality(self, process_patcher):
"""Integration test."""
process_patcher(
(
- dedent(
- """
+ dedent("""
foo/bar/path/to/file.sh:2:18: note: Double quote to prevent globbing and word splitting. [SC2086]
foo/bar/path/to/file.sh:53:10: warning: Use 'cd ... || exit' or 'cd ... || return' in case cd fails. [SC2164]
- """
- )
- .strip()
- .encode("ascii"),
+ """).strip().encode("ascii"),
"",
)
)
@@ -2248,8 +2130,7 @@ def test_quality(self, process_patcher):
"""Integration test."""
process_patcher(
(
- dedent(
- """
+ dedent("""
foo/bar/path/to/file.py:244:26: F541 [*] f-string without any placeholders
|
242 | ]
@@ -2271,10 +2152,7 @@ def test_quality(self, process_patcher):
134 | dedent(
|
= help: Remove assignment to unused variable `e`
- """
- )
- .strip()
- .encode("ascii"),
+ """).strip().encode("ascii"),
"",
)
)