hippo91 | 1f7c29c | 2020-08-20 18:40:19 +0200 | [diff] [blame] | 1 | # Copyright (c) 2015-2018, 2020 Claudiu Popa <pcmanticore@gmail.com> |
Ashley Whetter | 33b8185 | 2019-06-14 22:28:42 -0700 | [diff] [blame] | 2 | # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com> |
Pierre Sassoulas | 391c8aa | 2021-02-28 21:13:57 +0100 | [diff] [blame] | 3 | # Copyright (c) 2019-2021 Pierre Sassoulas <pierre.sassoulas@gmail.com> |
Claudiu Popa | 369d952 | 2020-04-27 11:04:14 +0200 | [diff] [blame] | 4 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
Pierre Sassoulas | ac85223 | 2021-02-21 15:13:06 +0100 | [diff] [blame] | 5 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> |
hippo91 | 1f7c29c | 2020-08-20 18:40:19 +0200 | [diff] [blame] | 6 | # Copyright (c) 2020 Damien Baty <damien.baty@polyconseil.fr> |
Pierre Sassoulas | aa688de | 2021-07-01 14:33:09 +0200 | [diff] [blame] | 7 | # Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com> |
Pierre Sassoulas | ea448b8 | 2021-08-20 22:07:21 +0200 | [diff] [blame] | 8 | # Copyright (c) 2021 Andreas Finkler <andi.finkler@gmail.com> |
| 9 | # Copyright (c) 2021 Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com> |
Ashley Whetter | 33b8185 | 2019-06-14 22:28:42 -0700 | [diff] [blame] | 10 | |
| 11 | # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
Marc Mueller | 2129086 | 2021-07-01 12:47:58 +0200 | [diff] [blame] | 12 | # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE |
Ashley Whetter | 33b8185 | 2019-06-14 22:28:42 -0700 | [diff] [blame] | 13 | |
| 14 | """ |
| 15 | for the visitors.diadefs module |
| 16 | """ |
Pierre Sassoulas | ec2957f | 2020-05-01 13:53:10 +0200 | [diff] [blame] | 17 | # pylint: disable=redefined-outer-name |
| 18 | |
Ashley Whetter | 33b8185 | 2019-06-14 22:28:42 -0700 | [diff] [blame] | 19 | import os |
| 20 | |
| 21 | import astroid |
| 22 | import pytest |
Marc Mueller | 7ed757e | 2021-08-19 09:01:49 +0200 | [diff] [blame] | 23 | from astroid import nodes |
Ashley Whetter | 33b8185 | 2019-06-14 22:28:42 -0700 | [diff] [blame] | 24 | |
| 25 | from pylint.pyreverse import inspector |
Ashley Whetter | 33b8185 | 2019-06-14 22:28:42 -0700 | [diff] [blame] | 26 | |
| 27 | |
| 28 | @pytest.fixture |
DudeNr33 | 2150196 | 2021-08-09 06:44:21 +0200 | [diff] [blame] | 29 | def project(get_project): |
Ashley Whetter | 33b8185 | 2019-06-14 22:28:42 -0700 | [diff] [blame] | 30 | project = get_project("data", "data") |
| 31 | linker = inspector.Linker(project) |
| 32 | linker.visit(project) |
| 33 | return project |
| 34 | |
| 35 | |
| 36 | def test_class_implements(project): |
| 37 | klass = project.get_module("data.clientmodule_test")["Ancestor"] |
| 38 | assert hasattr(klass, "implements") |
| 39 | assert len(klass.implements) == 1 |
Marc Mueller | 7ed757e | 2021-08-19 09:01:49 +0200 | [diff] [blame] | 40 | assert isinstance(klass.implements[0], nodes.ClassDef) |
Ashley Whetter | 33b8185 | 2019-06-14 22:28:42 -0700 | [diff] [blame] | 41 | assert klass.implements[0].name == "Interface" |
| 42 | |
| 43 | |
| 44 | def test_class_implements_specialization(project): |
| 45 | klass = project.get_module("data.clientmodule_test")["Specialization"] |
| 46 | assert hasattr(klass, "implements") |
| 47 | assert len(klass.implements) == 0 |
| 48 | |
| 49 | |
| 50 | def test_locals_assignment_resolution(project): |
| 51 | klass = project.get_module("data.clientmodule_test")["Specialization"] |
| 52 | assert hasattr(klass, "locals_type") |
| 53 | type_dict = klass.locals_type |
| 54 | assert len(type_dict) == 2 |
| 55 | keys = sorted(type_dict.keys()) |
| 56 | assert keys == ["TYPE", "top"] |
| 57 | assert len(type_dict["TYPE"]) == 1 |
| 58 | assert type_dict["TYPE"][0].value == "final class" |
| 59 | assert len(type_dict["top"]) == 1 |
| 60 | assert type_dict["top"][0].value == "class" |
| 61 | |
| 62 | |
| 63 | def test_instance_attrs_resolution(project): |
| 64 | klass = project.get_module("data.clientmodule_test")["Specialization"] |
| 65 | assert hasattr(klass, "instance_attrs_type") |
| 66 | type_dict = klass.instance_attrs_type |
Mark Byrne | b71be8a | 2021-07-30 20:21:02 +0200 | [diff] [blame] | 67 | assert len(type_dict) == 3 |
Ashley Whetter | 33b8185 | 2019-06-14 22:28:42 -0700 | [diff] [blame] | 68 | keys = sorted(type_dict.keys()) |
Mark Byrne | b71be8a | 2021-07-30 20:21:02 +0200 | [diff] [blame] | 69 | assert keys == ["_id", "relation", "relation2"] |
Pierre Sassoulas | 14f20e2 | 2021-03-27 15:21:29 +0100 | [diff] [blame] | 70 | assert isinstance(type_dict["relation"][0], astroid.bases.Instance), type_dict[ |
| 71 | "relation" |
| 72 | ] |
Ashley Whetter | 33b8185 | 2019-06-14 22:28:42 -0700 | [diff] [blame] | 73 | assert type_dict["relation"][0].name == "DoNothing" |
| 74 | assert type_dict["_id"][0] is astroid.Uninferable |
| 75 | |
| 76 | |
| 77 | def test_concat_interfaces(): |
| 78 | cls = astroid.extract_node( |
| 79 | ''' |
| 80 | class IMachin: pass |
| 81 | |
| 82 | class Correct2: |
| 83 | """docstring""" |
| 84 | __implements__ = (IMachin,) |
| 85 | |
| 86 | class BadArgument: |
| 87 | """docstring""" |
| 88 | __implements__ = (IMachin,) |
| 89 | |
| 90 | class InterfaceCanNowBeFound: #@ |
| 91 | """docstring""" |
| 92 | __implements__ = BadArgument.__implements__ + Correct2.__implements__ |
| 93 | ''' |
| 94 | ) |
| 95 | interfaces = inspector.interfaces(cls) |
| 96 | assert [i.name for i in interfaces] == ["IMachin"] |
| 97 | |
| 98 | |
| 99 | def test_interfaces(): |
| 100 | module = astroid.parse( |
| 101 | """ |
| 102 | class Interface(object): pass |
| 103 | class MyIFace(Interface): pass |
| 104 | class AnotherIFace(Interface): pass |
| 105 | class Concrete0(object): |
| 106 | __implements__ = MyIFace |
| 107 | class Concrete1: |
| 108 | __implements__ = (MyIFace, AnotherIFace) |
| 109 | class Concrete2: |
| 110 | __implements__ = (MyIFace, AnotherIFace) |
| 111 | class Concrete23(Concrete1): pass |
| 112 | """ |
| 113 | ) |
| 114 | |
| 115 | for klass, interfaces in ( |
| 116 | ("Concrete0", ["MyIFace"]), |
| 117 | ("Concrete1", ["MyIFace", "AnotherIFace"]), |
| 118 | ("Concrete2", ["MyIFace", "AnotherIFace"]), |
| 119 | ("Concrete23", ["MyIFace", "AnotherIFace"]), |
| 120 | ): |
| 121 | klass = module[klass] |
| 122 | assert [i.name for i in inspector.interfaces(klass)] == interfaces |
| 123 | |
| 124 | |
| 125 | def test_from_directory(project): |
| 126 | expected = os.path.join("tests", "data", "__init__.py") |
| 127 | assert project.name == "data" |
| 128 | assert project.path.endswith(expected) |
| 129 | |
| 130 | |
| 131 | def test_project_node(project): |
| 132 | expected = ["data", "data.clientmodule_test", "data.suppliermodule_test"] |
| 133 | assert sorted(project.keys()) == expected |