Path 1: 13 calls (0.5)

Dict (13)

None (13)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return
            

Path 2: 2 calls (0.08)

Dict (2)

None (2)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return
            

Path 3: 2 calls (0.08)

Dict (2)

None (2)

GeneratorExit (2)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return
            

Path 4: 2 calls (0.08)

Dict (2)

GeneratorExit (2)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return
            

Path 5: 1 calls (0.04)

Dict (1)

None (1)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return
            

Path 6: 1 calls (0.04)

Dict (1)

None (1)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return
            

Path 7: 1 calls (0.04)

Dict (1)

None (1)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return
            

Path 8: 1 calls (0.04)

Dict (1)

None (1)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return
            

Path 9: 1 calls (0.04)

Dict (1)

None (1)

GeneratorExit (1)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return
            

Path 10: 1 calls (0.04)

Dict (1)

None (1)

GeneratorExit (1)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return
            

Path 11: 1 calls (0.04)

Dict (1)

None (1)

GeneratorExit (1)

1def _check_dict_consider_namedtuple_dataclass(self, node: nodes.Dict) -> None:
2        """Check if dictionary values can be replaced by Namedtuple or Dataclass."""
3        if not (
4            isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
5            and isinstance(node.parent.parent, nodes.Module)
6            or isinstance(node.parent, nodes.AnnAssign)
7            and isinstance(node.parent.target, nodes.AssignName)
8            and utils.is_assign_name_annotated_with(node.parent.target, "Final")
9        ):
10            # If dict is not part of an 'Assign' or 'AnnAssign' node in
11            # a module context OR 'AnnAssign' with 'Final' annotation, skip check.
12            return
13
14        # All dict_values are itself dict nodes
15        if len(node.items) > 1 and all(
16            isinstance(dict_value, nodes.Dict) for _, dict_value in node.items
17        ):
18            KeyTupleT = Tuple[Type[nodes.NodeNG], str]
19
20            # Makes sure all keys are 'Const' string nodes
21            keys_checked: set[KeyTupleT] = set()
22            for _, dict_value in node.items:
23                dict_value = cast(nodes.Dict, dict_value)
24                for key, _ in dict_value.items:
25                    key_tuple = (type(key), key.as_string())
26                    if key_tuple in keys_checked:
27                        continue
28                    inferred = safe_infer(key)
29                    if not (
30                        isinstance(inferred, nodes.Const)
31                        and inferred.pytype() == "builtins.str"
32                    ):
33                        return
34                    keys_checked.add(key_tuple)
35
36            # Makes sure all subdicts have at least 1 common key
37            key_tuples: list[tuple[KeyTupleT, ...]] = []
38            for _, dict_value in node.items:
39                dict_value = cast(nodes.Dict, dict_value)
40                key_tuples.append(
41                    tuple((type(key), key.as_string()) for key, _ in dict_value.items)
42                )
43            keys_intersection: set[KeyTupleT] = set(key_tuples[0])
44            for sub_key_tuples in key_tuples[1:]:
45                keys_intersection.intersection_update(sub_key_tuples)
46            if not keys_intersection:
47                return
48
49            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
50            return
51
52        # All dict_values are itself either list or tuple nodes
53        if len(node.items) > 1 and all(
54            isinstance(dict_value, (nodes.List, nodes.Tuple))
55            for _, dict_value in node.items
56        ):
57            # Make sure all sublists have the same length > 0
58            list_length = len(node.items[0][1].elts)
59            if list_length == 0:
60                return
61            for _, dict_value in node.items[1:]:
62                if len(dict_value.elts) != list_length:
63                    return
64
65            # Make sure at least one list entry isn't a dict
66            for _, dict_value in node.items:
67                if all(isinstance(entry, nodes.Dict) for entry in dict_value.elts):
68                    return
69
70            self.add_message("consider-using-namedtuple-or-dataclass", node=node)
71            return