blob: 021aa9a28506d0e08a54e64ebab4335a06df9a37 [file]
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE
# Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
import pytest
from astroid import extract_node
from astroid.const import PY312_PLUS, PY313_PLUS
from astroid.nodes import (
AssignName,
List,
Name,
ParamSpec,
Subscript,
Tuple,
TypeAlias,
TypeVar,
TypeVarTuple,
)
if not PY312_PLUS:
pytest.skip("Requires Python 3.12 or higher", allow_module_level=True)
def test_type_alias() -> None:
node = extract_node("type Point[T] = list[float, float]")
assert isinstance(node, TypeAlias)
assert isinstance(node.type_params[0], TypeVar)
assert isinstance(node.type_params[0].name, AssignName)
assert node.type_params[0].name.name == "T"
assert node.type_params[0].bound is None
assert node.type_params[0].default_value is None
assert isinstance(node.value, Subscript)
assert node.value.value.name == "list"
assert node.value.slice.name == "tuple"
assert all(elt.name == "float" for elt in node.value.slice.elts)
assert node.inferred()[0] is node
assert node.type_params[0].inferred()[0] is node.type_params[0]
assert node.statement() is node
assigned = next(node.assigned_stmts())
assert assigned is node.value
def test_type_var() -> None:
node = extract_node("type Point[T: int] = T")
param = node.type_params[0]
assert isinstance(param, TypeVar)
assert isinstance(param.bound, Name)
assert param.bound.name == "int"
assert param.default_value is None
@pytest.mark.skipif(not PY313_PLUS, reason="Type parameter defaults were added in 313")
def test_type_var_defaults() -> None:
node = extract_node("type Point[T: int = int] = T")
param = node.type_params[0]
assert isinstance(param, TypeVar)
assert isinstance(param.bound, Name)
assert param.bound.name == "int"
assert isinstance(param.default_value, Name)
assert param.default_value.name == "int"
def test_type_param_spec() -> None:
node = extract_node("type Alias[**P] = Callable[P, int]")
params = node.type_params[0]
assert isinstance(params, ParamSpec)
assert isinstance(params.name, AssignName)
assert params.name.name == "P"
assert params.default_value is None
assert node.inferred()[0] is node
@pytest.mark.skipif(not PY313_PLUS, reason="Type parameter defaults were added in 313")
def test_type_param_spec_defaults() -> None:
node = extract_node("type Alias[**P = [int, str]] = Callable[P, int]")
params = node.type_params[0]
assert isinstance(params, ParamSpec)
assert isinstance(params.name, AssignName)
assert params.name.name == "P"
assert isinstance(params.default_value, List)
assert len(params.default_value.elts) == 2
assert node.inferred()[0] is node
def test_type_var_tuple() -> None:
node = extract_node("type Alias[*Ts] = tuple[*Ts]")
params = node.type_params[0]
assert isinstance(params, TypeVarTuple)
assert isinstance(params.name, AssignName)
assert params.name.name == "Ts"
assert params.default_value is None
assert node.inferred()[0] is node
@pytest.mark.skipif(not PY313_PLUS, reason="Type parameter defaults were added in 313")
def test_type_var_tuple_defaults() -> None:
node = extract_node("type Alias[*Ts = tuple[int, str]] = tuple[*Ts]")
params = node.type_params[0]
assert isinstance(params, TypeVarTuple)
assert isinstance(params.name, AssignName)
assert params.name.name == "Ts"
assert isinstance(params.default_value, Subscript)
assert isinstance(params.default_value.value, Name)
assert params.default_value.value.name == "tuple"
assert isinstance(params.default_value.slice, Tuple)
assert len(params.default_value.slice.elts) == 2
assert node.inferred()[0] is node
def test_type_param() -> None:
func_node = extract_node("def func[T]() -> T: ...")
assert isinstance(func_node.type_params[0], TypeVar)
assert func_node.type_params[0].name.name == "T"
assert func_node.type_params[0].bound is None
class_node = extract_node("class MyClass[T]: ...")
assert isinstance(class_node.type_params[0], TypeVar)
assert class_node.type_params[0].name.name == "T"
assert class_node.type_params[0].bound is None
def test_get_children() -> None:
func_node = extract_node("def func[T]() -> T: ...")
func_children = tuple(func_node.get_children())
assert isinstance(func_children[2], TypeVar)
class_node = extract_node("class MyClass[T]: ...")
class_children = tuple(class_node.get_children())
assert isinstance(class_children[0], TypeVar)