You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Argument Clinic should understand *args and **kwargs parameters #64490
Argument Clinic currently prevents the "impl" function from ever seeing the "args" tuple or the "kwargs" dict. There should be a way to ask it to pass those values in to the "impl" function.
So, let's think about this for a minute. What's the API that we *want* here?
If your function has the signature
(a, b, c=20, *args)
and you call it with
(1, 2, 3, 4, 5)
should "args" be (4, 5), or (1, 2, 3, 4, 5)?
I assert that the impl function should get the same "args" (and "kwargs") that a Python function would--that is, post-argument-processing. In the above example "args" should get (4, 5).
This might be somewhat painful to do in round 1, where we're still leveraging off PyArg_ParseTuple*. But in the future it'll be cheaper to do it this way. In any case, it's the right API, so that's what we should do.
(Adding Nick just to see if he agrees--he had a use case for *args in the builtin module.)
Yes, I agree we should follow the Python level semantics, and only capture the excess positional arguments. For the record, the four builtins I flagged as needing this in order to add introspection information:
__build_class__
2 positional only args, arbitrary additional args
checks size with PyTuple_GET_SIZE
uses PyTuple_GET_ITEM x2 + PyTuple_GetSlice to unpack
print
only arbitrary position args, iterates and extracts using PyTuple_GetItem
uses PyArg_ParseTupleAndKeywords with an empty tuple to extract the keyword-only args
min
max
use a shared helper function min_max
uses the args tuple directly if size > 1
otherwise uses PyArg_UnpackTuple to extract the supplied iterable
uses PyArg_ParseTupleAndKeywords with an empty tuple to extract the keyword-only args
this "one arg means iterable" style API might need to be a special case...
I think at first step we can support var-positional parameter only when there are no other positional parameters, and var-keyword parameter only when there are no other keyword parameters. So print, max and dict.update will be supported, but __build_class__, map and functools.partial are not.
bisect.bisect_right(a, x[, lo[, hi]]) -> index
where the absence of *hi* implies hi=len(a)
min(iterable, *[, default=obj, key=func]) -> value
min(arg1, arg2, *args, *[, key=func]) -> value
has two signatures depending on the number of
positional arguments and a keyword argument
only used in the first signature. It's implementation
is also shared with max().
dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
d = {}
for k, v in iterable:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
defsumseq(seq, a=0, b=None):
# Pure python code with nullable intifbisNone:
b=len(seq)
returnsum(seq[a:b])
FYI I started to work on a different Argument Clinic enhancement, issue bpo-29299: "Argument Clinic: Fix signature of optional positional-only arguments".
I've had a stab at **kwds support, see #138344. It is an intentionally restricted implementation, only supporting METH_VARARGS|METH_KEYWORDS and strictly positional-ponly parameters. However, I think it's a useful start, and allows converting several functions to AC already, which affords us the other benefits of using AC for those functions.
Activity
larryhastings commentedon Jan 18, 2014
Argument Clinic currently prevents the "impl" function from ever seeing the "args" tuple or the "kwargs" dict. There should be a way to ask it to pass those values in to the "impl" function.
larryhastings commentedon Aug 19, 2014
So, let's think about this for a minute. What's the API that we *want* here?
If your function has the signature
(a, b, c=20, *args)
and you call it with
(1, 2, 3, 4, 5)
should "args" be (4, 5), or (1, 2, 3, 4, 5)?
I assert that the impl function should get the same "args" (and "kwargs") that a Python function would--that is, post-argument-processing. In the above example "args" should get (4, 5).
This might be somewhat painful to do in round 1, where we're still leveraging off PyArg_ParseTuple*. But in the future it'll be cheaper to do it this way. In any case, it's the right API, so that's what we should do.
(Adding Nick just to see if he agrees--he had a use case for *args in the builtin module.)
ncoghlan commentedon Aug 19, 2014
Yes, I agree we should follow the Python level semantics, and only capture the excess positional arguments. For the record, the four builtins I flagged as needing this in order to add introspection information:
__build_class__
print
min
max
serhiy-storchaka commentedon May 6, 2016
I think at first step we can support var-positional parameter only when there are no other positional parameters, and var-keyword parameter only when there are no other keyword parameters. So print, max and dict.update will be supported, but __build_class__, map and functools.partial are not.
serhiy-storchaka commentedon Jan 17, 2017
I'll try to implement the support of var-positional parameters.
rhettinger commentedon Jan 17, 2017
In case it is helpful, here's my list of examples where the AC and existing signature objects are insufficiently expressive:
bisect.bisect_right(a, x[, lo[, hi]]) -> index
where the absence of *hi* implies hi=len(a)
min(iterable, *[, default=obj, key=func]) -> value
min(arg1, arg2, *args, *[, key=func]) -> value
has two signatures depending on the number of
positional arguments and a keyword argument
only used in the first signature. It's implementation
is also shared with max().
dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
d = {}
for k, v in iterable:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
vstinner commentedon Jan 17, 2017
FYI I started to work on a different Argument Clinic enhancement, issue bpo-29299: "Argument Clinic: Fix signature of optional positional-only arguments".
4 remaining items
gh-64490: Fix refcount error when arguments are packed to tuple in ar…
gh-64490: Fix bugs in argument clinic varargs processing (#32092)
[3.11] pythongh-64490: Fix refcount error when arguments are packed t…
[3.11] gh-64490: Fix refcount error when arguments are packed to tupl…
[3.11] pythongh-64490: Fix bugs in argument clinic varargs processing (…
[3.11] gh-64490: Fix bugs in argument clinic varargs processing (GH-3…
gpshead commentedon Feb 7, 2023
#18609 appears to have added
*argssupport, but it wasn't documented.gpshead commentedon Feb 7, 2023
(unassigning since it isn't actively being worked on) @isidentical as FYI for the missing documentation.
skirpichev commentedon Aug 12, 2025
See python/devguide#1629
AA-Turner commentedon Sep 1, 2025
I've had a stab at
**kwdssupport, see #138344. It is an intentionally restricted implementation, only supportingMETH_VARARGS|METH_KEYWORDSand strictly positional-ponly parameters. However, I think it's a useful start, and allows converting several functions to AC already, which affords us the other benefits of using AC for those functions.A
gh-64490: Argument Clinic: Add support for ``**kwds`` (#138344)
serhiy-storchaka commentedon Aug 22, 2026
There was a bug:
gh-64490: Tweak AC implementation for **kwds (GH-139133)