@@ -147,28 +147,6 @@ def __repr__(self):
147
147
_marker = _Sentinel ()
148
148
149
149
150
- def _check_generic (cls , parameters , elen = _marker ):
151
- """Check correct count for parameters of a generic cls (internal helper).
152
- This gives a nice error message in case of count mismatch.
153
- """
154
- if not elen :
155
- raise TypeError (f"{ cls } is not a generic class" )
156
- if elen is _marker :
157
- if not hasattr (cls , "__parameters__" ) or not cls .__parameters__ :
158
- raise TypeError (f"{ cls } is not a generic class" )
159
- elen = len (cls .__parameters__ )
160
- alen = len (parameters )
161
- if alen != elen :
162
- if hasattr (cls , "__parameters__" ):
163
- parameters = [p for p in cls .__parameters__ if not _is_unpack (p )]
164
- num_tv_tuples = sum (isinstance (p , TypeVarTuple ) for p in parameters )
165
- if (num_tv_tuples > 0 ) and (alen >= elen - num_tv_tuples ):
166
- return
167
- things = "arguments" if sys .version_info >= (3 , 10 ) else "parameters"
168
- raise TypeError (f"Too { 'many' if alen > elen else 'few' } { things } for { cls } ;"
169
- f" actual { alen } , expected { elen } " )
170
-
171
-
172
150
if sys .version_info >= (3 , 10 ):
173
151
def _should_collect_from_parameters (t ):
174
152
return isinstance (
@@ -182,27 +160,6 @@ def _should_collect_from_parameters(t):
182
160
return isinstance (t , typing ._GenericAlias ) and not t ._special
183
161
184
162
185
- def _collect_type_vars (types , typevar_types = None ):
186
- """Collect all type variable contained in types in order of
187
- first appearance (lexicographic order). For example::
188
-
189
- _collect_type_vars((T, List[S, T])) == (T, S)
190
- """
191
- if typevar_types is None :
192
- typevar_types = typing .TypeVar
193
- tvars = []
194
- for t in types :
195
- if (
196
- isinstance (t , typevar_types ) and
197
- t not in tvars and
198
- not _is_unpack (t )
199
- ):
200
- tvars .append (t )
201
- if _should_collect_from_parameters (t ):
202
- tvars .extend ([t for t in t .__parameters__ if t not in tvars ])
203
- return tuple (tvars )
204
-
205
-
206
163
NoReturn = typing .NoReturn
207
164
208
165
# Some unconstrained type variables. These are used by the container types.
@@ -2690,9 +2647,151 @@ def wrapper(*args, **kwargs):
2690
2647
# counting generic parameters, so that when we subscript a generic,
2691
2648
# the runtime doesn't try to substitute the Unpack with the subscripted type.
2692
2649
if not hasattr (typing , "TypeVarTuple" ):
2650
+ def _check_generic (cls , parameters , elen = _marker ):
2651
+ """Check correct count for parameters of a generic cls (internal helper).
2652
+
2653
+ This gives a nice error message in case of count mismatch.
2654
+ """
2655
+ if not elen :
2656
+ raise TypeError (f"{ cls } is not a generic class" )
2657
+ if elen is _marker :
2658
+ if not hasattr (cls , "__parameters__" ) or not cls .__parameters__ :
2659
+ raise TypeError (f"{ cls } is not a generic class" )
2660
+ elen = len (cls .__parameters__ )
2661
+ alen = len (parameters )
2662
+ if alen != elen :
2663
+ expect_val = elen
2664
+ if hasattr (cls , "__parameters__" ):
2665
+ parameters = [p for p in cls .__parameters__ if not _is_unpack (p )]
2666
+ num_tv_tuples = sum (isinstance (p , TypeVarTuple ) for p in parameters )
2667
+ if (num_tv_tuples > 0 ) and (alen >= elen - num_tv_tuples ):
2668
+ return
2669
+
2670
+ # deal with TypeVarLike defaults
2671
+ # required TypeVarLikes cannot appear after a defaulted one.
2672
+ if alen < elen :
2673
+ # since we validate TypeVarLike default in _collect_type_vars
2674
+ # or _collect_parameters we can safely check parameters[alen]
2675
+ if getattr (parameters [alen ], '__default__' , None ) is not None :
2676
+ return
2677
+
2678
+ num_default_tv = sum (getattr (p , '__default__' , None )
2679
+ is not None for p in parameters )
2680
+
2681
+ elen -= num_default_tv
2682
+
2683
+ expect_val = f"at least { elen } "
2684
+
2685
+ things = "arguments" if sys .version_info >= (3 , 10 ) else "parameters"
2686
+ raise TypeError (f"Too { 'many' if alen > elen else 'few' } { things } "
2687
+ f" for { cls } ; actual { alen } , expected { expect_val } " )
2688
+ else :
2689
+ # Python 3.11+
2690
+
2691
+ def _check_generic (cls , parameters , elen ):
2692
+ """Check correct count for parameters of a generic cls (internal helper).
2693
+
2694
+ This gives a nice error message in case of count mismatch.
2695
+ """
2696
+ if not elen :
2697
+ raise TypeError (f"{ cls } is not a generic class" )
2698
+ alen = len (parameters )
2699
+ if alen != elen :
2700
+ expect_val = elen
2701
+ if hasattr (cls , "__parameters__" ):
2702
+ parameters = [p for p in cls .__parameters__ if not _is_unpack (p )]
2703
+
2704
+ # deal with TypeVarLike defaults
2705
+ # required TypeVarLikes cannot appear after a defaulted one.
2706
+ if alen < elen :
2707
+ # since we validate TypeVarLike default in _collect_type_vars
2708
+ # or _collect_parameters we can safely check parameters[alen]
2709
+ if getattr (parameters [alen ], '__default__' , None ) is not None :
2710
+ return
2711
+
2712
+ num_default_tv = sum (getattr (p , '__default__' , None )
2713
+ is not None for p in parameters )
2714
+
2715
+ elen -= num_default_tv
2716
+
2717
+ expect_val = f"at least { elen } "
2718
+
2719
+ raise TypeError (f"Too { 'many' if alen > elen else 'few' } arguments"
2720
+ f" for { cls } ; actual { alen } , expected { expect_val } " )
2721
+
2722
+ typing ._check_generic = _check_generic
2723
+
2724
+ # Python 3.11+ _collect_type_vars was renamed to _collect_parameters
2725
+ if hasattr (typing , '_collect_type_vars' ):
2726
+ def _collect_type_vars (types , typevar_types = None ):
2727
+ """Collect all type variable contained in types in order of
2728
+ first appearance (lexicographic order). For example::
2729
+
2730
+ _collect_type_vars((T, List[S, T])) == (T, S)
2731
+ """
2732
+ if typevar_types is None :
2733
+ typevar_types = typing .TypeVar
2734
+ tvars = []
2735
+ # required TypeVarLike cannot appear after TypeVarLike with default
2736
+ default_encountered = False
2737
+ for t in types :
2738
+ if (
2739
+ isinstance (t , typevar_types ) and
2740
+ t not in tvars and
2741
+ not _is_unpack (t )
2742
+ ):
2743
+ if getattr (t , '__default__' , None ) is not None :
2744
+ default_encountered = True
2745
+ elif default_encountered :
2746
+ raise TypeError (f'Type parameter { t !r} without a default'
2747
+ ' follows type parameter with a default' )
2748
+
2749
+ tvars .append (t )
2750
+ if _should_collect_from_parameters (t ):
2751
+ tvars .extend ([t for t in t .__parameters__ if t not in tvars ])
2752
+ return tuple (tvars )
2753
+
2693
2754
typing ._collect_type_vars = _collect_type_vars
2694
- typing ._check_generic = _check_generic
2755
+ else :
2756
+ def _collect_parameters (args ):
2757
+ """Collect all type variables and parameter specifications in args
2758
+ in order of first appearance (lexicographic order).
2759
+
2760
+ For example::
2761
+
2762
+ assert _collect_parameters((T, Callable[P, T])) == (T, P)
2763
+ """
2764
+ parameters = []
2765
+ # required TypeVarLike cannot appear after TypeVarLike with default
2766
+ default_encountered = False
2767
+ for t in args :
2768
+ if isinstance (t , type ):
2769
+ # We don't want __parameters__ descriptor of a bare Python class.
2770
+ pass
2771
+ elif isinstance (t , tuple ):
2772
+ # `t` might be a tuple, when `ParamSpec` is substituted with
2773
+ # `[T, int]`, or `[int, *Ts]`, etc.
2774
+ for x in t :
2775
+ for collected in _collect_parameters ([x ]):
2776
+ if collected not in parameters :
2777
+ parameters .append (collected )
2778
+ elif hasattr (t , '__typing_subst__' ):
2779
+ if t not in parameters :
2780
+ if getattr (t , '__default__' , None ) is not None :
2781
+ default_encountered = True
2782
+ elif default_encountered :
2783
+ raise TypeError (f'Type parameter { t !r} without a default'
2784
+ ' follows type parameter with a default' )
2785
+
2786
+ parameters .append (t )
2787
+ else :
2788
+ for x in getattr (t , '__parameters__' , ()):
2789
+ if x not in parameters :
2790
+ parameters .append (x )
2791
+
2792
+ return tuple (parameters )
2695
2793
2794
+ typing ._collect_parameters = _collect_parameters
2696
2795
2697
2796
# Backport typing.NamedTuple as it exists in Python 3.13.
2698
2797
# In 3.11, the ability to define generic `NamedTuple`s was supported.
0 commit comments