From 9d54dd9faf9fb8f7bb592b4dc24c387084027a2c Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Wed, 21 Jun 2023 21:38:43 -0400 Subject: [PATCH] Python 3.12 adjustments for typing brain A C-accelerator was introduced for the typing module in Python 3.12 (see https://github.com/python/cpython/pull/103764). Because a pure python source is no longer available, now we stub out the missing classes and provide some __class_getitem__ methods to allow subscripting like Type[int]. This may mean when 3.12 is the minimum, we can remove older brain features like infer_typing_alias(). --- astroid/brain/brain_typing.py | 37 ++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/astroid/brain/brain_typing.py b/astroid/brain/brain_typing.py index 924f0ac0f9..2ed37e8c0f 100644 --- a/astroid/brain/brain_typing.py +++ b/astroid/brain/brain_typing.py @@ -6,14 +6,16 @@ from __future__ import annotations +import textwrap import typing from collections.abc import Iterator from functools import partial from typing import Final from astroid import context, extract_node, inference_tip -from astroid.builder import _extract_single_node -from astroid.const import PY39_PLUS +from astroid.builder import _extract_single_node, AstroidBuilder +from astroid.brain.helpers import register_module_extender +from astroid.const import PY39_PLUS, PY312_PLUS from astroid.exceptions import ( AttributeInferenceError, InferenceError, @@ -231,7 +233,8 @@ def _looks_like_typing_alias(node: Call) -> bool: """ return ( isinstance(node.func, Name) - and node.func.name == "_alias" + # TODO: remove _DeprecatedGenericAlias when Py3.14 min + and node.func.name in ("_alias", "_DeprecatedGenericAlias") and ( # _alias function works also for builtins object such as list and dict isinstance(node.args[0], (Attribute, Name)) @@ -273,6 +276,8 @@ def infer_typing_alias( :param node: call node :param context: inference context + + # TODO: evaluate if still necessary when Py3.12 is minimum """ if ( not isinstance(node.parent, Assign) @@ -415,6 +420,29 @@ def infer_typing_cast( return node.args[1].infer(context=ctx) +def _typing_transform(): + return AstroidBuilder(AstroidManager()).string_build( + textwrap.dedent( + """ + class Generic: + @classmethod + def __class_getitem__(cls, item): return cls + class ParamSpec: ... + class ParamSpecArgs: ... + class ParamSpecKwargs: ... + class TypeAlias: ... + class Type: + @classmethod + def __class_getitem__(cls, item): return cls + class TypeVar: + @classmethod + def __class_getitem__(cls, item): return cls + class TypeVarTuple: ... + """ + ) + ) + + AstroidManager().register_transform( Call, inference_tip(infer_typing_typevar_or_newtype), @@ -442,3 +470,6 @@ def infer_typing_cast( AstroidManager().register_transform( Call, inference_tip(infer_special_alias), _looks_like_special_alias ) + +if PY312_PLUS: + register_module_extender(AstroidManager(), "typing", _typing_transform)