summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikita Sobolev <mail@sobolevn.me>2022-12-24 14:45:47 (GMT)
committerGitHub <noreply@github.com>2022-12-24 14:45:47 (GMT)
commitbdfb6943861431a79e63f0da2e6b3fe163c12bc7 (patch)
tree18ea678c9448cfe0fa193ccaf594b87abab98606
parent0769f957514300a75be51fc6d1b963c8e359208b (diff)
downloadcpython-bdfb6943861431a79e63f0da2e6b3fe163c12bc7.zip
cpython-bdfb6943861431a79e63f0da2e6b3fe163c12bc7.tar.gz
cpython-bdfb6943861431a79e63f0da2e6b3fe163c12bc7.tar.bz2
gh-100357: Convert several functions in `bltinsmodule` to AC (#100358)
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2022-12-20-09-56-56.gh-issue-100357.hPyTwY.rst2
-rw-r--r--Python/bltinmodule.c206
-rw-r--r--Python/clinic/bltinmodule.c.h196
3 files changed, 305 insertions, 99 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-12-20-09-56-56.gh-issue-100357.hPyTwY.rst b/Misc/NEWS.d/next/Core and Builtins/2022-12-20-09-56-56.gh-issue-100357.hPyTwY.rst
new file mode 100644
index 0000000..fb25de6
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-12-20-09-56-56.gh-issue-100357.hPyTwY.rst
@@ -0,0 +1,2 @@
+Convert ``vars``, ``dir``, ``next``, ``getattr``, and ``iter`` to argument
+clinic.
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 2d4822e..9ebe4c8 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -837,31 +837,33 @@ finally:
return result;
}
-/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
+/*[clinic input]
+dir as builtin_dir
+
+ arg: object = NULL
+ /
+
+Show attributes of an object.
+
+If called without an argument, return the names in the current scope.
+Else, return an alphabetized list of names comprising (some of) the attributes
+of the given object, and of attributes reachable from it.
+If the object supplies a method named __dir__, it will be used; otherwise
+the default dir() logic is used and returns:
+ for a module object: the module's attributes.
+ for a class object: its attributes, and recursively the attributes
+ of its bases.
+ for any other object: its attributes, its class's attributes, and
+ recursively the attributes of its class's base classes.
+[clinic start generated code]*/
+
static PyObject *
-builtin_dir(PyObject *self, PyObject *args)
+builtin_dir_impl(PyObject *module, PyObject *arg)
+/*[clinic end generated code: output=24f2c7a52c1e3b08 input=ed6d6ccb13d52251]*/
{
- PyObject *arg = NULL;
-
- if (!PyArg_UnpackTuple(args, "dir", 0, 1, &arg))
- return NULL;
return PyObject_Dir(arg);
}
-PyDoc_STRVAR(dir_doc,
-"dir([object]) -> list of strings\n"
-"\n"
-"If called without an argument, return the names in the current scope.\n"
-"Else, return an alphabetized list of names comprising (some of) the attributes\n"
-"of the given object, and of attributes reachable from it.\n"
-"If the object supplies a method named __dir__, it will be used; otherwise\n"
-"the default dir() logic is used and returns:\n"
-" for a module object: the module's attributes.\n"
-" for a class object: its attributes, and recursively the attributes\n"
-" of its bases.\n"
-" for any other object: its attributes, its class's attributes, and\n"
-" recursively the attributes of its class's base classes.");
-
/*[clinic input]
divmod as builtin_divmod
@@ -1109,36 +1111,39 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
}
-/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
+/*[clinic input]
+getattr as builtin_getattr
+
+ object: object
+ name: object
+ default: object = NULL
+ /
+
+Get a named attribute from an object.
+
+getattr(x, 'y') is equivalent to x.y
+When a default argument is given, it is returned when the attribute doesn't
+exist; without it, an exception is raised in that case.
+[clinic start generated code]*/
+
static PyObject *
-builtin_getattr(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+builtin_getattr_impl(PyObject *module, PyObject *object, PyObject *name,
+ PyObject *default_value)
+/*[clinic end generated code: output=74ad0e225e3f701c input=d7562cd4c3556171]*/
{
- PyObject *v, *name, *result;
-
- if (!_PyArg_CheckPositional("getattr", nargs, 2, 3))
- return NULL;
+ PyObject *result;
- v = args[0];
- name = args[1];
- if (nargs > 2) {
- if (_PyObject_LookupAttr(v, name, &result) == 0) {
- PyObject *dflt = args[2];
- return Py_NewRef(dflt);
+ if (default_value != NULL) {
+ if (_PyObject_LookupAttr(object, name, &result) == 0) {
+ return Py_NewRef(default_value);
}
}
else {
- result = PyObject_GetAttr(v, name);
+ result = PyObject_GetAttr(object, name);
}
return result;
}
-PyDoc_STRVAR(getattr_doc,
-"getattr(object, name[, default]) -> value\n\
-\n\
-Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.\n\
-When a default argument is given, it is returned when the attribute doesn't\n\
-exist; without it, an exception is raised in that case.");
-
/*[clinic input]
globals as builtin_globals
@@ -1450,34 +1455,43 @@ PyTypeObject PyMap_Type = {
};
-/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
+/*[clinic input]
+next as builtin_next
+
+ iterator: object
+ default: object = NULL
+ /
+
+Return the next item from the iterator.
+
+If default is given and the iterator is exhausted,
+it is returned instead of raising StopIteration.
+[clinic start generated code]*/
+
static PyObject *
-builtin_next(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+builtin_next_impl(PyObject *module, PyObject *iterator,
+ PyObject *default_value)
+/*[clinic end generated code: output=a38a94eeb447fef9 input=180f9984f182020f]*/
{
- PyObject *it, *res;
-
- if (!_PyArg_CheckPositional("next", nargs, 1, 2))
- return NULL;
+ PyObject *res;
- it = args[0];
- if (!PyIter_Check(it)) {
+ if (!PyIter_Check(iterator)) {
PyErr_Format(PyExc_TypeError,
"'%.200s' object is not an iterator",
- Py_TYPE(it)->tp_name);
+ Py_TYPE(iterator)->tp_name);
return NULL;
}
- res = (*Py_TYPE(it)->tp_iternext)(it);
+ res = (*Py_TYPE(iterator)->tp_iternext)(iterator);
if (res != NULL) {
return res;
- } else if (nargs > 1) {
- PyObject *def = args[1];
+ } else if (default_value != NULL) {
if (PyErr_Occurred()) {
if(!PyErr_ExceptionMatches(PyExc_StopIteration))
return NULL;
PyErr_Clear();
}
- return Py_NewRef(def);
+ return Py_NewRef(default_value);
} else if (PyErr_Occurred()) {
return NULL;
} else {
@@ -1486,12 +1500,6 @@ builtin_next(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
}
}
-PyDoc_STRVAR(next_doc,
-"next(iterator[, default])\n\
-\n\
-Return the next item from the iterator. If default is given and the iterator\n\
-is exhausted, it is returned instead of raising StopIteration.");
-
/*[clinic input]
setattr as builtin_setattr
@@ -1584,34 +1592,33 @@ builtin_hex(PyObject *module, PyObject *number)
}
-/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
+/*[clinic input]
+iter as builtin_iter
+
+ object: object
+ sentinel: object = NULL
+ /
+
+Get an iterator from an object.
+
+In the first form, the argument must supply its own iterator, or be a sequence.
+In the second form, the callable is called until it returns the sentinel.
+[clinic start generated code]*/
+
static PyObject *
-builtin_iter(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+builtin_iter_impl(PyObject *module, PyObject *object, PyObject *sentinel)
+/*[clinic end generated code: output=12cf64203c195a94 input=a5d64d9d81880ba6]*/
{
- PyObject *v;
-
- if (!_PyArg_CheckPositional("iter", nargs, 1, 2))
- return NULL;
- v = args[0];
- if (nargs == 1)
- return PyObject_GetIter(v);
- if (!PyCallable_Check(v)) {
+ if (sentinel == NULL)
+ return PyObject_GetIter(object);
+ if (!PyCallable_Check(object)) {
PyErr_SetString(PyExc_TypeError,
- "iter(v, w): v must be callable");
+ "iter(object, sentinel): object must be callable");
return NULL;
}
- PyObject *sentinel = args[1];
- return PyCallIter_New(v, sentinel);
+ return PyCallIter_New(object, sentinel);
}
-PyDoc_STRVAR(iter_doc,
-"iter(iterable) -> iterator\n\
-iter(callable, sentinel) -> iterator\n\
-\n\
-Get an iterator from an object. In the first form, the argument must\n\
-supply its own iterator, or be a sequence.\n\
-In the second form, the callable is called until it returns the sentinel.");
-
/*[clinic input]
aiter as builtin_aiter
@@ -2390,20 +2397,29 @@ builtin_sorted(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject
}
-/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
+/*[clinic input]
+vars as builtin_vars
+
+ object: object = NULL
+ /
+
+Show vars.
+
+Without arguments, equivalent to locals().
+With an argument, equivalent to object.__dict__.
+[clinic start generated code]*/
+
static PyObject *
-builtin_vars(PyObject *self, PyObject *args)
+builtin_vars_impl(PyObject *module, PyObject *object)
+/*[clinic end generated code: output=840a7f64007a3e0a input=80cbdef9182c4ba3]*/
{
- PyObject *v = NULL;
PyObject *d;
- if (!PyArg_UnpackTuple(args, "vars", 0, 1, &v))
- return NULL;
- if (v == NULL) {
+ if (object == NULL) {
d = Py_XNewRef(PyEval_GetLocals());
}
else {
- if (_PyObject_LookupAttr(v, &_Py_ID(__dict__), &d) == 0) {
+ if (_PyObject_LookupAttr(object, &_Py_ID(__dict__), &d) == 0) {
PyErr_SetString(PyExc_TypeError,
"vars() argument must have __dict__ attribute");
}
@@ -2411,12 +2427,6 @@ builtin_vars(PyObject *self, PyObject *args)
return d;
}
-PyDoc_STRVAR(vars_doc,
-"vars([object]) -> dictionary\n\
-\n\
-Without arguments, equivalent to locals().\n\
-With an argument, equivalent to object.__dict__.");
-
/*[clinic input]
sum as builtin_sum
@@ -2966,12 +2976,12 @@ static PyMethodDef builtin_methods[] = {
BUILTIN_CHR_METHODDEF
BUILTIN_COMPILE_METHODDEF
BUILTIN_DELATTR_METHODDEF
- {"dir", builtin_dir, METH_VARARGS, dir_doc},
+ BUILTIN_DIR_METHODDEF
BUILTIN_DIVMOD_METHODDEF
BUILTIN_EVAL_METHODDEF
BUILTIN_EXEC_METHODDEF
BUILTIN_FORMAT_METHODDEF
- {"getattr", _PyCFunction_CAST(builtin_getattr), METH_FASTCALL, getattr_doc},
+ BUILTIN_GETATTR_METHODDEF
BUILTIN_GLOBALS_METHODDEF
BUILTIN_HASATTR_METHODDEF
BUILTIN_HASH_METHODDEF
@@ -2980,13 +2990,13 @@ static PyMethodDef builtin_methods[] = {
BUILTIN_INPUT_METHODDEF
BUILTIN_ISINSTANCE_METHODDEF
BUILTIN_ISSUBCLASS_METHODDEF
- {"iter", _PyCFunction_CAST(builtin_iter), METH_FASTCALL, iter_doc},
+ BUILTIN_ITER_METHODDEF
BUILTIN_AITER_METHODDEF
BUILTIN_LEN_METHODDEF
BUILTIN_LOCALS_METHODDEF
{"max", _PyCFunction_CAST(builtin_max), METH_VARARGS | METH_KEYWORDS, max_doc},
{"min", _PyCFunction_CAST(builtin_min), METH_VARARGS | METH_KEYWORDS, min_doc},
- {"next", _PyCFunction_CAST(builtin_next), METH_FASTCALL, next_doc},
+ BUILTIN_NEXT_METHODDEF
BUILTIN_ANEXT_METHODDEF
BUILTIN_OCT_METHODDEF
BUILTIN_ORD_METHODDEF
@@ -2997,7 +3007,7 @@ static PyMethodDef builtin_methods[] = {
BUILTIN_SETATTR_METHODDEF
BUILTIN_SORTED_METHODDEF
BUILTIN_SUM_METHODDEF
- {"vars", builtin_vars, METH_VARARGS, vars_doc},
+ BUILTIN_VARS_METHODDEF
{NULL, NULL},
};
diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h
index 89f069d..baf9555 100644
--- a/Python/clinic/bltinmodule.c.h
+++ b/Python/clinic/bltinmodule.c.h
@@ -386,6 +386,49 @@ exit:
return return_value;
}
+PyDoc_STRVAR(builtin_dir__doc__,
+"dir($module, arg=<unrepresentable>, /)\n"
+"--\n"
+"\n"
+"Show attributes of an object.\n"
+"\n"
+"If called without an argument, return the names in the current scope.\n"
+"Else, return an alphabetized list of names comprising (some of) the attributes\n"
+"of the given object, and of attributes reachable from it.\n"
+"If the object supplies a method named __dir__, it will be used; otherwise\n"
+"the default dir() logic is used and returns:\n"
+" for a module object: the module\'s attributes.\n"
+" for a class object: its attributes, and recursively the attributes\n"
+" of its bases.\n"
+" for any other object: its attributes, its class\'s attributes, and\n"
+" recursively the attributes of its class\'s base classes.");
+
+#define BUILTIN_DIR_METHODDEF \
+ {"dir", _PyCFunction_CAST(builtin_dir), METH_FASTCALL, builtin_dir__doc__},
+
+static PyObject *
+builtin_dir_impl(PyObject *module, PyObject *arg);
+
+static PyObject *
+builtin_dir(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *arg = NULL;
+
+ if (!_PyArg_CheckPositional("dir", nargs, 0, 1)) {
+ goto exit;
+ }
+ if (nargs < 1) {
+ goto skip_optional;
+ }
+ arg = args[0];
+skip_optional:
+ return_value = builtin_dir_impl(module, arg);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(builtin_divmod__doc__,
"divmod($module, x, y, /)\n"
"--\n"
@@ -546,6 +589,47 @@ exit:
return return_value;
}
+PyDoc_STRVAR(builtin_getattr__doc__,
+"getattr($module, object, name, default=<unrepresentable>, /)\n"
+"--\n"
+"\n"
+"Get a named attribute from an object.\n"
+"\n"
+"getattr(x, \'y\') is equivalent to x.y\n"
+"When a default argument is given, it is returned when the attribute doesn\'t\n"
+"exist; without it, an exception is raised in that case.");
+
+#define BUILTIN_GETATTR_METHODDEF \
+ {"getattr", _PyCFunction_CAST(builtin_getattr), METH_FASTCALL, builtin_getattr__doc__},
+
+static PyObject *
+builtin_getattr_impl(PyObject *module, PyObject *object, PyObject *name,
+ PyObject *default_value);
+
+static PyObject *
+builtin_getattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *object;
+ PyObject *name;
+ PyObject *default_value = NULL;
+
+ if (!_PyArg_CheckPositional("getattr", nargs, 2, 3)) {
+ goto exit;
+ }
+ object = args[0];
+ name = args[1];
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ default_value = args[2];
+skip_optional:
+ return_value = builtin_getattr_impl(module, object, name, default_value);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(builtin_globals__doc__,
"globals($module, /)\n"
"--\n"
@@ -611,6 +695,44 @@ PyDoc_STRVAR(builtin_id__doc__,
#define BUILTIN_ID_METHODDEF \
{"id", (PyCFunction)builtin_id, METH_O, builtin_id__doc__},
+PyDoc_STRVAR(builtin_next__doc__,
+"next($module, iterator, default=<unrepresentable>, /)\n"
+"--\n"
+"\n"
+"Return the next item from the iterator.\n"
+"\n"
+"If default is given and the iterator is exhausted,\n"
+"it is returned instead of raising StopIteration.");
+
+#define BUILTIN_NEXT_METHODDEF \
+ {"next", _PyCFunction_CAST(builtin_next), METH_FASTCALL, builtin_next__doc__},
+
+static PyObject *
+builtin_next_impl(PyObject *module, PyObject *iterator,
+ PyObject *default_value);
+
+static PyObject *
+builtin_next(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *iterator;
+ PyObject *default_value = NULL;
+
+ if (!_PyArg_CheckPositional("next", nargs, 1, 2)) {
+ goto exit;
+ }
+ iterator = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ default_value = args[1];
+skip_optional:
+ return_value = builtin_next_impl(module, iterator, default_value);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(builtin_setattr__doc__,
"setattr($module, obj, name, value, /)\n"
"--\n"
@@ -702,6 +824,43 @@ PyDoc_STRVAR(builtin_hex__doc__,
#define BUILTIN_HEX_METHODDEF \
{"hex", (PyCFunction)builtin_hex, METH_O, builtin_hex__doc__},
+PyDoc_STRVAR(builtin_iter__doc__,
+"iter($module, object, sentinel=<unrepresentable>, /)\n"
+"--\n"
+"\n"
+"Get an iterator from an object.\n"
+"\n"
+"In the first form, the argument must supply its own iterator, or be a sequence.\n"
+"In the second form, the callable is called until it returns the sentinel.");
+
+#define BUILTIN_ITER_METHODDEF \
+ {"iter", _PyCFunction_CAST(builtin_iter), METH_FASTCALL, builtin_iter__doc__},
+
+static PyObject *
+builtin_iter_impl(PyObject *module, PyObject *object, PyObject *sentinel);
+
+static PyObject *
+builtin_iter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *object;
+ PyObject *sentinel = NULL;
+
+ if (!_PyArg_CheckPositional("iter", nargs, 1, 2)) {
+ goto exit;
+ }
+ object = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ sentinel = args[1];
+skip_optional:
+ return_value = builtin_iter_impl(module, object, sentinel);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(builtin_aiter__doc__,
"aiter($module, async_iterable, /)\n"
"--\n"
@@ -1080,6 +1239,41 @@ exit:
return return_value;
}
+PyDoc_STRVAR(builtin_vars__doc__,
+"vars($module, object=<unrepresentable>, /)\n"
+"--\n"
+"\n"
+"Show vars.\n"
+"\n"
+"Without arguments, equivalent to locals().\n"
+"With an argument, equivalent to object.__dict__.");
+
+#define BUILTIN_VARS_METHODDEF \
+ {"vars", _PyCFunction_CAST(builtin_vars), METH_FASTCALL, builtin_vars__doc__},
+
+static PyObject *
+builtin_vars_impl(PyObject *module, PyObject *object);
+
+static PyObject *
+builtin_vars(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *object = NULL;
+
+ if (!_PyArg_CheckPositional("vars", nargs, 0, 1)) {
+ goto exit;
+ }
+ if (nargs < 1) {
+ goto skip_optional;
+ }
+ object = args[0];
+skip_optional:
+ return_value = builtin_vars_impl(module, object);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(builtin_sum__doc__,
"sum($module, iterable, /, start=0)\n"
"--\n"
@@ -1215,4 +1409,4 @@ builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
exit:
return return_value;
}
-/*[clinic end generated code: output=973da43fa65aa727 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=0a6a8efe82cf8b81 input=a9049054013a1b77]*/