@@ -2857,6 +2857,18 @@ def _check_generic(cls, parameters, elen):
28572857 typing ._check_generic = _check_generic
28582858
28592859
2860+ def _has_generic_or_protocol_as_origin () -> bool :
2861+ try :
2862+ frame = sys ._getframe (2 )
2863+ # not all platforms have sys._getframe()
2864+ except AttributeError :
2865+ return False # err on the side of leniency
2866+ else :
2867+ return frame .f_locals .get ("origin" ) in {
2868+ typing .Generic , Protocol , typing .Protocol
2869+ }
2870+
2871+
28602872_TYPEVARTUPLE_TYPES = {TypeVarTuple , getattr (typing , "TypeVarTuple" , None )}
28612873
28622874
@@ -2882,23 +2894,29 @@ def _collect_type_vars(types, typevar_types=None):
28822894 if typevar_types is None :
28832895 typevar_types = typing .TypeVar
28842896 tvars = []
2885- # required TypeVarLike cannot appear after TypeVarLike with default
2897+
2898+ # A required TypeVarLike cannot appear after a TypeVarLike with a default
2899+ # if it was a direct call to `Generic[]` or `Protocol[]`
2900+ enforce_default_ordering = _has_generic_or_protocol_as_origin ()
28862901 default_encountered = False
2887- # or after TypeVarTuple
2902+
2903+ # Also, a TypeVarLike with a default cannot appear after a TypeVarTuple
28882904 type_var_tuple_encountered = False
2905+
28892906 for t in types :
28902907 if _is_unpacked_typevartuple (t ):
28912908 type_var_tuple_encountered = True
28922909 elif isinstance (t , typevar_types ) and t not in tvars :
2893- has_default = getattr (t , '__default__' , NoDefault ) is not NoDefault
2894- if has_default :
2895- if type_var_tuple_encountered :
2896- raise TypeError ('Type parameter with a default'
2897- ' follows TypeVarTuple' )
2898- default_encountered = True
2899- elif default_encountered :
2900- raise TypeError (f'Type parameter { t !r} without a default'
2901- ' follows type parameter with a default' )
2910+ if enforce_default_ordering :
2911+ has_default = getattr (t , '__default__' , NoDefault ) is not NoDefault
2912+ if has_default :
2913+ if type_var_tuple_encountered :
2914+ raise TypeError ('Type parameter with a default'
2915+ ' follows TypeVarTuple' )
2916+ default_encountered = True
2917+ elif default_encountered :
2918+ raise TypeError (f'Type parameter { t !r} without a default'
2919+ ' follows type parameter with a default' )
29022920
29032921 tvars .append (t )
29042922 if _should_collect_from_parameters (t ):
@@ -2916,10 +2934,15 @@ def _collect_parameters(args):
29162934 assert _collect_parameters((T, Callable[P, T])) == (T, P)
29172935 """
29182936 parameters = []
2919- # required TypeVarLike cannot appear after TypeVarLike with default
2937+
2938+ # A required TypeVarLike cannot appear after a TypeVarLike with default
2939+ # if it was a direct call to `Generic[]` or `Protocol[]`
2940+ enforce_default_ordering = _has_generic_or_protocol_as_origin ()
29202941 default_encountered = False
2921- # or after TypeVarTuple
2942+
2943+ # Also, a TypeVarLike with a default cannot appear after a TypeVarTuple
29222944 type_var_tuple_encountered = False
2945+
29232946 for t in args :
29242947 if isinstance (t , type ):
29252948 # We don't want __parameters__ descriptor of a bare Python class.
@@ -2933,17 +2956,20 @@ def _collect_parameters(args):
29332956 parameters .append (collected )
29342957 elif hasattr (t , '__typing_subst__' ):
29352958 if t not in parameters :
2936- has_default = getattr (t , '__default__' , NoDefault ) is not NoDefault
2959+ if enforce_default_ordering :
2960+ has_default = (
2961+ getattr (t , '__default__' , NoDefault ) is not NoDefault
2962+ )
29372963
2938- if type_var_tuple_encountered and has_default :
2939- raise TypeError ('Type parameter with a default'
2940- ' follows TypeVarTuple' )
2964+ if type_var_tuple_encountered and has_default :
2965+ raise TypeError ('Type parameter with a default'
2966+ ' follows TypeVarTuple' )
29412967
2942- if has_default :
2943- default_encountered = True
2944- elif default_encountered :
2945- raise TypeError (f'Type parameter { t !r} without a default'
2946- ' follows type parameter with a default' )
2968+ if has_default :
2969+ default_encountered = True
2970+ elif default_encountered :
2971+ raise TypeError (f'Type parameter { t !r} without a default'
2972+ ' follows type parameter with a default' )
29472973
29482974 parameters .append (t )
29492975 else :
0 commit comments