@@ -1232,22 +1232,95 @@ def set_template_dict(self, template_dict: TemplateDict) -> None:
12321232
12331233# Converters for var-positional parameter.
12341234
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 ):
12361247 type = 'PyObject *'
12371248 format_unit = ''
12381249 c_default = 'NULL'
12391250
12401251 def cleanup (self ) -> str :
12411252 return f"""Py_XDECREF({ self .parser_name } );\n """
12421253
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 "
12451302
1246- class varpos_array_converter (CConverter ):
1303+
1304+ class varpos_array_converter (VarPosCConverter ):
12471305 type = 'PyObject * const *'
1248- format_unit = ''
12491306 length = True
12501307 c_ignored_default = ''
12511308
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