Skip to content

Commit

Permalink
Add assigned_stmts() to PEP 695 nodes (#2320)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobtylerwalls authored Oct 15, 2023
1 parent ab75985 commit d7be465
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 1 deletion.
3 changes: 3 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ What's New in astroid 3.0.1?
============================
Release date: TBA

* Fix crashes linting code using PEP 695 (Python 3.12) generic type syntax.

Closes pylint-dev/pylint#9098


What's New in astroid 3.0.0?
Expand Down
15 changes: 15 additions & 0 deletions astroid/nodes/node_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3405,6 +3405,11 @@ def _infer(
) -> Iterator[ParamSpec]:
yield self

assigned_stmts = protocols.generic_type_assigned_stmts
"""Returns the assigned statement (non inferred) according to the assignment type.
See astroid/protocols.py for actual implementation.
"""


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

assigned_stmts = protocols.generic_type_assigned_stmts
"""Returns the assigned statement (non inferred) according to the assignment type.
See astroid/protocols.py for actual implementation.
"""


class TypeVarTuple(_base_nodes.AssignTypeNode):
"""Class representing a :class:`ast.TypeVarTuple` node.
Expand Down Expand Up @@ -4192,6 +4202,11 @@ def _infer(
) -> Iterator[TypeVarTuple]:
yield self

assigned_stmts = protocols.generic_type_assigned_stmts
"""Returns the assigned statement (non inferred) according to the assignment type.
See astroid/protocols.py for actual implementation.
"""


UNARY_OP_METHOD = {
"+": "__pos__",
Expand Down
14 changes: 14 additions & 0 deletions astroid/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -915,3 +915,17 @@ def match_as_assigned_stmts(
and self.pattern is None
):
yield self.parent.parent.subject


@decorators.yes_if_nothing_inferred
def generic_type_assigned_stmts(
self: nodes.TypeVar | nodes.TypeVarTuple | nodes.ParamSpec,
node: nodes.AssignName,
context: InferenceContext | None = None,
assign_path: None = None,
) -> Generator[nodes.NodeNG, None, None]:
"""Return empty generator (return -> raises StopIteration) so inferred value
is Uninferable.
"""
return
yield
29 changes: 28 additions & 1 deletion tests/test_protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import astroid
from astroid import extract_node, nodes
from astroid.const import PY310_PLUS
from astroid.const import PY310_PLUS, PY312_PLUS
from astroid.exceptions import InferenceError
from astroid.manager import AstroidManager
from astroid.util import Uninferable, UninferableBase
Expand Down Expand Up @@ -415,3 +415,30 @@ def test_assigned_stmts_match_as():
assert match_as.name
assigned_match_as = next(match_as.name.assigned_stmts())
assert assigned_match_as == subject


@pytest.mark.skipif(not PY312_PLUS, reason="Generic typing syntax requires python 3.12")
class TestGenericTypeSyntax:
@staticmethod
def test_assigned_stmts_type_var():
"""The result is 'Uninferable' and no exception is raised."""
assign_stmts = extract_node("type Point[T] = tuple[float, float]")
type_var: nodes.TypeVar = assign_stmts.type_params[0]
assigned = next(type_var.name.assigned_stmts())
assert assigned is Uninferable

@staticmethod
def test_assigned_stmts_type_var_tuple():
"""The result is 'Uninferable' and no exception is raised."""
assign_stmts = extract_node("type Alias[*Ts] = tuple[*Ts]")
type_var_tuple: nodes.TypeVarTuple = assign_stmts.type_params[0]
assigned = next(type_var_tuple.name.assigned_stmts())
assert assigned is Uninferable

@staticmethod
def test_assigned_stmts_param_spec():
"""The result is 'Uninferable' and no exception is raised."""
assign_stmts = extract_node("type Alias[**P] = Callable[P, int]")
param_spec: nodes.ParamSpec = assign_stmts.type_params[0]
assigned = next(param_spec.name.assigned_stmts())
assert assigned is Uninferable

0 comments on commit d7be465

Please sign in to comment.