Skip to content

Commit a21f5d3

Browse files
authored
Fix Pyreverse optional annotation bug (#9016)
* Add alternative optional bug test cases * Fix Pyreverse optional annotation bug * Fix type error
1 parent fbbf788 commit a21f5d3

File tree

6 files changed

+28
-8
lines changed

6 files changed

+28
-8
lines changed

doc/whatsnew/fragments/9014.bugfix

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Don't add `Optional` to `|` annotations with `None` in Pyreverse diagrams.
2+
3+
Closes #9014

pylint/pyreverse/utils.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,22 @@ def get_annotation(
194194
default = ""
195195

196196
label = get_annotation_label(ann)
197-
if ann:
198-
label = (
199-
rf"Optional[{label}]"
200-
if getattr(default, "value", "value") is None
201-
and not label.startswith("Optional")
202-
else label
197+
198+
if (
199+
ann
200+
and getattr(default, "value", "value") is None
201+
and not label.startswith("Optional")
202+
and (
203+
not isinstance(ann, nodes.BinOp)
204+
or not any(
205+
isinstance(child, nodes.Const) and child.value is None
206+
for child in ann.get_children()
207+
)
203208
)
204-
if label:
209+
):
210+
label = rf"Optional[{label}]"
211+
212+
if label and ann:
205213
ann.name = label
206214
return ann
207215

tests/pyreverse/functional/class_diagrams/annotations/attributes_annotation.dot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ digraph "classes" {
22
rankdir=BT
33
charset="utf-8"
44
"attributes_annotation.Dummy" [color="black", fontcolor="black", label=<{Dummy|<br ALIGN="LEFT"/>|}>, shape="record", style="solid"];
5-
"attributes_annotation.Dummy2" [color="black", fontcolor="black", label=<{Dummy2|alternative_union_syntax : str \| int<br ALIGN="LEFT"/>class_attr : list[Dummy]<br ALIGN="LEFT"/>optional : Optional[Dummy]<br ALIGN="LEFT"/>param : str<br ALIGN="LEFT"/>union : Union[int, str]<br ALIGN="LEFT"/>|}>, shape="record", style="solid"];
5+
"attributes_annotation.Dummy2" [color="black", fontcolor="black", label=<{Dummy2|alternative_optional : int \| None<br ALIGN="LEFT"/>alternative_optional_swapped : None \| int<br ALIGN="LEFT"/>alternative_union_syntax : str \| int<br ALIGN="LEFT"/>class_attr : list[Dummy]<br ALIGN="LEFT"/>optional : Optional[Dummy]<br ALIGN="LEFT"/>optional_union : Optional[int \| str]<br ALIGN="LEFT"/>param : str<br ALIGN="LEFT"/>union : Union[int, str]<br ALIGN="LEFT"/>|}>, shape="record", style="solid"];
66
}

tests/pyreverse/functional/class_diagrams/annotations/attributes_annotation.mmd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ classDiagram
22
class Dummy {
33
}
44
class Dummy2 {
5+
alternative_optional : int | None
6+
alternative_optional_swapped : None | int
57
alternative_union_syntax : str | int
68
class_attr : list[Dummy]
79
optional : Optional[Dummy]
10+
optional_union : Optional[int | str]
811
param : str
912
union : Union[int, str]
1013
}

tests/pyreverse/functional/class_diagrams/annotations/attributes_annotation.puml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ set namespaceSeparator none
33
class "Dummy" as attributes_annotation.Dummy {
44
}
55
class "Dummy2" as attributes_annotation.Dummy2 {
6+
alternative_optional : int | None
7+
alternative_optional_swapped : None | int
68
alternative_union_syntax : str | int
79
class_attr : list[Dummy]
810
optional : Optional[Dummy]
11+
optional_union : Optional[int | str]
912
param : str
1013
union : Union[int, str]
1114
}

tests/pyreverse/functional/class_diagrams/annotations/attributes_annotation.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ def __init__(self, param: str) -> None:
1616
self.union: Union[int, str] = ""
1717
self.alternative_union_syntax: str | int = 0
1818
self.optional: Optional[Dummy] = None
19+
self.alternative_optional: int | None = None
20+
self.alternative_optional_swapped: None | int = None
21+
self.optional_union: int | str = None

0 commit comments

Comments
 (0)