Path 1: 9356 calls (0.45)

Name (9347) AssignName (7) DelName (2)

Expr (3350) Assign (1458) AnnAssign (908) FunctionDef (696) Return (618) ExceptHandler (548) Raise (476) For (419) ClassDef (283) If (260)

FunctionDef (6137) Module (2245) ClassDef (898) AsyncFunctionDef (76)

NamesConsumer (9356)

'function' (5941) 'module' (1774) 'class' (867) 'comprehension' (601) 'lambda' (173)

tuple (9356)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 2: 5040 calls (0.24)

Name (4886) AssignName (152) DelName (2)

Expr (1602) Assign (1330) If (552) Return (315) FunctionDef (260) AugAssign (225) ClassDef (195) AnnAssign (175) With (116) For (113)

FunctionDef (2397) Module (2342) ClassDef (273) AsyncFunctionDef (28)

NamesConsumer (5040)

'function' (2387) 'module' (2120) 'class' (271) 'comprehension' (195) 'lambda' (67)

tuple (5040)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 3: 4182 calls (0.2)

Name (4096) AssignName (76) DelName (10)

Expr (1153) Return (988) Assign (871) If (597) For (170) AugAssign (115) AnnAssign (94) Raise (60) With (60) Assert (46)

FunctionDef (3258) Module (878) AsyncFunctionDef (46)

NamesConsumer (4182)

'function' (3268) 'module' (852) 'comprehension' (36) 'lambda' (26)

tuple (4182)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 4: 996 calls (0.05)

Name (996)

FunctionDef (236) Expr (208) ClassDef (167) Assign (166) Return (106) AnnAssign (37) If (22) With (20) Raise (11) For (6)

FunctionDef (596) ClassDef (271) Module (115) AsyncFunctionDef (14)

NamesConsumer (996)

'function' (607) 'class' (259) 'module' (113) 'lambda' (13) 'comprehension' (4)

tuple (996)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 5: 644 calls (0.03)

Name (644)

ClassDef (237) Assign (144) Expr (127) Return (50) FunctionDef (26) Raise (12) AnnAssign (10) AsyncWith (9) For (8) With (6)

ClassDef (255) Module (200) FunctionDef (178) AsyncFunctionDef (11)

NamesConsumer (644)

'class' (255) 'module' (200) 'function' (189)

tuple (644)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 6: 472 calls (0.02)

Name (471) AssignName (1)

Assign (285) Expr (133) Return (30) FunctionDef (8) Assert (7) For (4) If (3) Raise (1) AugAssign (1)

Module (369) FunctionDef (96) AsyncFunctionDef (7)

NamesConsumer (472)

'comprehension' (285) 'lambda' (181) 'module' (4) 'function' (2)

tuple (472)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 7: 46 calls (0.0)

Name (46)

Expr (33) Raise (9) If (4)

FunctionDef (37) Module (9)

NamesConsumer (46)

'function' (37) 'module' (9)

tuple (46)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 8: 33 calls (0.0)

Name (33)

Expr (20) Assign (6) Assert (2) If (2) AnnAssign (1) AugAssign (1) Return (1)

Module (25) FunctionDef (8)

NamesConsumer (33)

'module' (23) 'function' (8) 'lambda' (2)

tuple (33)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 9: 23 calls (0.0)

Name (23)

Assign (14) Expr (4) Return (3) AnnAssign (1) AugAssign (1)

FunctionDef (16) Module (7)

NamesConsumer (23)

'function' (15) 'module' (7) 'lambda' (1)

tuple (23)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 10: 20 calls (0.0)

Name (20)

Assign (19) If (1)

ClassDef (20)

NamesConsumer (20)

'lambda' (17) 'comprehension' (3)

tuple (20)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 11: 16 calls (0.0)

Name (16)

Assign (16)

Module (15) FunctionDef (1)

NamesConsumer (16)

'lambda' (16)

tuple (16)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 12: 14 calls (0.0)

Name (14)

If (6) Expr (5) Assign (3)

FunctionDef (12) Module (2)

NamesConsumer (14)

'function' (12) 'module' (2)

tuple (14)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 13: 13 calls (0.0)

Name (13)

FunctionDef (9) ClassDef (3) Expr (1)

FunctionDef (10) ClassDef (3)

NamesConsumer (13)

'function' (10) 'class' (3)

tuple (13)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 14: 11 calls (0.0)

Name (11)

Assign (6) If (2) Assert (1) Expr (1) Return (1)

Module (7) FunctionDef (4)

NamesConsumer (11)

'module' (7) 'function' (4)

tuple (11)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 15: 10 calls (0.0)

Name (10)

If (6) Assign (4)

ClassDef (10)

NamesConsumer (10)

'class' (9) 'comprehension' (1)

tuple (10)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 16: 7 calls (0.0)

Name (7)

FunctionDef (5) AnnAssign (2)

FunctionDef (5) ClassDef (2)

NamesConsumer (7)

'function' (5) 'class' (2)

tuple (7)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 17: 7 calls (0.0)

Name (5) AssignName (2)

Assign (5) AugAssign (2)

ClassDef (7)

NamesConsumer (7)

'class' (7)

tuple (7)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 18: 6 calls (0.0)

Name (6)

Expr (5) If (1)

FunctionDef (6)

NamesConsumer (6)

'function' (6)

tuple (6)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 19: 5 calls (0.0)

Name (5)

FunctionDef (5)

FunctionDef (5)

NamesConsumer (5)

'function' (5)

tuple (5)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 20: 5 calls (0.0)

AssignName (3) DelName (2)

AugAssign (3) Delete (2)

FunctionDef (4) Module (1)

NamesConsumer (5)

'function' (4) 'module' (1)

tuple (5)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 21: 4 calls (0.0)

Name (4)

FunctionDef (3) AsyncFunctionDef (1)

FunctionDef (3) AsyncFunctionDef (1)

NamesConsumer (4)

'function' (4)

tuple (4)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 22: 3 calls (0.0)

Name (3)

Assign (3)

ClassDef (3)

NamesConsumer (3)

'lambda' (2) 'comprehension' (1)

tuple (3)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 23: 3 calls (0.0)

Name (3)

FunctionDef (3)

FunctionDef (3)

NamesConsumer (3)

'comprehension' (3)

tuple (3)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 24: 3 calls (0.0)

Name (3)

Expr (3)

Module (3)

NamesConsumer (3)

'module' (3)

tuple (3)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 25: 2 calls (0.0)

Name (2)

Assign (1) Expr (1)

Module (1) FunctionDef (1)

NamesConsumer (2)

'comprehension' (2)

tuple (2)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 26: 2 calls (0.0)

Name (2)

Assign (2)

ClassDef (2)

NamesConsumer (2)

'lambda' (2)

tuple (2)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 27: 2 calls (0.0)

Name (2)

AnnAssign (2)

ClassDef (2)

NamesConsumer (2)

'class' (2)

tuple (2)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 28: 2 calls (0.0)

Name (2)

Assign (2)

ClassDef (2)

NamesConsumer (2)

'lambda' (2)

tuple (2)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 29: 2 calls (0.0)

Name (2)

Expr (2)

FunctionDef (2)

NamesConsumer (2)

'function' (2)

tuple (2)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 30: 2 calls (0.0)

Name (2)

Expr (2)

Module (2)

NamesConsumer (2)

'module' (2)

tuple (2)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 31: 1 calls (0.0)

Name (1)

Assign (1)

ClassDef (1)

NamesConsumer (1)

'lambda' (1)

tuple (1)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 32: 1 calls (0.0)

Name (1)

Assign (1)

ClassDef (1)

NamesConsumer (1)

'class' (1)

tuple (1)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 33: 1 calls (0.0)

Name (1)

Assign (1)

Module (1)

NamesConsumer (1)

'module' (1)

tuple (1)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 34: 1 calls (0.0)

Name (1)

ClassDef (1)

ClassDef (1)

NamesConsumer (1)

'class' (1)

tuple (1)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 35: 1 calls (0.0)

Name (1)

Assign (1)

ClassDef (1)

NamesConsumer (1)

'lambda' (1)

tuple (1)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 36: 1 calls (0.0)

Name (1)

ClassDef (1)

ClassDef (1)

NamesConsumer (1)

'comprehension' (1)

tuple (1)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 37: 1 calls (0.0)

Name (1)

Assign (1)

Module (1)

NamesConsumer (1)

'lambda' (1)

tuple (1)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 38: 1 calls (0.0)

Name (1)

AnnAssign (1)

ClassDef (1)

NamesConsumer (1)

'class' (1)

tuple (1)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)
            

Path 39: 1 calls (0.0)

Name (1)

AnnAssign (1)

FunctionDef (1)

NamesConsumer (1)

'function' (1)

tuple (1)

1def _check_consumer(
2        self,
3        node: nodes.Name,
4        stmt: nodes.NodeNG,
5        frame: nodes.LocalsDictNodeNG,
6        current_consumer: NamesConsumer,
7        base_scope_type: str,
8    ) -> tuple[VariableVisitConsumerAction, list[nodes.NodeNG] | None]:
9        """Checks a consumer for conditions that should trigger messages."""
10        # If the name has already been consumed, only check it's not a loop
11        # variable used outside the loop.
12        if node.name in current_consumer.consumed:
13            # Avoid the case where there are homonyms inside function scope and
14            # comprehension current scope (avoid bug #1731)
15            if utils.is_func_decorator(current_consumer.node) or not isinstance(
16                node, nodes.ComprehensionScope
17            ):
18                self._check_late_binding_closure(node)
19                return (VariableVisitConsumerAction.RETURN, None)
20
21        found_nodes = current_consumer.get_next_to_consume(node)
22        if found_nodes is None:
23            return (VariableVisitConsumerAction.CONTINUE, None)
24        if not found_nodes:
25            if node.name in current_consumer.consumed_uncertain:
26                confidence = CONTROL_FLOW
27            else:
28                confidence = HIGH
29            self.add_message(
30                "used-before-assignment",
31                args=node.name,
32                node=node,
33                confidence=confidence,
34            )
35            # Mark for consumption any nodes added to consumed_uncertain by
36            # get_next_to_consume() because they might not have executed.
37            return (
38                VariableVisitConsumerAction.RETURN,
39                current_consumer.consumed_uncertain[node.name],
40            )
41
42        self._check_late_binding_closure(node)
43
44        defnode = utils.assign_parent(found_nodes[0])
45        defstmt = defnode.statement(future=True)
46        defframe = defstmt.frame(future=True)
47
48        # The class reuses itself in the class scope.
49        is_recursive_klass: bool = (
50            frame is defframe
51            and defframe.parent_of(node)
52            and isinstance(defframe, nodes.ClassDef)
53            and node.name == defframe.name
54        )
55
56        if (
57            is_recursive_klass
58            and utils.get_node_first_ancestor_of_type(node, nodes.Lambda)
59            and (
60                not utils.is_default_argument(node)
61                or node.scope().parent.scope() is not defframe
62            )
63        ):
64            # Self-referential class references are fine in lambda's --
65            # As long as they are not part of the default argument directly
66            # under the scope of the parent self-referring class.
67            # Example of valid default argument:
68            # class MyName3:
69            #     myattr = 1
70            #     mylambda3 = lambda: lambda a=MyName3: a
71            # Example of invalid default argument:
72            # class MyName4:
73            #     myattr = 1
74            #     mylambda4 = lambda a=MyName4: lambda: a
75
76            # If the above conditional is True,
77            # there is no possibility of undefined-variable
78            # Also do not consume class name
79            # (since consuming blocks subsequent checks)
80            # -- quit
81            return (VariableVisitConsumerAction.RETURN, None)
82
83        (
84            maybe_before_assign,
85            annotation_return,
86            use_outer_definition,
87        ) = self._is_variable_violation(
88            node,
89            defnode,
90            stmt,
91            defstmt,
92            frame,
93            defframe,
94            base_scope_type,
95            is_recursive_klass,
96        )
97
98        if use_outer_definition:
99            return (VariableVisitConsumerAction.CONTINUE, None)
100
101        if (
102            maybe_before_assign
103            and not utils.is_defined_before(node)
104            and not astroid.are_exclusive(stmt, defstmt, ("NameError",))
105        ):
106            # Used and defined in the same place, e.g `x += 1` and `del x`
107            defined_by_stmt = defstmt is stmt and isinstance(
108                node, (nodes.DelName, nodes.AssignName)
109            )
110            if (
111                is_recursive_klass
112                or defined_by_stmt
113                or annotation_return
114                or isinstance(defstmt, nodes.Delete)
115            ):
116                if not utils.node_ignores_exception(node, NameError):
117                    # Handle postponed evaluation of annotations
118                    if not (
119                        self._postponed_evaluation_enabled
120                        and isinstance(
121                            stmt,
122                            (
123                                nodes.AnnAssign,
124                                nodes.FunctionDef,
125                                nodes.Arguments,
126                            ),
127                        )
128                        and node.name in node.root().locals
129                    ):
130                        if defined_by_stmt:
131                            return (VariableVisitConsumerAction.CONTINUE, [node])
132                        return (VariableVisitConsumerAction.CONTINUE, None)
133
134            elif base_scope_type != "lambda":
135                # E0601 may *not* occurs in lambda scope.
136
137                # Skip postponed evaluation of annotations
138                # and unevaluated annotations inside a function body
139                if not (
140                    self._postponed_evaluation_enabled
141                    and isinstance(stmt, (nodes.AnnAssign, nodes.FunctionDef))
142                ) and not (
143                    isinstance(stmt, nodes.AnnAssign)
144                    and utils.get_node_first_ancestor_of_type(stmt, nodes.FunctionDef)
145                ):
146                    self.add_message(
147                        "used-before-assignment",
148                        args=node.name,
149                        node=node,
150                        confidence=HIGH,
151                    )
152                    return (VariableVisitConsumerAction.RETURN, found_nodes)
153
154            elif base_scope_type == "lambda":
155                # E0601 can occur in class-level scope in lambdas, as in
156                # the following example:
157                #   class A:
158                #      x = lambda attr: f + attr
159                #      f = 42
160                # We check lineno because doing the following is fine:
161                #   class A:
162                #      x = 42
163                #      y = lambda attr: x + attr
164                if (
165                    isinstance(frame, nodes.ClassDef)
166                    and node.name in frame.locals
167                    and stmt.fromlineno <= defstmt.fromlineno
168                ):
169                    self.add_message(
170                        "used-before-assignment",
171                        args=node.name,
172                        node=node,
173                        confidence=HIGH,
174                    )
175
176        elif self._is_only_type_assignment(node, defstmt):
177            if node.scope().locals.get(node.name):
178                self.add_message(
179                    "used-before-assignment", args=node.name, node=node, confidence=HIGH
180                )
181            else:
182                self.add_message(
183                    "undefined-variable", args=node.name, node=node, confidence=HIGH
184                )
185            return (VariableVisitConsumerAction.RETURN, found_nodes)
186
187        elif isinstance(defstmt, nodes.ClassDef):
188            return self._is_first_level_self_reference(node, defstmt, found_nodes)
189
190        elif isinstance(defnode, nodes.NamedExpr):
191            if isinstance(defnode.parent, nodes.IfExp):
192                if self._is_never_evaluated(defnode, defnode.parent):
193                    self.add_message(
194                        "undefined-variable",
195                        args=node.name,
196                        node=node,
197                        confidence=INFERENCE,
198                    )
199                    return (VariableVisitConsumerAction.RETURN, found_nodes)
200
201        return (VariableVisitConsumerAction.RETURN, found_nodes)