3838from astroid .util import Uninferable
3939
4040TYPING_NAMEDTUPLE_BASENAMES = {"NamedTuple" , "typing.NamedTuple" }
41- TYPING_TYPEVARS = {"TypeVar" , "NewType" }
42- TYPING_TYPEVARS_QUALIFIED = {"typing.TypeVar" , "typing.NewType" }
4341TYPING_TYPE_TEMPLATE = """
4442class Meta(type):
4543 def __getitem__(self, item):
@@ -52,6 +50,11 @@ def __args__(self):
5250class {0}(metaclass=Meta):
5351 pass
5452"""
53+ # PEP484 suggests NewType is equivalent to this for typing purposes
54+ TYPING_NEWTYPE_TEMPLATE = """
55+ class {derived}({base}):
56+ pass
57+ """
5558TYPING_MEMBERS = set (getattr (typing , "__all__" , []))
5659
5760TYPING_ALIAS = frozenset (
@@ -106,23 +109,32 @@ def __class_getitem__(cls, item):
106109"""
107110
108111
109- def looks_like_typing_typevar_or_newtype (node ):
112+ def looks_like_typing_typevar (node ):
113+ func = node .func
114+ if isinstance (func , Attribute ):
115+ return func .attrname == "TypeVar"
116+ if isinstance (func , Name ):
117+ return func .name == "TypeVar"
118+ return False
119+
120+
121+ def looks_like_typing_newtype (node ):
110122 func = node .func
111123 if isinstance (func , Attribute ):
112- return func .attrname in TYPING_TYPEVARS
124+ return func .attrname == "NewType"
113125 if isinstance (func , Name ):
114- return func .name in TYPING_TYPEVARS
126+ return func .name == "NewType"
115127 return False
116128
117129
118- def infer_typing_typevar_or_newtype (node , context_itton = None ):
130+ def infer_typing_typevar (node , context_itton = None ):
119131 """Infer a typing.TypeVar(...) or typing.NewType(...) call"""
120132 try :
121133 func = next (node .func .infer (context = context_itton ))
122134 except (InferenceError , StopIteration ) as exc :
123135 raise UseInferenceDefault from exc
124136
125- if func .qname () not in TYPING_TYPEVARS_QUALIFIED :
137+ if func .qname () != "typing.TypeVar" :
126138 raise UseInferenceDefault
127139 if not node .args :
128140 raise UseInferenceDefault
@@ -132,6 +144,24 @@ def infer_typing_typevar_or_newtype(node, context_itton=None):
132144 return node .infer (context = context_itton )
133145
134146
147+ def infer_typing_newtype (node , context_itton = None ):
148+ """Infer a typing.TypeVar(...) or typing.NewType(...) call"""
149+ try :
150+ func = next (node .func .infer (context = context_itton ))
151+ except (InferenceError , StopIteration ) as exc :
152+ raise UseInferenceDefault from exc
153+
154+ if func .qname () != "typing.NewType" :
155+ raise UseInferenceDefault
156+ if not node .args :
157+ raise UseInferenceDefault
158+
159+ derived = node .args [0 ].as_string ().strip ("'" )
160+ base = node .args [1 ].as_string ().strip ("'" )
161+ node = extract_node (TYPING_NEWTYPE_TEMPLATE .format (derived = derived , base = base ))
162+ return node .infer (context = context_itton )
163+
164+
135165def _looks_like_typing_subscript (node ):
136166 """Try to figure out if a Subscript node *might* be a typing-related subscript"""
137167 if isinstance (node , Name ):
@@ -409,8 +439,13 @@ def infer_typing_cast(
409439
410440AstroidManager ().register_transform (
411441 Call ,
412- inference_tip (infer_typing_typevar_or_newtype ),
413- looks_like_typing_typevar_or_newtype ,
442+ inference_tip (infer_typing_typevar ),
443+ looks_like_typing_typevar ,
444+ )
445+ AstroidManager ().register_transform (
446+ Call ,
447+ inference_tip (infer_typing_newtype ),
448+ looks_like_typing_newtype ,
414449)
415450AstroidManager ().register_transform (
416451 Subscript , inference_tip (infer_typing_attr ), _looks_like_typing_subscript
0 commit comments