@@ -150,6 +150,7 @@ def _check_methods_in_mro(C, *methods):
150
150
'overload' ,
151
151
'Text' ,
152
152
'TypeAlias' ,
153
+ 'TypeGuard' ,
153
154
'TYPE_CHECKING' ,
154
155
]
155
156
@@ -2514,3 +2515,291 @@ class Concatenate(metaclass=_ConcatenateAliasMeta, _root=True):
2514
2515
See PEP 612 for detailed information.
2515
2516
"""
2516
2517
__slots__ = ()
2518
+
2519
+ if hasattr (typing , 'TypeGuard' ):
2520
+ TypeGuard = typing .TypeGuard
2521
+ elif sys .version_info [:2 ] >= (3 , 9 ):
2522
+ class _TypeGuardForm (typing ._SpecialForm , _root = True ):
2523
+ def __repr__ (self ):
2524
+ return 'typing_extensions.' + self ._name
2525
+
2526
+ @_TypeGuardForm
2527
+ def TypeGuard (self , parameters ):
2528
+ """Special typing form used to annotate the return type of a user-defined
2529
+ type guard function. ``TypeGuard`` only accepts a single type argument.
2530
+ At runtime, functions marked this way should return a boolean.
2531
+
2532
+ ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static
2533
+ type checkers to determine a more precise type of an expression within a
2534
+ program's code flow. Usually type narrowing is done by analyzing
2535
+ conditional code flow and applying the narrowing to a block of code. The
2536
+ conditional expression here is sometimes referred to as a "type guard".
2537
+
2538
+ Sometimes it would be convenient to use a user-defined boolean function
2539
+ as a type guard. Such a function should use ``TypeGuard[...]`` as its
2540
+ return type to alert static type checkers to this intention.
2541
+
2542
+ Using ``-> TypeGuard`` tells the static type checker that for a given
2543
+ function:
2544
+
2545
+ 1. The return value is a boolean.
2546
+ 2. If the return value is ``True``, the type of its argument
2547
+ is the type inside ``TypeGuard``.
2548
+
2549
+ For example::
2550
+
2551
+ def is_str(val: Union[str, float]):
2552
+ # "isinstance" type guard
2553
+ if isinstance(val, str):
2554
+ # Type of ``val`` is narrowed to ``str``
2555
+ ...
2556
+ else:
2557
+ # Else, type of ``val`` is narrowed to ``float``.
2558
+ ...
2559
+
2560
+ Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower
2561
+ form of ``TypeA`` (it can even be a wider form) and this may lead to
2562
+ type-unsafe results. The main reason is to allow for things like
2563
+ narrowing ``List[object]`` to ``List[str]`` even though the latter is not
2564
+ a subtype of the former, since ``List`` is invariant. The responsibility of
2565
+ writing type-safe type guards is left to the user.
2566
+
2567
+ ``TypeGuard`` also works with type variables. For more information, see
2568
+ PEP 647 (User-Defined Type Guards).
2569
+ """
2570
+ item = typing ._type_check (parameters , '{} accepts only single type.' .format (self ))
2571
+ return _GenericAlias (self , (item ,))
2572
+
2573
+ elif sys .version_info [:2 ] >= (3 , 7 ):
2574
+ class _TypeGuardForm (typing ._SpecialForm , _root = True ):
2575
+
2576
+ def __repr__ (self ):
2577
+ return 'typing_extensions.' + self ._name
2578
+
2579
+ def __getitem__ (self , parameters ):
2580
+ item = typing ._type_check (parameters ,
2581
+ '{} accepts only a single type' .format (self ._name ))
2582
+ return _GenericAlias (self , (item ,))
2583
+
2584
+ TypeGuard = _TypeGuardForm (
2585
+ 'TypeGuard' ,
2586
+ doc = """Special typing form used to annotate the return type of a user-defined
2587
+ type guard function. ``TypeGuard`` only accepts a single type argument.
2588
+ At runtime, functions marked this way should return a boolean.
2589
+
2590
+ ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static
2591
+ type checkers to determine a more precise type of an expression within a
2592
+ program's code flow. Usually type narrowing is done by analyzing
2593
+ conditional code flow and applying the narrowing to a block of code. The
2594
+ conditional expression here is sometimes referred to as a "type guard".
2595
+
2596
+ Sometimes it would be convenient to use a user-defined boolean function
2597
+ as a type guard. Such a function should use ``TypeGuard[...]`` as its
2598
+ return type to alert static type checkers to this intention.
2599
+
2600
+ Using ``-> TypeGuard`` tells the static type checker that for a given
2601
+ function:
2602
+
2603
+ 1. The return value is a boolean.
2604
+ 2. If the return value is ``True``, the type of its argument
2605
+ is the type inside ``TypeGuard``.
2606
+
2607
+ For example::
2608
+
2609
+ def is_str(val: Union[str, float]):
2610
+ # "isinstance" type guard
2611
+ if isinstance(val, str):
2612
+ # Type of ``val`` is narrowed to ``str``
2613
+ ...
2614
+ else:
2615
+ # Else, type of ``val`` is narrowed to ``float``.
2616
+ ...
2617
+
2618
+ Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower
2619
+ form of ``TypeA`` (it can even be a wider form) and this may lead to
2620
+ type-unsafe results. The main reason is to allow for things like
2621
+ narrowing ``List[object]`` to ``List[str]`` even though the latter is not
2622
+ a subtype of the former, since ``List`` is invariant. The responsibility of
2623
+ writing type-safe type guards is left to the user.
2624
+
2625
+ ``TypeGuard`` also works with type variables. For more information, see
2626
+ PEP 647 (User-Defined Type Guards).
2627
+ """ )
2628
+ elif hasattr (typing , '_FinalTypingBase' ):
2629
+ class _TypeGuard (typing ._FinalTypingBase , _root = True ):
2630
+ """Special typing form used to annotate the return type of a user-defined
2631
+ type guard function. ``TypeGuard`` only accepts a single type argument.
2632
+ At runtime, functions marked this way should return a boolean.
2633
+
2634
+ ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static
2635
+ type checkers to determine a more precise type of an expression within a
2636
+ program's code flow. Usually type narrowing is done by analyzing
2637
+ conditional code flow and applying the narrowing to a block of code. The
2638
+ conditional expression here is sometimes referred to as a "type guard".
2639
+
2640
+ Sometimes it would be convenient to use a user-defined boolean function
2641
+ as a type guard. Such a function should use ``TypeGuard[...]`` as its
2642
+ return type to alert static type checkers to this intention.
2643
+
2644
+ Using ``-> TypeGuard`` tells the static type checker that for a given
2645
+ function:
2646
+
2647
+ 1. The return value is a boolean.
2648
+ 2. If the return value is ``True``, the type of its argument
2649
+ is the type inside ``TypeGuard``.
2650
+
2651
+ For example::
2652
+
2653
+ def is_str(val: Union[str, float]):
2654
+ # "isinstance" type guard
2655
+ if isinstance(val, str):
2656
+ # Type of ``val`` is narrowed to ``str``
2657
+ ...
2658
+ else:
2659
+ # Else, type of ``val`` is narrowed to ``float``.
2660
+ ...
2661
+
2662
+ Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower
2663
+ form of ``TypeA`` (it can even be a wider form) and this may lead to
2664
+ type-unsafe results. The main reason is to allow for things like
2665
+ narrowing ``List[object]`` to ``List[str]`` even though the latter is not
2666
+ a subtype of the former, since ``List`` is invariant. The responsibility of
2667
+ writing type-safe type guards is left to the user.
2668
+
2669
+ ``TypeGuard`` also works with type variables. For more information, see
2670
+ PEP 647 (User-Defined Type Guards).
2671
+ """
2672
+
2673
+ __slots__ = ('__type__' ,)
2674
+
2675
+ def __init__ (self , tp = None , ** kwds ):
2676
+ self .__type__ = tp
2677
+
2678
+ def __getitem__ (self , item ):
2679
+ cls = type (self )
2680
+ if self .__type__ is None :
2681
+ return cls (typing ._type_check (item ,
2682
+ '{} accepts only a single type.' .format (cls .__name__ [1 :])),
2683
+ _root = True )
2684
+ raise TypeError ('{} cannot be further subscripted'
2685
+ .format (cls .__name__ [1 :]))
2686
+
2687
+ def _eval_type (self , globalns , localns ):
2688
+ new_tp = typing ._eval_type (self .__type__ , globalns , localns )
2689
+ if new_tp == self .__type__ :
2690
+ return self
2691
+ return type (self )(new_tp , _root = True )
2692
+
2693
+ def __repr__ (self ):
2694
+ r = super ().__repr__ ()
2695
+ if self .__type__ is not None :
2696
+ r += '[{}]' .format (typing ._type_repr (self .__type__ ))
2697
+ return r
2698
+
2699
+ def __hash__ (self ):
2700
+ return hash ((type (self ).__name__ , self .__type__ ))
2701
+
2702
+ def __eq__ (self , other ):
2703
+ if not isinstance (other , _TypeGuard ):
2704
+ return NotImplemented
2705
+ if self .__type__ is not None :
2706
+ return self .__type__ == other .__type__
2707
+ return self is other
2708
+
2709
+ TypeGuard = _TypeGuard (_root = True )
2710
+ else :
2711
+ class _TypeGuardMeta (typing .TypingMeta ):
2712
+ """Metaclass for TypeGuard"""
2713
+
2714
+ def __new__ (cls , name , bases , namespace , tp = None , _root = False ):
2715
+ self = super ().__new__ (cls , name , bases , namespace , _root = _root )
2716
+ if tp is not None :
2717
+ self .__type__ = tp
2718
+ return self
2719
+
2720
+ def __instancecheck__ (self , obj ):
2721
+ raise TypeError ("TypeGuard cannot be used with isinstance()." )
2722
+
2723
+ def __subclasscheck__ (self , cls ):
2724
+ raise TypeError ("TypeGuard cannot be used with issubclass()." )
2725
+
2726
+ def __getitem__ (self , item ):
2727
+ cls = type (self )
2728
+ if self .__type__ is not None :
2729
+ raise TypeError ('{} cannot be further subscripted'
2730
+ .format (cls .__name__ [1 :]))
2731
+
2732
+ param = typing ._type_check (
2733
+ item ,
2734
+ '{} accepts only single type.' .format (cls .__name__ [1 :]))
2735
+ return cls (self .__name__ , self .__bases__ ,
2736
+ dict (self .__dict__ ), tp = param , _root = True )
2737
+
2738
+ def _eval_type (self , globalns , localns ):
2739
+ new_tp = typing ._eval_type (self .__type__ , globalns , localns )
2740
+ if new_tp == self .__type__ :
2741
+ return self
2742
+ return type (self )(self .__name__ , self .__bases__ ,
2743
+ dict (self .__dict__ ), tp = self .__type__ ,
2744
+ _root = True )
2745
+
2746
+ def __repr__ (self ):
2747
+ r = super ().__repr__ ()
2748
+ if self .__type__ is not None :
2749
+ r += '[{}]' .format (typing ._type_repr (self .__type__ ))
2750
+ return r
2751
+
2752
+ def __hash__ (self ):
2753
+ return hash ((type (self ).__name__ , self .__type__ ))
2754
+
2755
+ def __eq__ (self , other ):
2756
+ if not hasattr (other , "__type__" ):
2757
+ return NotImplemented
2758
+ if self .__type__ is not None :
2759
+ return self .__type__ == other .__type__
2760
+ return self is other
2761
+
2762
+ class TypeGuard (typing .Final , metaclass = _TypeGuardMeta , _root = True ):
2763
+ """Special typing form used to annotate the return type of a user-defined
2764
+ type guard function. ``TypeGuard`` only accepts a single type argument.
2765
+ At runtime, functions marked this way should return a boolean.
2766
+
2767
+ ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static
2768
+ type checkers to determine a more precise type of an expression within a
2769
+ program's code flow. Usually type narrowing is done by analyzing
2770
+ conditional code flow and applying the narrowing to a block of code. The
2771
+ conditional expression here is sometimes referred to as a "type guard".
2772
+
2773
+ Sometimes it would be convenient to use a user-defined boolean function
2774
+ as a type guard. Such a function should use ``TypeGuard[...]`` as its
2775
+ return type to alert static type checkers to this intention.
2776
+
2777
+ Using ``-> TypeGuard`` tells the static type checker that for a given
2778
+ function:
2779
+
2780
+ 1. The return value is a boolean.
2781
+ 2. If the return value is ``True``, the type of its argument
2782
+ is the type inside ``TypeGuard``.
2783
+
2784
+ For example::
2785
+
2786
+ def is_str(val: Union[str, float]):
2787
+ # "isinstance" type guard
2788
+ if isinstance(val, str):
2789
+ # Type of ``val`` is narrowed to ``str``
2790
+ ...
2791
+ else:
2792
+ # Else, type of ``val`` is narrowed to ``float``.
2793
+ ...
2794
+
2795
+ Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower
2796
+ form of ``TypeA`` (it can even be a wider form) and this may lead to
2797
+ type-unsafe results. The main reason is to allow for things like
2798
+ narrowing ``List[object]`` to ``List[str]`` even though the latter is not
2799
+ a subtype of the former, since ``List`` is invariant. The responsibility of
2800
+ writing type-safe type guards is left to the user.
2801
+
2802
+ ``TypeGuard`` also works with type variables. For more information, see
2803
+ PEP 647 (User-Defined Type Guards).
2804
+ """
2805
+ __type__ = None
0 commit comments