Skip to content

Commit 29b9559

Browse files
committed
Builtin functions min() and max() now use Argument Clinic
1 parent 196b53e commit 29b9559

File tree

2 files changed

+193
-57
lines changed

2 files changed

+193
-57
lines changed

Python/bltinmodule.c

Lines changed: 70 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,40 +1705,29 @@ builtin_locals_impl(PyObject *module)
17051705

17061706

17071707
static PyObject *
1708-
min_max(PyObject *args, PyObject *kwds, int op)
1708+
min_max(PyObject *args, PyObject *key, PyObject *default_value, int op)
17091709
{
17101710
PyObject *v, *it, *item, *val, *maxitem, *maxval, *keyfunc=NULL;
1711-
PyObject *emptytuple, *defaultval = NULL;
1712-
static char *kwlist[] = {"key", "default", NULL};
1713-
const char *name = op == Py_LT ? "min" : "max";
1714-
const int positional = PyTuple_Size(args) > 1;
1715-
int ret;
1711+
const char *name = (op == Py_LT) ? "min" : "max";
1712+
const int nargs = PyTuple_GET_SIZE(args);
17161713

1714+
if (nargs == 0) {
1715+
PyErr_Format(PyExc_TypeError, "%s expected at least 1 argument, got 0", name);
1716+
return NULL;
1717+
}
1718+
1719+
const int positional = nargs > 1; // False iff nargs == 1
17171720
if (positional) {
17181721
v = args;
1719-
}
1720-
else if (!PyArg_UnpackTuple(args, name, 1, 1, &v)) {
1721-
if (PyExceptionClass_Check(PyExc_TypeError)) {
1722-
PyErr_Format(PyExc_TypeError, "%s expected at least 1 argument, got 0", name);
1722+
if (default_value != NULL) {
1723+
PyErr_Format(PyExc_TypeError,
1724+
"Cannot specify a default for %s() with multiple "
1725+
"positional arguments", name);
1726+
return NULL;
17231727
}
1724-
return NULL;
17251728
}
1726-
1727-
emptytuple = PyTuple_New(0);
1728-
if (emptytuple == NULL)
1729-
return NULL;
1730-
ret = PyArg_ParseTupleAndKeywords(emptytuple, kwds,
1731-
(op == Py_LT) ? "|$OO:min" : "|$OO:max",
1732-
kwlist, &keyfunc, &defaultval);
1733-
Py_DECREF(emptytuple);
1734-
if (!ret)
1735-
return NULL;
1736-
1737-
if (positional && defaultval != NULL) {
1738-
PyErr_Format(PyExc_TypeError,
1739-
"Cannot specify a default for %s() with multiple "
1740-
"positional arguments", name);
1741-
return NULL;
1729+
else {
1730+
v = PyTuple_GET_ITEM(args, 0);
17421731
}
17431732

17441733
it = PyObject_GetIter(v);
@@ -1791,9 +1780,9 @@ min_max(PyObject *args, PyObject *kwds, int op)
17911780
goto Fail_it;
17921781
if (maxval == NULL) {
17931782
assert(maxitem == NULL);
1794-
if (defaultval != NULL) {
1795-
Py_INCREF(defaultval);
1796-
maxitem = defaultval;
1783+
if (default_value != NULL) {
1784+
Py_INCREF(default_value);
1785+
maxitem = default_value;
17971786
} else {
17981787
PyErr_Format(PyExc_ValueError,
17991788
"%s() arg is an empty sequence", name);
@@ -1815,40 +1804,65 @@ min_max(PyObject *args, PyObject *kwds, int op)
18151804
return NULL;
18161805
}
18171806

1818-
/* AC: cannot convert yet, waiting for *args support */
1807+
/*[clinic input]
1808+
min as builtin_min
1809+
1810+
*args: object
1811+
key: object = NULL
1812+
one-argument function to extract a comparison key from each element.
1813+
default: object = NULL
1814+
object to return if the provided iterable is empty.
1815+
1816+
Return the smallest argument or the smallest item in iterable object.
1817+
1818+
min(iterable, *[, default=obj, key=func]) -> value
1819+
min(arg1, arg2, *args, *[, key=func]) -> value
1820+
1821+
With a single iterable argument, return its smallest item. The
1822+
default keyword-only argument specifies an object to return if
1823+
the provided iterable is empty.
1824+
With two or more arguments, return the smallest argument.
1825+
1826+
[clinic start generated code]*/
1827+
18191828
static PyObject *
1820-
builtin_min(PyObject *self, PyObject *args, PyObject *kwds)
1829+
builtin_min_impl(PyObject *module, PyObject *args, PyObject *key,
1830+
PyObject *default_value)
1831+
/*[clinic end generated code: output=f74a10b650d4d5e7 input=b081b1c2b37c5754]*/
18211832
{
1822-
return min_max(args, kwds, Py_LT);
1833+
return min_max(args, key, default_value, Py_LT);
18231834
}
18241835

1825-
PyDoc_STRVAR(min_doc,
1826-
"min(iterable, *[, default=obj, key=func]) -> value\n\
1827-
min(arg1, arg2, *args, *[, key=func]) -> value\n\
1828-
\n\
1829-
With a single iterable argument, return its smallest item. The\n\
1830-
default keyword-only argument specifies an object to return if\n\
1831-
the provided iterable is empty.\n\
1832-
With two or more arguments, return the smallest argument.");
18331836

1837+
/*[clinic input]
1838+
max as builtin_max
1839+
1840+
*args: object
1841+
key: object = NULL
1842+
one-argument function to extract a comparison key from each element.
1843+
default: object = NULL
1844+
object to return if the provided iterable is empty.
1845+
1846+
Return the smallest argument or the smallest item in iterable object.
1847+
1848+
max(iterable, *[, default=obj, key=func]) -> value
1849+
max(arg1, arg2, *args, *[, key=func]) -> value
1850+
1851+
With a single iterable argument, return its biggest item. The
1852+
default keyword-only argument specifies an object to return if
1853+
the provided iterable is empty.
1854+
With two or more arguments, return the smallest argument.
1855+
1856+
[clinic start generated code]*/
18341857

1835-
/* AC: cannot convert yet, waiting for *args support */
18361858
static PyObject *
1837-
builtin_max(PyObject *self, PyObject *args, PyObject *kwds)
1859+
builtin_max_impl(PyObject *module, PyObject *args, PyObject *key,
1860+
PyObject *default_value)
1861+
/*[clinic end generated code: output=c6d5a5acfe12dc13 input=f88fccad611bca32]*/
18381862
{
1839-
return min_max(args, kwds, Py_GT);
1863+
return min_max(args, key, default_value, Py_GT);
18401864
}
18411865

1842-
PyDoc_STRVAR(max_doc,
1843-
"max(iterable, *[, default=obj, key=func]) -> value\n\
1844-
max(arg1, arg2, *args, *[, key=func]) -> value\n\
1845-
\n\
1846-
With a single iterable argument, return its biggest item. The\n\
1847-
default keyword-only argument specifies an object to return if\n\
1848-
the provided iterable is empty.\n\
1849-
With two or more arguments, return the largest argument.");
1850-
1851-
18521866
/*[clinic input]
18531867
oct as builtin_oct
18541868
@@ -2954,8 +2968,8 @@ static PyMethodDef builtin_methods[] = {
29542968
BUILTIN_AITER_METHODDEF
29552969
BUILTIN_LEN_METHODDEF
29562970
BUILTIN_LOCALS_METHODDEF
2957-
{"max", (PyCFunction)(void(*)(void))builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc},
2958-
{"min", (PyCFunction)(void(*)(void))builtin_min, METH_VARARGS | METH_KEYWORDS, min_doc},
2971+
BUILTIN_MAX_METHODDEF
2972+
BUILTIN_MIN_METHODDEF
29592973
{"next", (PyCFunction)(void(*)(void))builtin_next, METH_FASTCALL, next_doc},
29602974
BUILTIN_ANEXT_METHODDEF
29612975
BUILTIN_OCT_METHODDEF

Python/clinic/bltinmodule.c.h

Lines changed: 123 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)