gh-100357: Convert several functions in `bltinsmodule` to AC (#100358)

This commit is contained in:
Nikita Sobolev 2022-12-24 17:45:47 +03:00 committed by GitHub
parent 0769f95751
commit bdfb694386
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 307 additions and 101 deletions

View File

@ -0,0 +1,2 @@
Convert ``vars``, ``dir``, ``next``, ``getattr``, and ``iter`` to argument
clinic.

View File

@ -837,31 +837,33 @@ finally:
return result;
}
/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
static PyObject *
builtin_dir(PyObject *self, PyObject *args)
{
PyObject *arg = NULL;
/*[clinic input]
dir as builtin_dir
if (!PyArg_UnpackTuple(args, "dir", 0, 1, &arg))
return NULL;
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_impl(PyObject *module, PyObject *arg)
/*[clinic end generated code: output=24f2c7a52c1e3b08 input=ed6d6ccb13d52251]*/
{
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;
PyObject *result;
if (!_PyArg_CheckPositional("getattr", nargs, 2, 3))
return NULL;
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;
PyObject *res;
if (!_PyArg_CheckPositional("next", nargs, 1, 2))
return NULL;
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 */
static PyObject *
builtin_iter(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *v;
/*[clinic input]
iter as builtin_iter
if (!_PyArg_CheckPositional("iter", nargs, 1, 2))
return NULL;
v = args[0];
if (nargs == 1)
return PyObject_GetIter(v);
if (!PyCallable_Check(v)) {
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_impl(PyObject *module, PyObject *object, PyObject *sentinel)
/*[clinic end generated code: output=12cf64203c195a94 input=a5d64d9d81880ba6]*/
{
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},
};

View File

@ -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]*/