39
39
from mypy .options import Options
40
40
41
41
try :
42
- from typed_ast import ast3
43
- from typed_ast .ast3 import (
44
- AST ,
45
- Call ,
46
- FunctionType ,
47
- Name ,
48
- Attribute ,
49
- Ellipsis as ast3_Ellipsis ,
50
- Starred ,
51
- NameConstant ,
52
- Expression as ast3_Expression ,
53
- Str ,
54
- Bytes ,
55
- Index ,
56
- Num ,
57
- UnaryOp ,
58
- USub ,
59
- )
42
+ # Check if we can use the stdlib ast module instead of typed_ast.
43
+ if sys .version_info >= (3 , 8 ):
44
+ import ast as ast3
45
+ assert 'kind' in ast3 .Constant ._fields , \
46
+ "This 3.8.0 alpha (%s) is too old; 3.8.0a3 required" % sys .version .split ()[0 ]
47
+ from ast import (
48
+ AST ,
49
+ Call ,
50
+ FunctionType ,
51
+ Name ,
52
+ Attribute ,
53
+ Ellipsis as ast3_Ellipsis ,
54
+ Starred ,
55
+ NameConstant ,
56
+ Expression as ast3_Expression ,
57
+ Str ,
58
+ Bytes ,
59
+ Index ,
60
+ Num ,
61
+ UnaryOp ,
62
+ USub ,
63
+ )
64
+
65
+ def ast3_parse (source : Union [str , bytes ], filename : str , mode : str ,
66
+ feature_version : int = sys .version_info [1 ]) -> AST :
67
+ return ast3 .parse (source , filename , mode ,
68
+ type_comments = True , # This works the magic
69
+ feature_version = feature_version )
70
+
71
+ NamedExpr = ast3 .NamedExpr
72
+ Constant = ast3 .Constant
73
+ else :
74
+ from typed_ast import ast3
75
+ from typed_ast .ast3 import (
76
+ AST ,
77
+ Call ,
78
+ FunctionType ,
79
+ Name ,
80
+ Attribute ,
81
+ Ellipsis as ast3_Ellipsis ,
82
+ Starred ,
83
+ NameConstant ,
84
+ Expression as ast3_Expression ,
85
+ Str ,
86
+ Bytes ,
87
+ Index ,
88
+ Num ,
89
+ UnaryOp ,
90
+ USub ,
91
+ )
92
+
93
+ def ast3_parse (source : Union [str , bytes ], filename : str , mode : str ,
94
+ feature_version : int = sys .version_info [1 ]) -> AST :
95
+ return ast3 .parse (source , filename , mode , feature_version = feature_version )
96
+
97
+ # These don't exist before 3.8
98
+ NamedExpr = Any
99
+ Constant = Any
60
100
except ImportError :
61
101
if sys .version_info .minor > 2 :
62
102
try :
@@ -122,7 +162,7 @@ def parse(source: Union[str, bytes],
122
162
else :
123
163
assert options .python_version [0 ] >= 3
124
164
feature_version = options .python_version [1 ]
125
- ast = ast3 . parse (source , fnam , 'exec' , feature_version = feature_version )
165
+ ast = ast3_parse (source , fnam , 'exec' , feature_version = feature_version )
126
166
127
167
tree = ASTConverter (options = options ,
128
168
is_stub = is_stub_file ,
@@ -146,7 +186,7 @@ def parse_type_comment(type_comment: str,
146
186
assume_str_is_unicode : bool = True ,
147
187
) -> Optional [Type ]:
148
188
try :
149
- typ = ast3 . parse (type_comment , '<type_comment>' , 'eval' )
189
+ typ = ast3_parse (type_comment , '<type_comment>' , 'eval' )
150
190
except SyntaxError as e :
151
191
if errors is not None :
152
192
errors .report (line , e .offset , TYPE_COMMENT_SYNTAX_ERROR , blocker = True )
@@ -366,16 +406,12 @@ def visit_Module(self, mod: ast3.Module) -> MypyFile:
366
406
# arguments = (arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults,
367
407
# arg? kwarg, expr* defaults)
368
408
def visit_FunctionDef (self , n : ast3 .FunctionDef ) -> Union [FuncDef , Decorator ]:
369
- f = self .do_func_def (n )
370
- f .set_line (n .lineno , n .col_offset ) # Overrides set_line -- can't use self.set_line
371
- return f
409
+ return self .do_func_def (n )
372
410
373
411
# AsyncFunctionDef(identifier name, arguments args,
374
412
# stmt* body, expr* decorator_list, expr? returns, string? type_comment)
375
413
def visit_AsyncFunctionDef (self , n : ast3 .AsyncFunctionDef ) -> Union [FuncDef , Decorator ]:
376
- f = self .do_func_def (n , is_coroutine = True )
377
- f .set_line (n .lineno , n .col_offset ) # Overrides set_line -- can't use self.set_line
378
- return f
414
+ return self .do_func_def (n , is_coroutine = True )
379
415
380
416
def do_func_def (self , n : Union [ast3 .FunctionDef , ast3 .AsyncFunctionDef ],
381
417
is_coroutine : bool = False ) -> Union [FuncDef , Decorator ]:
@@ -397,7 +433,7 @@ def do_func_def(self, n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef],
397
433
return_type = None
398
434
elif n .type_comment is not None :
399
435
try :
400
- func_type_ast = ast3 . parse (n .type_comment , '<func_type>' , 'func_type' )
436
+ func_type_ast = ast3_parse (n .type_comment , '<func_type>' , 'func_type' )
401
437
assert isinstance (func_type_ast , FunctionType )
402
438
# for ellipsis arg
403
439
if (len (func_type_ast .argtypes ) == 1 and
@@ -470,15 +506,25 @@ def do_func_def(self, n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef],
470
506
func_type .line = lineno
471
507
472
508
if n .decorator_list :
509
+ if sys .version_info < (3 , 8 ):
510
+ # Before 3.8, [typed_]ast the line number points to the first decorator.
511
+ # In 3.8, it points to the 'def' line, where we want it.
512
+ lineno += len (n .decorator_list )
513
+
473
514
var = Var (func_def .name ())
474
515
var .is_ready = False
475
- var .set_line (n . decorator_list [ 0 ]. lineno )
516
+ var .set_line (lineno )
476
517
477
518
func_def .is_decorated = True
478
- func_def .set_line (lineno + len (n .decorator_list ))
479
- func_def .body .set_line (func_def .get_line ())
480
- return Decorator (func_def , self .translate_expr_list (n .decorator_list ), var )
519
+ func_def .set_line (lineno , n .col_offset )
520
+ func_def .body .set_line (lineno ) # TODO: Why?
521
+
522
+ deco = Decorator (func_def , self .translate_expr_list (n .decorator_list ), var )
523
+ deco .set_line (n .decorator_list [0 ].lineno )
524
+ return deco
481
525
else :
526
+ # FuncDef overrides set_line -- can't use self.set_line
527
+ func_def .set_line (lineno , n .col_offset )
482
528
return func_def
483
529
484
530
def set_type_optional (self , type : Optional [Type ], initializer : Optional [Expression ]) -> None :
@@ -568,7 +614,15 @@ def visit_ClassDef(self, n: ast3.ClassDef) -> ClassDef:
568
614
metaclass = dict (keywords ).get ('metaclass' ),
569
615
keywords = keywords )
570
616
cdef .decorators = self .translate_expr_list (n .decorator_list )
571
- self .set_line (cdef , n )
617
+ if n .decorator_list and sys .version_info >= (3 , 8 ):
618
+ # Before 3.8, n.lineno points to the first decorator; in
619
+ # 3.8, it points to the 'class' statement. We always make
620
+ # it point to the first decorator. (The node structure
621
+ # here is different than for decorated functions.)
622
+ cdef .line = n .decorator_list [0 ].lineno
623
+ cdef .column = n .col_offset
624
+ else :
625
+ self .set_line (cdef , n )
572
626
self .class_nesting -= 1
573
627
return cdef
574
628
@@ -617,6 +671,10 @@ def visit_AugAssign(self, n: ast3.AugAssign) -> OperatorAssignmentStmt:
617
671
self .visit (n .value ))
618
672
return self .set_line (s , n )
619
673
674
+ def visit_NamedExpr (self , n : NamedExpr ) -> None :
675
+ self .fail ("assignment expressions are not yet supported" , n .lineno , n .col_offset )
676
+ return None
677
+
620
678
# For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
621
679
def visit_For (self , n : ast3 .For ) -> ForStmt :
622
680
if n .type_comment is not None :
@@ -926,6 +984,30 @@ def visit_Call(self, n: Call) -> CallExpr:
926
984
cast ('List[Optional[str]]' , [None ] * len (args )) + keyword_names )
927
985
return self .set_line (e , n )
928
986
987
+ # Constant(object value) -- a constant, in Python 3.8.
988
+ def visit_Constant (self , n : Constant ) -> Any :
989
+ val = n .value
990
+ e = None # type: Any
991
+ if val is None :
992
+ e = NameExpr ('None' )
993
+ elif isinstance (val , str ):
994
+ e = StrExpr (n .s )
995
+ elif isinstance (val , bytes ):
996
+ e = BytesExpr (bytes_to_human_readable_repr (n .s ))
997
+ elif isinstance (val , bool ): # Must check before int!
998
+ e = NameExpr (str (val ))
999
+ elif isinstance (val , int ):
1000
+ e = IntExpr (val )
1001
+ elif isinstance (val , float ):
1002
+ e = FloatExpr (val )
1003
+ elif isinstance (val , complex ):
1004
+ e = ComplexExpr (val )
1005
+ elif val is Ellipsis :
1006
+ e = EllipsisExpr ()
1007
+ else :
1008
+ raise RuntimeError ('Constant not implemented for ' + str (type (val )))
1009
+ return self .set_line (e , n )
1010
+
929
1011
# Num(object n) -- a number as a PyObject.
930
1012
def visit_Num (self , n : ast3 .Num ) -> Union [IntExpr , FloatExpr , ComplexExpr ]:
931
1013
# The n field has the type complex, but complex isn't *really*
@@ -994,7 +1076,8 @@ def visit_Bytes(self, n: ast3.Bytes) -> Union[BytesExpr, StrExpr]:
994
1076
995
1077
# NameConstant(singleton value)
996
1078
def visit_NameConstant (self , n : NameConstant ) -> NameExpr :
997
- return NameExpr (str (n .value ))
1079
+ e = NameExpr (str (n .value ))
1080
+ return self .set_line (e , n )
998
1081
999
1082
# Ellipsis
1000
1083
def visit_Ellipsis (self , n : ast3_Ellipsis ) -> EllipsisExpr :
@@ -1094,7 +1177,7 @@ def invalid_type(self, node: AST, note: Optional[str] = None) -> RawExpressionTy
1094
1177
def visit (self , node : ast3 .expr ) -> Type : ...
1095
1178
1096
1179
@overload # noqa
1097
- def visit (self , node : Optional [AST ]) -> Optional [Type ]: ...
1180
+ def visit (self , node : Optional [AST ]) -> Optional [Type ]: ... # noqa
1098
1181
1099
1182
def visit (self , node : Optional [AST ]) -> Optional [Type ]: # noqa
1100
1183
"""Modified visit -- keep track of the stack of nodes"""
@@ -1205,6 +1288,34 @@ def visit_NameConstant(self, n: NameConstant) -> Type:
1205
1288
else :
1206
1289
return UnboundType (str (n .value ), line = self .line )
1207
1290
1291
+ # Only for 3.8 and newer
1292
+ def visit_Constant (self , n : Constant ) -> Type :
1293
+ val = n .value
1294
+ if val is None :
1295
+ # None is a type.
1296
+ return UnboundType ('None' , line = self .line )
1297
+ if isinstance (val , str ):
1298
+ # Parse forward reference.
1299
+ if (n .kind and 'u' in n .kind ) or self .assume_str_is_unicode :
1300
+ return parse_type_string (n .s , 'builtins.unicode' , self .line , n .col_offset ,
1301
+ assume_str_is_unicode = self .assume_str_is_unicode )
1302
+ else :
1303
+ return parse_type_string (n .s , 'builtins.str' , self .line , n .col_offset ,
1304
+ assume_str_is_unicode = self .assume_str_is_unicode )
1305
+ if val is Ellipsis :
1306
+ # '...' is valid in some types.
1307
+ return EllipsisType (line = self .line )
1308
+ if isinstance (val , bool ):
1309
+ # Special case for True/False.
1310
+ return RawExpressionType (val , 'builtins.bool' , line = self .line )
1311
+ if isinstance (val , (int , float , complex )):
1312
+ return self .numeric_type (val , n )
1313
+ if isinstance (val , bytes ):
1314
+ contents = bytes_to_human_readable_repr (val )
1315
+ return RawExpressionType (contents , 'builtins.bytes' , self .line , column = n .col_offset )
1316
+ # Everything else is invalid.
1317
+ return self .invalid_type (n )
1318
+
1208
1319
# UnaryOp(op, operand)
1209
1320
def visit_UnaryOp (self , n : UnaryOp ) -> Type :
1210
1321
# We support specifically Literal[-4] and nothing else.
@@ -1216,13 +1327,11 @@ def visit_UnaryOp(self, n: UnaryOp) -> Type:
1216
1327
return typ
1217
1328
return self .invalid_type (n )
1218
1329
1219
- # Num(number n)
1220
- def visit_Num (self , n : Num ) -> Type :
1221
- # The n field has the type complex, but complex isn't *really*
1330
+ def numeric_type (self , value : object , n : AST ) -> Type :
1331
+ # The node's field has the type complex, but complex isn't *really*
1222
1332
# a parent of int and float, and this causes isinstance below
1223
1333
# to think that the complex branch is always picked. Avoid
1224
1334
# this by throwing away the type.
1225
- value = n .n # type: object
1226
1335
if isinstance (value , int ):
1227
1336
numeric_value = value # type: Optional[int]
1228
1337
type_name = 'builtins.int'
@@ -1239,24 +1348,31 @@ def visit_Num(self, n: Num) -> Type:
1239
1348
column = getattr (n , 'col_offset' , - 1 ),
1240
1349
)
1241
1350
1242
- # Str(string s)
1243
- def visit_Str (self , n : Str ) -> Type :
1244
- # Note: we transform these fallback types into the correct types in
1245
- # 'typeanal.py' -- specifically in the named_type_with_normalized_str method.
1246
- # If we're analyzing Python 3, that function will translate 'builtins.unicode'
1247
- # into 'builtins.str'. In contrast, if we're analyzing Python 2 code, we'll
1248
- # translate 'builtins.bytes' in the method below into 'builtins.str'.
1249
- if 'u' in n .kind or self .assume_str_is_unicode :
1250
- return parse_type_string (n .s , 'builtins.unicode' , self .line , n .col_offset ,
1251
- assume_str_is_unicode = self .assume_str_is_unicode )
1252
- else :
1253
- return parse_type_string (n .s , 'builtins.str' , self .line , n .col_offset ,
1254
- assume_str_is_unicode = self .assume_str_is_unicode )
1351
+ if sys .version_info < (3 , 8 ):
1352
+ # Using typed_ast
1353
+
1354
+ # Num(number n)
1355
+ def visit_Num (self , n : Num ) -> Type :
1356
+ return self .numeric_type (n .n , n )
1357
+
1358
+ # Str(string s)
1359
+ def visit_Str (self , n : Str ) -> Type :
1360
+ # Note: we transform these fallback types into the correct types in
1361
+ # 'typeanal.py' -- specifically in the named_type_with_normalized_str method.
1362
+ # If we're analyzing Python 3, that function will translate 'builtins.unicode'
1363
+ # into 'builtins.str'. In contrast, if we're analyzing Python 2 code, we'll
1364
+ # translate 'builtins.bytes' in the method below into 'builtins.str'.
1365
+ if 'u' in n .kind or self .assume_str_is_unicode :
1366
+ return parse_type_string (n .s , 'builtins.unicode' , self .line , n .col_offset ,
1367
+ assume_str_is_unicode = self .assume_str_is_unicode )
1368
+ else :
1369
+ return parse_type_string (n .s , 'builtins.str' , self .line , n .col_offset ,
1370
+ assume_str_is_unicode = self .assume_str_is_unicode )
1255
1371
1256
- # Bytes(bytes s)
1257
- def visit_Bytes (self , n : Bytes ) -> Type :
1258
- contents = bytes_to_human_readable_repr (n .s )
1259
- return RawExpressionType (contents , 'builtins.bytes' , self .line , column = n .col_offset )
1372
+ # Bytes(bytes s)
1373
+ def visit_Bytes (self , n : Bytes ) -> Type :
1374
+ contents = bytes_to_human_readable_repr (n .s )
1375
+ return RawExpressionType (contents , 'builtins.bytes' , self .line , column = n .col_offset )
1260
1376
1261
1377
# Subscript(expr value, slice slice, expr_context ctx)
1262
1378
def visit_Subscript (self , n : ast3 .Subscript ) -> Type :
0 commit comments