Skip to content

Commit ba4c130

Browse files
Fix issues with typing_extensions.TypeVar (#1973) (#1974)
Co-authored-by: Daniël van Noord <[email protected]> Co-authored-by: Pierre Sassoulas <[email protected]> (cherry picked from commit 0c9ab0f) Co-authored-by: Marc Mueller <[email protected]>
1 parent aed900b commit ba4c130

File tree

5 files changed

+58
-5
lines changed

5 files changed

+58
-5
lines changed

ChangeLog

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ What's New in astroid 2.13.4?
1212
=============================
1313
Release date: TBA
1414

15+
* Fix issues with ``typing_extensions.TypeVar``.
16+
1517

1618

1719
What's New in astroid 2.13.3?

astroid/brain/brain_namedtuple_enum.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,15 @@
4040
"enum.IntFlag",
4141
}
4242
ENUM_QNAME: Final[str] = "enum.Enum"
43-
TYPING_NAMEDTUPLE_BASENAMES: Final[set[str]] = {"NamedTuple", "typing.NamedTuple"}
43+
TYPING_NAMEDTUPLE_QUALIFIED: Final = {
44+
"typing.NamedTuple",
45+
"typing_extensions.NamedTuple",
46+
}
47+
TYPING_NAMEDTUPLE_BASENAMES: Final = {
48+
"NamedTuple",
49+
"typing.NamedTuple",
50+
"typing_extensions.NamedTuple",
51+
}
4452

4553

4654
def _infer_first(node, context):
@@ -542,7 +550,7 @@ def infer_typing_namedtuple(
542550
except (InferenceError, StopIteration) as exc:
543551
raise UseInferenceDefault from exc
544552

545-
if func.qname() != "typing.NamedTuple":
553+
if func.qname() not in TYPING_NAMEDTUPLE_QUALIFIED:
546554
raise UseInferenceDefault
547555

548556
if len(node.args) != 2:

astroid/brain/brain_typing.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from __future__ import annotations
88

9+
import sys
910
import typing
1011
from collections.abc import Iterator
1112
from functools import partial
@@ -34,9 +35,18 @@
3435
from astroid.nodes.scoped_nodes import ClassDef, FunctionDef
3536
from astroid.util import Uninferable
3637

37-
TYPING_NAMEDTUPLE_BASENAMES = {"NamedTuple", "typing.NamedTuple"}
38+
if sys.version_info >= (3, 8):
39+
from typing import Final
40+
else:
41+
from typing_extensions import Final
42+
3843
TYPING_TYPEVARS = {"TypeVar", "NewType"}
39-
TYPING_TYPEVARS_QUALIFIED = {"typing.TypeVar", "typing.NewType"}
44+
TYPING_TYPEVARS_QUALIFIED: Final = {
45+
"typing.TypeVar",
46+
"typing.NewType",
47+
"typing_extensions.TypeVar",
48+
}
49+
TYPING_TYPEDDICT_QUALIFIED: Final = {"typing.TypedDict", "typing_extensions.TypedDict"}
4050
TYPING_TYPE_TEMPLATE = """
4151
class Meta(type):
4252
def __getitem__(self, item):
@@ -186,7 +196,7 @@ def _looks_like_typedDict( # pylint: disable=invalid-name
186196
node: FunctionDef | ClassDef,
187197
) -> bool:
188198
"""Check if node is TypedDict FunctionDef."""
189-
return node.qname() in {"typing.TypedDict", "typing_extensions.TypedDict"}
199+
return node.qname() in TYPING_TYPEDDICT_QUALIFIED
190200

191201

192202
def infer_old_typedDict( # pylint: disable=invalid-name

requirements_test_brain.txt

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ types-python-dateutil
99
six
1010
types-six
1111
urllib3
12+
typing_extensions>=4.4.0

tests/unittest_brain.py

+32
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@
6666
except ImportError:
6767
HAS_SIX = False
6868

69+
try:
70+
import typing_extensions # pylint: disable=unused-import
71+
72+
HAS_TYPING_EXTENSIONS = True
73+
HAS_TYPING_EXTENSIONS_TYPEVAR = hasattr(typing_extensions, "TypeVar")
74+
except ImportError:
75+
HAS_TYPING_EXTENSIONS = False
76+
HAS_TYPING_EXTENSIONS_TYPEVAR = False
77+
6978

7079
def assertEqualMro(klass: ClassDef, expected_mro: list[str]) -> None:
7180
"""Check mro names."""
@@ -2148,6 +2157,29 @@ class A:
21482157
assert inferred.value == 42
21492158

21502159

2160+
@pytest.mark.skipif(
2161+
not HAS_TYPING_EXTENSIONS,
2162+
reason="These tests require the typing_extensions library",
2163+
)
2164+
class TestTypingExtensions:
2165+
@staticmethod
2166+
@pytest.mark.skipif(
2167+
not HAS_TYPING_EXTENSIONS_TYPEVAR,
2168+
reason="Need typing_extensions>=4.4.0 to test TypeVar",
2169+
)
2170+
def test_typing_extensions_types() -> None:
2171+
ast_nodes = builder.extract_node(
2172+
"""
2173+
from typing_extensions import TypeVar
2174+
TypeVar('MyTypeVar', int, float, complex) #@
2175+
TypeVar('AnyStr', str, bytes) #@
2176+
"""
2177+
)
2178+
for node in ast_nodes:
2179+
inferred = next(node.infer())
2180+
assert isinstance(inferred, nodes.ClassDef)
2181+
2182+
21512183
class ReBrainTest(unittest.TestCase):
21522184
def test_regex_flags(self) -> None:
21532185
names = [name for name in dir(re) if name.isupper()]

0 commit comments

Comments
 (0)