Path 1: 3480 calls (0.21)

Name (3466) AssignName (13) DelName (1)

None (3480)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 2: 2663 calls (0.16)

Name (2657) DelName (3) AssignName (3)

None (2663)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 3: 2420 calls (0.15)

Name (2420)

None (2420)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 4: 2417 calls (0.14)

Name (2417)

None (2417)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 5: 1359 calls (0.08)

Name (1225) AssignName (134)

None (1359)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 6: 1351 calls (0.08)

Name (1323) AssignName (26) DelName (2)

None (1351)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 7: 1112 calls (0.07)

Name (1103) AssignName (8) DelName (1)

None (1112)

GeneratorExit (1112)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 8: 660 calls (0.04)

Name (655) DelName (4) AssignName (1)

None (660)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 9: 337 calls (0.02)

Name (337)

None (337)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 10: 224 calls (0.01)

Name (223) DelName (1)

None (224)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 11: 181 calls (0.01)

Name (177) AssignName (3) DelName (1)

None (181)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 12: 129 calls (0.01)

Name (124) AssignName (4) DelName (1)

None (129)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 13: 102 calls (0.01)

Name (100) AssignName (2)

None (102)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 14: 92 calls (0.01)

Name (52) AssignName (40)

None (92)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 15: 87 calls (0.01)

Name (87)

None (87)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 16: 16 calls (0.0)

Name (16)

None (16)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 17: 11 calls (0.0)

Name (11)

None (11)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 18: 7 calls (0.0)

Name (7)

None (7)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 19: 5 calls (0.0)

Name (5)

None (5)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 20: 5 calls (0.0)

Name (5)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 21: 4 calls (0.0)

Name (4)

None (4)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 22: 4 calls (0.0)

Name (4)

None (4)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 23: 3 calls (0.0)

Name (3)

None (3)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 24: 3 calls (0.0)

Name (3)

None (3)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 25: 2 calls (0.0)

Name (2)

None (2)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 26: 2 calls (0.0)

Name (2)

None (2)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 27: 2 calls (0.0)

Name (2)

None (2)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 28: 1 calls (0.0)

Name (1)

None (1)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 29: 1 calls (0.0)

Name (1)

None (1)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 30: 1 calls (0.0)

Name (1)

None (1)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 31: 1 calls (0.0)

Name (1)

None (1)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 32: 1 calls (0.0)

Name (1)

None (1)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 33: 1 calls (0.0)

Name (1)

None (1)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 34: 1 calls (0.0)

Name (1)

None (1)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 35: 1 calls (0.0)

Name (1)

None (1)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)
            

Path 36: 1 calls (0.0)

Name (1)

None (1)

1def _loopvar_name(self, node: astroid.Name) -> None:
2        # filter variables according to node's scope
3        astmts = [s for s in node.lookup(node.name)[1] if hasattr(s, "assign_type")]
4        # If this variable usage exists inside a function definition
5        # that exists in the same loop,
6        # the usage is safe because the function will not be defined either if
7        # the variable is not defined.
8        scope = node.scope()
9        # FunctionDef subclasses Lambda due to a curious ontology. Check both.
10        # See https://github.com/PyCQA/astroid/issues/291
11        # TODO: Revisit when astroid 3.0 includes the change
12        if isinstance(scope, nodes.Lambda) and any(
13            asmt.scope().parent_of(scope) for asmt in astmts
14        ):
15            return
16        # Filter variables according to their respective scope. Test parent
17        # and statement to avoid #74747. This is not a total fix, which would
18        # introduce a mechanism similar to special attribute lookup in
19        # modules. Also, in order to get correct inference in this case, the
20        # scope lookup rules would need to be changed to return the initial
21        # assignment (which does not exist in code per se) as well as any later
22        # modifications.
23        if (
24            not astmts  # pylint: disable=too-many-boolean-expressions
25            or (
26                astmts[0].parent == astmts[0].root()
27                and astmts[0].parent.parent_of(node)
28            )
29            or (
30                astmts[0].is_statement
31                or not isinstance(astmts[0].parent, nodes.Module)
32                and astmts[0].statement(future=True).parent_of(node)
33            )
34        ):
35            _astmts = []
36        else:
37            _astmts = astmts[:1]
38        for i, stmt in enumerate(astmts[1:]):
39            if astmts[i].statement(future=True).parent_of(
40                stmt
41            ) and not utils.in_for_else_branch(astmts[i].statement(future=True), stmt):
42                continue
43            _astmts.append(stmt)
44        astmts = _astmts
45        if len(astmts) != 1:
46            return
47
48        assign = astmts[0].assign_type()
49        if not (
50            isinstance(assign, (nodes.For, nodes.Comprehension, nodes.GeneratorExp))
51            and assign.statement(future=True) is not node.statement(future=True)
52        ):
53            return
54
55        if not isinstance(assign, nodes.For):
56            self.add_message("undefined-loop-variable", args=node.name, node=node)
57            return
58        for else_stmt in assign.orelse:
59            if isinstance(
60                else_stmt, (nodes.Return, nodes.Raise, nodes.Break, nodes.Continue)
61            ):
62                return
63            # TODO: 2.16: Consider using RefactoringChecker._is_function_def_never_returning
64            if isinstance(else_stmt, nodes.Expr) and isinstance(
65                else_stmt.value, nodes.Call
66            ):
67                inferred_func = utils.safe_infer(else_stmt.value.func)
68                if (
69                    isinstance(inferred_func, nodes.FunctionDef)
70                    and inferred_func.returns
71                ):
72                    inferred_return = utils.safe_infer(inferred_func.returns)
73                    if isinstance(
74                        inferred_return, nodes.FunctionDef
75                    ) and inferred_return.qname() in {
76                        *TYPING_NORETURN,
77                        *TYPING_NEVER,
78                        "typing._SpecialForm",
79                    }:
80                        return
81                    # typing_extensions.NoReturn returns a _SpecialForm
82                    if (
83                        isinstance(inferred_return, bases.Instance)
84                        and inferred_return.qname() == "typing._SpecialForm"
85                    ):
86                        return
87
88        maybe_walrus = utils.get_node_first_ancestor_of_type(node, nodes.NamedExpr)
89        if maybe_walrus:
90            maybe_comprehension = utils.get_node_first_ancestor_of_type(
91                maybe_walrus, nodes.Comprehension
92            )
93            if maybe_comprehension:
94                comprehension_scope = utils.get_node_first_ancestor_of_type(
95                    maybe_comprehension, nodes.ComprehensionScope
96                )
97                if comprehension_scope is None:
98                    # Should not be possible.
99                    pass
100                elif (
101                    comprehension_scope.parent.scope() is scope
102                    and node.name in comprehension_scope.locals
103                ):
104                    return
105
106        # For functions we can do more by inferring the length of the itered object
107        try:
108            inferred = next(assign.iter.infer())
109            # Prefer the target of enumerate() rather than the enumerate object itself
110            if (
111                isinstance(inferred, astroid.Instance)
112                and inferred.qname() == "builtins.enumerate"
113            ):
114                likely_call = assign.iter
115                if isinstance(assign.iter, nodes.IfExp):
116                    likely_call = assign.iter.body
117                if isinstance(likely_call, nodes.Call):
118                    inferred = next(likely_call.args[0].infer())
119        except astroid.InferenceError:
120            self.add_message("undefined-loop-variable", args=node.name, node=node)
121        else:
122            if (
123                isinstance(inferred, astroid.Instance)
124                and inferred.qname() == BUILTIN_RANGE
125            ):
126                # Consider range() objects safe, even if they might not yield any results.
127                return
128
129            # Consider sequences.
130            sequences = (
131                nodes.List,
132                nodes.Tuple,
133                nodes.Dict,
134                nodes.Set,
135                astroid.objects.FrozenSet,
136            )
137            if not isinstance(inferred, sequences):
138                self.add_message("undefined-loop-variable", args=node.name, node=node)
139                return
140
141            elements = getattr(inferred, "elts", getattr(inferred, "items", []))
142            if not elements:
143                self.add_message("undefined-loop-variable", args=node.name, node=node)