@@ -150,6 +150,7 @@ def _check_methods_in_mro(C, *methods):
150150 'overload' ,
151151 'Text' ,
152152 'TypeAlias' ,
153+ 'TypeGuard' ,
153154 'TYPE_CHECKING' ,
154155]
155156
@@ -2514,3 +2515,291 @@ class Concatenate(metaclass=_ConcatenateAliasMeta, _root=True):
25142515 See PEP 612 for detailed information.
25152516 """
25162517 __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