70
70
AsyncTaskIncompleteValue ,
71
71
BoundsMap ,
72
72
CallableValue ,
73
+ CallValue ,
73
74
CanAssign ,
74
75
CanAssignContext ,
75
76
CanAssignError ,
@@ -411,7 +412,10 @@ def allow_unpack(self) -> bool:
411
412
ParameterKind .VAR_POSITIONAL ,
412
413
ParameterKind .KEYWORD_ONLY ,
413
414
},
414
- ParameterKind .PARAM_SPEC : {ParameterKind .POSITIONAL_ONLY },
415
+ ParameterKind .PARAM_SPEC : {
416
+ ParameterKind .POSITIONAL_ONLY ,
417
+ ParameterKind .POSITIONAL_OR_KEYWORD ,
418
+ },
415
419
ParameterKind .ELLIPSIS : {ParameterKind .POSITIONAL_ONLY },
416
420
}
417
421
CAN_HAVE_DEFAULT = {
@@ -1079,8 +1083,28 @@ def bind_arguments(
1079
1083
)
1080
1084
bound_args [param .name ] = KWARGS , composite
1081
1085
else :
1082
- self .show_call_error ("Callable requires a ParamSpec argument" , ctx )
1083
- return None
1086
+ new_actuals = ActualArguments (
1087
+ positionals = actual_args .positionals [positional_index :],
1088
+ star_args = (
1089
+ actual_args .star_args if not star_args_consumed else None
1090
+ ),
1091
+ keywords = {
1092
+ key : value
1093
+ for key , value in actual_args .keywords .items ()
1094
+ if key not in keywords_consumed
1095
+ },
1096
+ star_kwargs = (
1097
+ actual_args .star_kwargs
1098
+ if not star_kwargs_consumed
1099
+ else None
1100
+ ),
1101
+ kwargs_required = actual_args .kwargs_required ,
1102
+ pos_or_keyword_params = actual_args .pos_or_keyword_params ,
1103
+ )
1104
+ star_args_consumed = True
1105
+ star_kwargs_consumed = True
1106
+ val = CallValue (new_actuals )
1107
+ bound_args [param .name ] = UNKNOWN , Composite (val )
1084
1108
else :
1085
1109
assert False , f"unhandled param { param .kind } "
1086
1110
@@ -1973,14 +1997,27 @@ def preprocess_args(
1973
1997
# Step 1: Split up args and kwargs if possible.
1974
1998
processed_args : List [Argument ] = []
1975
1999
kwargs_requireds = []
2000
+ param_spec = None
2001
+ param_spec_star_arg = None
2002
+ seen_param_spec_kwargs = False
1976
2003
for arg , label in args :
1977
2004
if label is ARGS :
2005
+ if isinstance (arg .value , ParamSpecArgsValue ):
2006
+ if param_spec is not None :
2007
+ ctx .on_error (
2008
+ "Only a single ParamSpec.args can be passed" , node = arg .node
2009
+ )
2010
+ param_spec = TypeVarValue (arg .value .param_spec )
2011
+ param_spec_star_arg = arg
2012
+ continue
1978
2013
concrete_values = concrete_values_from_iterable (
1979
2014
arg .value , ctx .can_assign_ctx
1980
2015
)
1981
2016
if isinstance (concrete_values , CanAssignError ):
1982
2017
ctx .on_error (
1983
- f"{ arg .value } is not iterable" , detail = str (concrete_values )
2018
+ f"{ arg .value } is not iterable" ,
2019
+ detail = str (concrete_values ),
2020
+ node = arg .node ,
1984
2021
)
1985
2022
return None
1986
2023
elif isinstance (concrete_values , Value ):
@@ -1995,6 +2032,23 @@ def preprocess_args(
1995
2032
for subval in concrete_values :
1996
2033
processed_args .append ((Composite (subval ), None ))
1997
2034
elif label is KWARGS :
2035
+ if isinstance (arg .value , ParamSpecKwargsValue ):
2036
+ if param_spec is None :
2037
+ ctx .on_error (
2038
+ "ParamSpec.kwargs cannot be passed without ParamSpec.args" ,
2039
+ node = arg .node ,
2040
+ )
2041
+ elif param_spec .typevar is not arg .value .param_spec :
2042
+ ctx .on_error (
2043
+ "ParamSpec.args and ParamSpec.kwargs must use the same ParamSpec" ,
2044
+ node = arg .node ,
2045
+ )
2046
+ elif seen_param_spec_kwargs :
2047
+ ctx .on_error (
2048
+ "Only a single ParamSpec.kwargs can be passed" , node = arg .node
2049
+ )
2050
+ seen_param_spec_kwargs = True
2051
+ continue
1998
2052
items = {}
1999
2053
extra_values = []
2000
2054
if arg .value is NO_RETURN_VALUE :
@@ -2036,6 +2090,11 @@ def preprocess_args(
2036
2090
processed_args .append ((new_composite , KWARGS ))
2037
2091
else :
2038
2092
processed_args .append ((arg , label ))
2093
+ if param_spec_star_arg is not None and not seen_param_spec_kwargs :
2094
+ ctx .on_error (
2095
+ "ParamSpec.args cannot be passed without ParamSpec.kwargs" ,
2096
+ node = param_spec_star_arg .node ,
2097
+ )
2039
2098
2040
2099
# Step 2: enforce invariants about ARGS and KWARGS placement. We dump
2041
2100
# any single arguments that come after *args into *args, and we merge all *args.
@@ -2097,6 +2156,9 @@ def preprocess_args(
2097
2156
more_processed_kwargs [label .name ] = (label .is_required , arg )
2098
2157
more_processed_args .append ((label .is_required , arg ))
2099
2158
elif isinstance (label , TypeVarValue ):
2159
+ if param_spec is not None :
2160
+ ctx .on_error ("Multiple ParamSpecs passed" )
2161
+ continue
2100
2162
param_spec = label
2101
2163
elif label is ELLIPSIS :
2102
2164
is_ellipsis = True
@@ -2276,7 +2338,6 @@ def check_call(
2276
2338
actual_args = preprocess_args (args , ctx )
2277
2339
if actual_args is None :
2278
2340
return AnyValue (AnySource .error )
2279
-
2280
2341
# We first bind the arguments for each overload, to get the obvious errors
2281
2342
# out of the way first.
2282
2343
errors_per_overload = []
@@ -2703,6 +2764,21 @@ def decompose_union(
2703
2764
return None
2704
2765
2705
2766
2767
+ def check_call_preprocessed (
2768
+ sig : ConcreteSignature , args : ActualArguments , ctx : CanAssignContext
2769
+ ) -> CanAssign :
2770
+ if isinstance (sig , Signature ):
2771
+ check_ctx = _CanAssignBasedContext (ctx )
2772
+ sig .check_call_preprocessed (args , check_ctx )
2773
+ if check_ctx .errors :
2774
+ return CanAssignError (
2775
+ "Incompatible callable" , [CanAssignError (e ) for e in check_ctx .errors ]
2776
+ )
2777
+ return {}
2778
+ else :
2779
+ return CanAssignError ("Overloads are not supported" )
2780
+
2781
+
2706
2782
def _extract_known_value (val : Value ) -> Optional [KnownValue ]:
2707
2783
if isinstance (val , AnnotatedValue ):
2708
2784
val = val .value
0 commit comments