@@ -1232,22 +1232,95 @@ def set_template_dict(self, template_dict: TemplateDict) -> None:
1232
1232
1233
1233
# Converters for var-positional parameter.
1234
1234
1235
- class varpos_tuple_converter (CConverter ):
1235
+ class VarPosCConverter (CConverter ):
1236
+ format_unit = ''
1237
+
1238
+ def parse_arg (self , argname : str , displayname : str , * , limited_capi : bool ) -> str | None :
1239
+ raise AssertionError ('should never be called' )
1240
+
1241
+ def parse_vararg (self , * , pos_only : int , min_pos : int , max_pos : int ,
1242
+ fastcall : bool , limited_capi : bool ) -> str :
1243
+ raise NotImplementedError
1244
+
1245
+
1246
+ class varpos_tuple_converter (VarPosCConverter ):
1236
1247
type = 'PyObject *'
1237
1248
format_unit = ''
1238
1249
c_default = 'NULL'
1239
1250
1240
1251
def cleanup (self ) -> str :
1241
1252
return f"""Py_XDECREF({ self .parser_name } );\n """
1242
1253
1243
- def parse_arg (self , argname : str , displayname : str , * , limited_capi : bool ) -> str | None :
1244
- raise AssertionError ('should never be called' )
1254
+ def parse_vararg (self , * , pos_only : int , min_pos : int , max_pos : int ,
1255
+ fastcall : bool , limited_capi : bool ) -> str :
1256
+ paramname = self .parser_name
1257
+ if fastcall :
1258
+ if limited_capi :
1259
+ if min (pos_only , min_pos ) < max_pos :
1260
+ size = f'Py_MAX(nargs - { max_pos } , 0)'
1261
+ else :
1262
+ size = f'nargs - { max_pos } ' if max_pos else 'nargs'
1263
+ return f"""
1264
+ { paramname } = PyTuple_New({ size } );
1265
+ if (!{ paramname } ) {{{{
1266
+ goto exit;
1267
+ }}}}
1268
+ for (Py_ssize_t i = { max_pos } ; i < nargs; ++i) {{{{
1269
+ PyTuple_SET_ITEM({ paramname } , i - { max_pos } , Py_NewRef(args[i]));
1270
+ }}}}
1271
+ """
1272
+ else :
1273
+ self .add_include ('pycore_tuple.h' , '_PyTuple_FromArray()' )
1274
+ start = f'args + { max_pos } ' if max_pos else 'args'
1275
+ size = f'nargs - { max_pos } ' if max_pos else 'nargs'
1276
+ if min (pos_only , min_pos ) < max_pos :
1277
+ return f"""
1278
+ { paramname } = nargs > { max_pos }
1279
+ ? _PyTuple_FromArray({ start } , { size } )
1280
+ : PyTuple_New(0);
1281
+ if ({ paramname } == NULL) {{{{
1282
+ goto exit;
1283
+ }}}}
1284
+ """
1285
+ else :
1286
+ return f"""
1287
+ { paramname } = _PyTuple_FromArray({ start } , { size } );
1288
+ if ({ paramname } == NULL) {{{{
1289
+ goto exit;
1290
+ }}}}
1291
+ """
1292
+ else :
1293
+ if max_pos :
1294
+ return f"""
1295
+ { paramname } = PyTuple_GetSlice(args, { max_pos } , PY_SSIZE_T_MAX);
1296
+ if (!{ paramname } ) {{{{
1297
+ goto exit;
1298
+ }}}}
1299
+ """
1300
+ else :
1301
+ return f"{ paramname } = Py_NewRef(args);\n "
1245
1302
1246
- class varpos_array_converter (CConverter ):
1303
+
1304
+ class varpos_array_converter (VarPosCConverter ):
1247
1305
type = 'PyObject * const *'
1248
- format_unit = ''
1249
1306
length = True
1250
1307
c_ignored_default = ''
1251
1308
1252
- def parse_arg (self , argname : str , displayname : str , * , limited_capi : bool ) -> str | None :
1253
- raise AssertionError ('should never be called' )
1309
+ def parse_vararg (self , * , pos_only : int , min_pos : int , max_pos : int ,
1310
+ fastcall : bool , limited_capi : bool ) -> str :
1311
+ paramname = self .parser_name
1312
+ if not fastcall :
1313
+ self .add_include ('pycore_tuple.h' , '_PyTuple_ITEMS()' )
1314
+ start = 'args' if fastcall else '_PyTuple_ITEMS(args)'
1315
+ size = 'nargs' if fastcall else 'PyTuple_GET_SIZE(args)'
1316
+ if max_pos :
1317
+ if min (pos_only , min_pos ) < max_pos :
1318
+ start = f'{ size } > { max_pos } ? { start } + { max_pos } : { start } '
1319
+ size = f'Py_MAX(0, { size } - { max_pos } )'
1320
+ else :
1321
+ start = f'{ start } + { max_pos } '
1322
+ size = f'{ size } - { max_pos } '
1323
+ return f"""
1324
+ { paramname } = { start } ;
1325
+ { self .length_name } = { size } ;
1326
+ """
0 commit comments