Skip to content

Commit ea7db79

Browse files
Add assigned_stmts() to PEP 695 nodes (#2320)
(cherry picked from commit d7be465)
1 parent 1f57444 commit ea7db79

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ What's New in astroid 3.0.1?
1313
============================
1414
Release date: TBA
1515

16+
* Fix crashes linting code using PEP 695 (Python 3.12) generic type syntax.
17+
18+
Closes pylint-dev/pylint#9098
1619

1720

1821
What's New in astroid 3.0.0?

astroid/nodes/node_classes.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3405,6 +3405,11 @@ def _infer(
34053405
) -> Iterator[ParamSpec]:
34063406
yield self
34073407

3408+
assigned_stmts = protocols.generic_type_assigned_stmts
3409+
"""Returns the assigned statement (non inferred) according to the assignment type.
3410+
See astroid/protocols.py for actual implementation.
3411+
"""
3412+
34083413

34093414
class Pass(_base_nodes.NoChildrenNode, _base_nodes.Statement):
34103415
"""Class representing an :class:`ast.Pass` node.
@@ -4153,6 +4158,11 @@ def _infer(
41534158
) -> Iterator[TypeVar]:
41544159
yield self
41554160

4161+
assigned_stmts = protocols.generic_type_assigned_stmts
4162+
"""Returns the assigned statement (non inferred) according to the assignment type.
4163+
See astroid/protocols.py for actual implementation.
4164+
"""
4165+
41564166

41574167
class TypeVarTuple(_base_nodes.AssignTypeNode):
41584168
"""Class representing a :class:`ast.TypeVarTuple` node.
@@ -4192,6 +4202,11 @@ def _infer(
41924202
) -> Iterator[TypeVarTuple]:
41934203
yield self
41944204

4205+
assigned_stmts = protocols.generic_type_assigned_stmts
4206+
"""Returns the assigned statement (non inferred) according to the assignment type.
4207+
See astroid/protocols.py for actual implementation.
4208+
"""
4209+
41954210

41964211
UNARY_OP_METHOD = {
41974212
"+": "__pos__",

astroid/protocols.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,3 +915,17 @@ def match_as_assigned_stmts(
915915
and self.pattern is None
916916
):
917917
yield self.parent.parent.subject
918+
919+
920+
@decorators.yes_if_nothing_inferred
921+
def generic_type_assigned_stmts(
922+
self: nodes.TypeVar | nodes.TypeVarTuple | nodes.ParamSpec,
923+
node: nodes.AssignName,
924+
context: InferenceContext | None = None,
925+
assign_path: None = None,
926+
) -> Generator[nodes.NodeNG, None, None]:
927+
"""Return empty generator (return -> raises StopIteration) so inferred value
928+
is Uninferable.
929+
"""
930+
return
931+
yield

tests/test_protocols.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import astroid
1515
from astroid import extract_node, nodes
16-
from astroid.const import PY310_PLUS
16+
from astroid.const import PY310_PLUS, PY312_PLUS
1717
from astroid.exceptions import InferenceError
1818
from astroid.manager import AstroidManager
1919
from astroid.util import Uninferable, UninferableBase
@@ -415,3 +415,30 @@ def test_assigned_stmts_match_as():
415415
assert match_as.name
416416
assigned_match_as = next(match_as.name.assigned_stmts())
417417
assert assigned_match_as == subject
418+
419+
420+
@pytest.mark.skipif(not PY312_PLUS, reason="Generic typing syntax requires python 3.12")
421+
class TestGenericTypeSyntax:
422+
@staticmethod
423+
def test_assigned_stmts_type_var():
424+
"""The result is 'Uninferable' and no exception is raised."""
425+
assign_stmts = extract_node("type Point[T] = tuple[float, float]")
426+
type_var: nodes.TypeVar = assign_stmts.type_params[0]
427+
assigned = next(type_var.name.assigned_stmts())
428+
assert assigned is Uninferable
429+
430+
@staticmethod
431+
def test_assigned_stmts_type_var_tuple():
432+
"""The result is 'Uninferable' and no exception is raised."""
433+
assign_stmts = extract_node("type Alias[*Ts] = tuple[*Ts]")
434+
type_var_tuple: nodes.TypeVarTuple = assign_stmts.type_params[0]
435+
assigned = next(type_var_tuple.name.assigned_stmts())
436+
assert assigned is Uninferable
437+
438+
@staticmethod
439+
def test_assigned_stmts_param_spec():
440+
"""The result is 'Uninferable' and no exception is raised."""
441+
assign_stmts = extract_node("type Alias[**P] = Callable[P, int]")
442+
param_spec: nodes.ParamSpec = assign_stmts.type_params[0]
443+
assigned = next(param_spec.name.assigned_stmts())
444+
assert assigned is Uninferable

0 commit comments

Comments
 (0)