@@ -310,12 +310,16 @@ def parse_metaclass(self) -> str:
310
310
311
311
def parse_decorated_function_or_class (self ) -> Node :
312
312
decorators = [] # type: List[Node]
313
+ no_type_checks = False
313
314
while self .current_str () == '@' :
314
315
self .expect ('@' )
315
- decorators .append (self .parse_expression ())
316
+ d_exp = self .parse_expression ()
317
+ if self .is_no_type_check_decorator (d_exp ):
318
+ no_type_checks = True
319
+ decorators .append (d_exp )
316
320
self .expect_break ()
317
321
if self .current_str () != 'class' :
318
- func = self .parse_function ()
322
+ func = self .parse_function (no_type_checks )
319
323
func .is_decorated = True
320
324
var = Var (func .name ())
321
325
# Types of decorated functions must always be inferred.
@@ -328,13 +332,22 @@ def parse_decorated_function_or_class(self) -> Node:
328
332
cls .decorators = decorators
329
333
return cls
330
334
331
- def parse_function (self ) -> FuncDef :
335
+ def is_no_type_check_decorator (self , expr : Node ) -> bool :
336
+ if isinstance (expr , NameExpr ):
337
+ return expr .name == 'no_type_check'
338
+ elif isinstance (expr , MemberExpr ):
339
+ if isinstance (expr .expr , NameExpr ):
340
+ return expr .expr .name == 'typing' and expr .name == 'no_type_check'
341
+ else :
342
+ return False
343
+
344
+ def parse_function (self , no_type_checks : bool = False ) -> FuncDef :
332
345
def_tok = self .expect ('def' )
333
346
is_method = self .is_class_body
334
347
self .is_class_body = False
335
348
try :
336
349
(name , args , init , kinds ,
337
- typ , is_error ) = self .parse_function_header ()
350
+ typ , is_error ) = self .parse_function_header (no_type_checks )
338
351
339
352
body , comment_type = self .parse_block (allow_type = True )
340
353
if comment_type :
@@ -394,8 +407,8 @@ def check_argument_kinds(self, funckinds: List[int], sigkinds: List[int],
394
407
"Inconsistent use of '{}' in function "
395
408
"signature" .format (token ), line )
396
409
397
- def parse_function_header (self ) -> Tuple [str , List [Var ], List [Node ],
398
- List [int ], CallableType , bool ]:
410
+ def parse_function_header (self , no_type_checks : bool = False ) -> Tuple [str , List [Var ], List [Node ],
411
+ List [int ], CallableType , bool ]:
399
412
"""Parse function header (a name followed by arguments)
400
413
401
414
Returns a 7-tuple with the following items:
@@ -415,7 +428,7 @@ def parse_function_header(self) -> Tuple[str, List[Var], List[Node],
415
428
416
429
self .errors .push_function (name )
417
430
418
- (args , init , kinds , typ ) = self .parse_args ()
431
+ (args , init , kinds , typ ) = self .parse_args (no_type_checks )
419
432
except ParseError :
420
433
if not isinstance (self .current (), Break ):
421
434
self .ind -= 1 # Kludge: go back to the Break token
@@ -426,21 +439,25 @@ def parse_function_header(self) -> Tuple[str, List[Var], List[Node],
426
439
427
440
return (name , args , init , kinds , typ , False )
428
441
429
- def parse_args (self ) -> Tuple [List [Var ], List [Node ], List [int ], CallableType ]:
442
+ def parse_args (self , no_type_checks : bool = False ) -> Tuple [List [Var ], List [Node ], List [int ], CallableType ]:
430
443
"""Parse a function signature (...) [-> t]."""
431
444
lparen = self .expect ('(' )
432
445
433
446
# Parse the argument list (everything within '(' and ')').
434
447
(args , init , kinds ,
435
448
has_inits , arg_names ,
436
449
commas , asterisk ,
437
- assigns , arg_types ) = self .parse_arg_list ()
450
+ assigns , arg_types ) = self .parse_arg_list (no_type_checks = no_type_checks )
438
451
439
452
self .expect (')' )
440
453
441
454
if self .current_str () == '->' :
442
455
self .skip ()
443
- ret_type = self .parse_type ()
456
+ if no_type_checks :
457
+ self .parse_expression ()
458
+ ret_type = None # type: Type
459
+ else :
460
+ ret_type = self .parse_type ()
444
461
else :
445
462
ret_type = None
446
463
@@ -466,7 +483,7 @@ def build_func_annotation(self, ret_type: Type, arg_types: List[Type],
466
483
return None
467
484
468
485
def parse_arg_list (
469
- self , allow_signature : bool = True ) -> Tuple [List [Var ], List [Node ],
486
+ self , allow_signature : bool = True , no_type_checks : bool = False ) -> Tuple [List [Var ], List [Node ],
470
487
List [int ], bool ,
471
488
List [Token ], List [Token ],
472
489
List [Token ], List [Token ],
@@ -517,13 +534,23 @@ def parse_arg_list(
517
534
kinds .append (nodes .ARG_STAR2 )
518
535
else :
519
536
kinds .append (nodes .ARG_STAR )
520
- arg_types .append (self .parse_arg_type (allow_signature ))
537
+
538
+ if no_type_checks :
539
+ self .parse_parameter_annotation ()
540
+ arg_types .append (None )
541
+ else :
542
+ arg_types .append (self .parse_arg_type (allow_signature ))
521
543
require_named = True
522
544
else :
523
545
name = self .expect_type (Name )
524
546
arg_names .append (name )
525
547
args .append (Var (name .string ))
526
- arg_types .append (self .parse_arg_type (allow_signature ))
548
+
549
+ if no_type_checks :
550
+ self .parse_parameter_annotation ()
551
+ arg_types .append (None )
552
+ else :
553
+ arg_types .append (self .parse_arg_type (allow_signature ))
527
554
528
555
if self .current_str () == '=' :
529
556
assigns .append (self .expect ('=' ))
@@ -549,6 +576,11 @@ def parse_arg_list(
549
576
return (args , init , kinds , has_inits , arg_names , commas , asterisk ,
550
577
assigns , arg_types )
551
578
579
+ def parse_parameter_annotation (self ) -> Node :
580
+ if self .current_str () == ':' :
581
+ self .skip ()
582
+ return self .parse_expression (precedence [',' ])
583
+
552
584
def parse_arg_type (self , allow_signature : bool ) -> Type :
553
585
if self .current_str () == ':' and allow_signature :
554
586
self .skip ()
0 commit comments