summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Byrne <31762852+mbyrnepr2@users.noreply.github.com>2021-08-18 17:52:22 +0200
committerGitHub <noreply@github.com>2021-08-18 17:52:22 +0200
commitbe039201f0d3ce2c0664f312646733b2a5af69c5 (patch)
treee42a3a209811b993626ea9b7270b58f988f80cc2
parent53da6541dbe621b55f2c7f1bfcf821541dc823e8 (diff)
downloadpylint-git-be039201f0d3ce2c0664f312646733b2a5af69c5.tar.gz
pyreverse - Handle a regression with typehints of type astroid.Subscript (#4859)
* pyreverse - Handle a regression with typehints of type astroid.Subscript Closes #4845 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * pyreverse - Handle a regression with typehints of type astroid.Subscript - Add test-case to pyreverse data files Closes #4845 Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
-rw-r--r--pylint/pyreverse/utils.py2
-rw-r--r--tests/data/suppliermodule_test.py8
-rw-r--r--tests/pyreverse/data/classes_No_Name.dot2
-rw-r--r--tests/pyreverse/data/classes_No_Name.puml1
-rw-r--r--tests/pyreverse/data/classes_No_Name.vcg2
-rw-r--r--tests/pyreverse/data/classes_colorized.dot2
-rw-r--r--tests/pyreverse/data/classes_colorized.puml1
-rw-r--r--tests/pyreverse/test_utils.py20
8 files changed, 34 insertions, 4 deletions
diff --git a/pylint/pyreverse/utils.py b/pylint/pyreverse/utils.py
index 7ca4501f1..bc0e40fc6 100644
--- a/pylint/pyreverse/utils.py
+++ b/pylint/pyreverse/utils.py
@@ -272,6 +272,8 @@ def infer_node(node: Union[astroid.AssignAttr, astroid.AssignName]) -> set:
ann = get_annotation(node)
try:
if ann:
+ if isinstance(ann, astroid.Subscript):
+ return {ann}
return set(ann.infer())
return set(node.infer())
except astroid.InferenceError:
diff --git a/tests/data/suppliermodule_test.py b/tests/data/suppliermodule_test.py
index add637d4a..9c8b05d52 100644
--- a/tests/data/suppliermodule_test.py
+++ b/tests/data/suppliermodule_test.py
@@ -1,4 +1,5 @@
""" file suppliermodule.py """
+from typing import Optional
class Interface:
def get_value(self):
@@ -14,9 +15,14 @@ class DoNothing: pass
class DoNothing2: pass
class DoSomething:
- def __init__(self, a_string: str, optional_int: int = None):
+ def __init__(
+ self,
+ a_string: str,
+ optional_int: int = None,
+ optional_int_2: Optional[int] = None):
self.my_string = a_string
self.my_int = optional_int
+ self.my_int_2 = optional_int_2
def do_it(self, new_int: int) -> int:
return self.my_int + new_int
diff --git a/tests/pyreverse/data/classes_No_Name.dot b/tests/pyreverse/data/classes_No_Name.dot
index f3e7b9625..cbe3d155d 100644
--- a/tests/pyreverse/data/classes_No_Name.dot
+++ b/tests/pyreverse/data/classes_No_Name.dot
@@ -5,7 +5,7 @@ charset="utf-8"
"data.suppliermodule_test.CustomException" [color="black", fontcolor="red", label="{CustomException|\l|}", shape="record", style="solid"];
"data.suppliermodule_test.DoNothing" [color="black", fontcolor="black", label="{DoNothing|\l|}", shape="record", style="solid"];
"data.suppliermodule_test.DoNothing2" [color="black", fontcolor="black", label="{DoNothing2|\l|}", shape="record", style="solid"];
-"data.suppliermodule_test.DoSomething" [color="black", fontcolor="black", label="{DoSomething|my_int : Optional[int]\lmy_string : str\l|do_it(new_int: int): int\l}", shape="record", style="solid"];
+"data.suppliermodule_test.DoSomething" [color="black", fontcolor="black", label="{DoSomething|my_int : Optional[int]\lmy_int_2 : Optional[int]\lmy_string : str\l|do_it(new_int: int): int\l}", shape="record", style="solid"];
"data.suppliermodule_test.Interface" [color="black", fontcolor="black", label="{Interface|\l|get_value()\lset_value(value)\l}", shape="record", style="solid"];
"data.clientmodule_test.Specialization" [color="black", fontcolor="black", label="{Specialization|TYPE : str\lrelation\lrelation2\ltop : str\l|}", 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.puml b/tests/pyreverse/data/classes_No_Name.puml
index 5acbe93d0..35bda65c1 100644
--- a/tests/pyreverse/data/classes_No_Name.puml
+++ b/tests/pyreverse/data/classes_No_Name.puml
@@ -14,6 +14,7 @@ class "DoNothing2" as data.suppliermodule_test.DoNothing2 {
}
class "DoSomething" as data.suppliermodule_test.DoSomething {
my_int : Optional[int]
+ my_int_2 : Optional[int]
my_string : str
do_it(new_int: int) -> int
}
diff --git a/tests/pyreverse/data/classes_No_Name.vcg b/tests/pyreverse/data/classes_No_Name.vcg
index 89697ce84..748c432f2 100644
--- a/tests/pyreverse/data/classes_No_Name.vcg
+++ b/tests/pyreverse/data/classes_No_Name.vcg
@@ -16,7 +16,7 @@ graph:{
node: {title:"data.suppliermodule_test.DoNothing2" label:"\fbDoNothing2\fn\n\f____________"
shape:box
}
- node: {title:"data.suppliermodule_test.DoSomething" label:"\fbDoSomething\fn\n\f________________________\n\f08my_int : Optional[int]\n\f08my_string : str\n\f________________________\n\f10do_it()"
+ node: {title:"data.suppliermodule_test.DoSomething" label:"\fbDoSomething\fn\n\f__________________________\n\f08my_int : Optional[int]\n\f08my_int_2 : Optional[int]\n\f08my_string : str\n\f__________________________\n\f10do_it()"
shape:box
}
node: {title:"data.suppliermodule_test.Interface" label:"\fbInterface\fn\n\f___________\n\f10get_value()\n\f10set_value()"
diff --git a/tests/pyreverse/data/classes_colorized.dot b/tests/pyreverse/data/classes_colorized.dot
index 41c81d94f..ff96df77c 100644
--- a/tests/pyreverse/data/classes_colorized.dot
+++ b/tests/pyreverse/data/classes_colorized.dot
@@ -5,7 +5,7 @@ charset="utf-8"
"data.suppliermodule_test.CustomException" [color="aliceblue", fontcolor="red", label="{CustomException|\l|}", shape="record", style="filled"];
"data.suppliermodule_test.DoNothing" [color="aliceblue", fontcolor="black", label="{DoNothing|\l|}", shape="record", style="filled"];
"data.suppliermodule_test.DoNothing2" [color="aliceblue", fontcolor="black", label="{DoNothing2|\l|}", shape="record", style="filled"];
-"data.suppliermodule_test.DoSomething" [color="aliceblue", fontcolor="black", label="{DoSomething|my_int : Optional[int]\lmy_string : str\l|do_it(new_int: int): int\l}", shape="record", style="filled"];
+"data.suppliermodule_test.DoSomething" [color="aliceblue", fontcolor="black", label="{DoSomething|my_int : Optional[int]\lmy_int_2 : Optional[int]\lmy_string : str\l|do_it(new_int: int): int\l}", shape="record", style="filled"];
"data.suppliermodule_test.Interface" [color="aliceblue", fontcolor="black", label="{Interface|\l|get_value()\lset_value(value)\l}", shape="record", style="filled"];
"data.clientmodule_test.Specialization" [color="aliceblue", fontcolor="black", label="{Specialization|TYPE : str\lrelation\lrelation2\ltop : str\l|}", shape="record", style="filled"];
"data.clientmodule_test.Specialization" -> "data.clientmodule_test.Ancestor" [arrowhead="empty", arrowtail="none"];
diff --git a/tests/pyreverse/data/classes_colorized.puml b/tests/pyreverse/data/classes_colorized.puml
index cbbc3b02e..25c0f34e9 100644
--- a/tests/pyreverse/data/classes_colorized.puml
+++ b/tests/pyreverse/data/classes_colorized.puml
@@ -14,6 +14,7 @@ class "DoNothing2" as data.suppliermodule_test.DoNothing2 #aliceblue {
}
class "DoSomething" as data.suppliermodule_test.DoSomething #aliceblue {
my_int : Optional[int]
+ my_int_2 : Optional[int]
my_string : str
do_it(new_int: int) -> int
}
diff --git a/tests/pyreverse/test_utils.py b/tests/pyreverse/test_utils.py
index c82a63e52..bc3a5baf6 100644
--- a/tests/pyreverse/test_utils.py
+++ b/tests/pyreverse/test_utils.py
@@ -117,3 +117,23 @@ def test_infer_node_3():
instance_attr = node.instance_attrs.get("component")[0]
assert isinstance(infer_node(instance_attr), set)
assert isinstance(infer_node(instance_attr).pop(), astroid.ClassDef)
+
+
+def test_infer_node_4():
+ """Verify the label for an argument with a typehint of the type
+ astroid.Subscript
+ """
+ node = astroid.extract_node(
+ """
+ class MyClass:
+ def __init__(self, my_int: Optional[int] = None):
+ self.my_test_int = my_int
+ """
+ )
+
+ instance_attr = node.instance_attrs.get("my_test_int")[0]
+ assert isinstance(instance_attr, astroid.AssignAttr)
+
+ inferred = infer_node(instance_attr).pop()
+ assert isinstance(inferred, astroid.Subscript)
+ assert inferred.name == "Optional[int]"