From e507a4d87ec80e706ac0c8ce2d23bd28006cbbbc Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 24 Apr 2023 19:50:25 +0000
Subject: Fix a false positive for ``bad-dunder-name`` when there is a
user-defined ``__index__`` method. (#8619) (#8622)
Closes #8613
(cherry picked from commit f223c6de3a39eae6d1c76e30b55da28639dd8777)
Co-authored-by: Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com>
---
doc/whatsnew/fragments/8613.false_positive | 3 +++
pylint/constants.py | 1 +
tests/functional/ext/bad_dunder/bad_dunder_name.py | 3 +++
3 files changed, 7 insertions(+)
create mode 100644 doc/whatsnew/fragments/8613.false_positive
diff --git a/doc/whatsnew/fragments/8613.false_positive b/doc/whatsnew/fragments/8613.false_positive
new file mode 100644
index 000000000..80d28e9c2
--- /dev/null
+++ b/doc/whatsnew/fragments/8613.false_positive
@@ -0,0 +1,3 @@
+Fix a false positive for ``bad-dunder-name`` when there is a user-defined ``__index__`` method.
+
+Closes #8613
diff --git a/pylint/constants.py b/pylint/constants.py
index ad7fc2256..de29fb9b8 100644
--- a/pylint/constants.py
+++ b/pylint/constants.py
@@ -281,6 +281,7 @@ EXTRA_DUNDER_METHODS = [
"__getnewargs_ex__",
"__getnewargs__",
"__getstate__",
+ "__index__",
"__setstate__",
"__reduce__",
"__reduce_ex__",
diff --git a/tests/functional/ext/bad_dunder/bad_dunder_name.py b/tests/functional/ext/bad_dunder/bad_dunder_name.py
index 48247aba0..6008866b1 100644
--- a/tests/functional/ext/bad_dunder/bad_dunder_name.py
+++ b/tests/functional/ext/bad_dunder/bad_dunder_name.py
@@ -49,6 +49,9 @@ class Apples:
def __doc__(self):
return "Docstring"
+ def __index__(self):
+ return 1
+
def __increase_me__(val):
return val + 1
--
cgit v1.2.1
From 4350c6fd7a955892712e2bf7a78adf4531e483b4 Mon Sep 17 00:00:00 2001
From: Andreas Finkler <3929834+DudeNr33@users.noreply.github.com>
Date: Thu, 27 Apr 2023 19:14:11 +0200
Subject: Added escaping of vertical bar character in annotation labels (#8610)
(#8631)
---
doc/whatsnew/fragments/8603.bugfix | 3 +++
pylint/pyreverse/dot_printer.py | 10 +++++++++-
tests/data/nullable_pattern.py | 10 ++++++++++
tests/pyreverse/data/classes_No_Name.dot | 1 +
tests/pyreverse/data/classes_No_Name.html | 6 +++++-
tests/pyreverse/data/classes_No_Name.mmd | 4 ++++
tests/pyreverse/data/classes_No_Name.puml | 4 ++++
tests/pyreverse/data/classes_No_Name.vcg | 29 +++++++++++++++-------------
tests/pyreverse/data/classes_colorized.dot | 1 +
tests/pyreverse/data/classes_colorized.puml | 4 ++++
tests/pyreverse/data/packages_No_Name.dot | 1 +
tests/pyreverse/data/packages_No_Name.html | 4 +++-
tests/pyreverse/data/packages_No_Name.mmd | 2 ++
tests/pyreverse/data/packages_No_Name.puml | 6 ++----
tests/pyreverse/data/packages_No_Name.vcg | 13 ++++++++-----
tests/pyreverse/data/packages_colorized.dot | 1 +
tests/pyreverse/data/packages_colorized.puml | 3 +++
tests/pyreverse/test_diadefs.py | 2 ++
tests/pyreverse/test_inspector.py | 1 +
19 files changed, 80 insertions(+), 25 deletions(-)
create mode 100644 doc/whatsnew/fragments/8603.bugfix
create mode 100644 tests/data/nullable_pattern.py
diff --git a/doc/whatsnew/fragments/8603.bugfix b/doc/whatsnew/fragments/8603.bugfix
new file mode 100644
index 000000000..1a1025c4b
--- /dev/null
+++ b/doc/whatsnew/fragments/8603.bugfix
@@ -0,0 +1,3 @@
+``pyreverse``: added escaping of vertical bar character in annotation labels produced by DOT printer to ensure it is not treated as field separator of record-based nodes.
+
+Closes #8603
diff --git a/pylint/pyreverse/dot_printer.py b/pylint/pyreverse/dot_printer.py
index 077e0552d..99cb17e97 100644
--- a/pylint/pyreverse/dot_printer.py
+++ b/pylint/pyreverse/dot_printer.py
@@ -121,11 +121,19 @@ class DotPrinter(Printer):
)
label += rf"{method_name}({', '.join(args)})"
if func.returns:
- label += ": " + get_annotation_label(func.returns)
+ annotation_label = get_annotation_label(func.returns)
+ label += ": " + self._escape_annotation_label(annotation_label)
label += rf"{HTMLLabels.LINEBREAK_LEFT.value}"
label += "}"
return label
+ def _escape_annotation_label(self, annotation_label: str) -> str:
+ # Escape vertical bar characters to make them appear as a literal characters
+ # otherwise it gets treated as field separator of record-based nodes
+ annotation_label = annotation_label.replace("|", r"\|")
+
+ return annotation_label
+
def emit_edge(
self,
from_node: str,
diff --git a/tests/data/nullable_pattern.py b/tests/data/nullable_pattern.py
new file mode 100644
index 000000000..bd730bbd6
--- /dev/null
+++ b/tests/data/nullable_pattern.py
@@ -0,0 +1,10 @@
+""" docstring for file nullable_pattern.py """
+from typing import Optional
+
+class NullablePatterns:
+ def return_nullable_1(self) -> int | None:
+ """ Nullable return type using the | operator as mentioned in PEP 604, see https://peps.python.org/pep-0604 """
+ pass
+
+ def return_nullable_2(self) -> Optional[int]:
+ pass
diff --git a/tests/pyreverse/data/classes_No_Name.dot b/tests/pyreverse/data/classes_No_Name.dot
index a598ab6d9..2e8830fa0 100644
--- a/tests/pyreverse/data/classes_No_Name.dot
+++ b/tests/pyreverse/data/classes_No_Name.dot
@@ -7,6 +7,7 @@ charset="utf-8"
"data.suppliermodule_test.DoNothing2" [color="black", fontcolor="black", label=<{DoNothing2|
|}>, shape="record", style="solid"];
"data.suppliermodule_test.DoSomething" [color="black", fontcolor="black", label=<{DoSomething|my_int : Optional[int]
my_int_2 : Optional[int]
my_string : str
|do_it(new_int: int): int
}>, shape="record", style="solid"];
"data.suppliermodule_test.Interface" [color="black", fontcolor="black", label=<{Interface|
|get_value()
set_value(value)
}>, shape="record", style="solid"];
+"data.nullable_pattern.NullablePatterns" [color="black", fontcolor="black", label=<{NullablePatterns|
|return_nullable_1(): int \| None
return_nullable_2(): Optional[int]
}>, shape="record", style="solid"];
"data.property_pattern.PropertyPatterns" [color="black", fontcolor="black", label=<{PropertyPatterns|prop1
prop2
|}>, shape="record", style="solid"];
"data.clientmodule_test.Specialization" [color="black", fontcolor="black", label=<{Specialization|TYPE : str
relation
relation2
top : str
|from_value(value: int)
increment_value(): None
transform_value(value: int): int
}>, shape="record", style="solid"];
"data.clientmodule_test.Specialization" -> "data.clientmodule_test.Ancestor" [arrowhead="empty", arrowtail="none"];
diff --git a/tests/pyreverse/data/classes_No_Name.html b/tests/pyreverse/data/classes_No_Name.html
index 602f2e3b7..bed9a8d14 100644
--- a/tests/pyreverse/data/classes_No_Name.html
+++ b/tests/pyreverse/data/classes_No_Name.html
@@ -26,6 +26,10 @@
get_value()*
set_value(value)*
}
+ class NullablePatterns {
+ return_nullable_1()* int | None
+ return_nullable_2()* Optional[int]
+ }
class PropertyPatterns {
prop1
prop2
@@ -44,7 +48,7 @@
DoNothing --* Ancestor : cls_member
DoNothing --* Specialization : relation
DoNothing2 --o Specialization : relation2
-
+