0
0
mirror of https://github.com/python/cpython.git synced 2024-11-21 21:09:37 +01:00
cpython/Modules/_testcapi/abstract.c
Erlend E. Aasland e006c7371d
gh-105201: Add PyIter_NextItem() (#122331)
Return -1 and set an exception on error; return 0 if the iterator is
exhausted, and return 1 if the next item was fetched successfully.

Prefer this API to PyIter_Next(), which requires the caller to use
PyErr_Occurred() to differentiate between iterator exhaustion and errors.

Co-authered-by: Irit Katriel <iritkatriel@yahoo.com>
2024-08-08 00:47:15 +02:00

182 lines
4.7 KiB
C

#include "parts.h"
#include "util.h"
static PyObject *
object_getoptionalattr(PyObject *self, PyObject *args)
{
PyObject *obj, *attr_name, *value = UNINITIALIZED_PTR;
if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) {
return NULL;
}
NULLABLE(obj);
NULLABLE(attr_name);
switch (PyObject_GetOptionalAttr(obj, attr_name, &value)) {
case -1:
assert(value == NULL);
return NULL;
case 0:
assert(value == NULL);
return Py_NewRef(PyExc_AttributeError);
case 1:
return value;
default:
Py_FatalError("PyObject_GetOptionalAttr() returned invalid code");
Py_UNREACHABLE();
}
}
static PyObject *
object_getoptionalattrstring(PyObject *self, PyObject *args)
{
PyObject *obj, *value = UNINITIALIZED_PTR;
const char *attr_name;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) {
return NULL;
}
NULLABLE(obj);
switch (PyObject_GetOptionalAttrString(obj, attr_name, &value)) {
case -1:
assert(value == NULL);
return NULL;
case 0:
assert(value == NULL);
return Py_NewRef(PyExc_AttributeError);
case 1:
return value;
default:
Py_FatalError("PyObject_GetOptionalAttrString() returned invalid code");
Py_UNREACHABLE();
}
}
static PyObject *
object_hasattrwitherror(PyObject *self, PyObject *args)
{
PyObject *obj, *attr_name;
if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) {
return NULL;
}
NULLABLE(obj);
NULLABLE(attr_name);
RETURN_INT(PyObject_HasAttrWithError(obj, attr_name));
}
static PyObject *
object_hasattrstringwitherror(PyObject *self, PyObject *args)
{
PyObject *obj;
const char *attr_name;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) {
return NULL;
}
NULLABLE(obj);
RETURN_INT(PyObject_HasAttrStringWithError(obj, attr_name));
}
static PyObject *
mapping_getoptionalitemstring(PyObject *self, PyObject *args)
{
PyObject *obj, *value = UNINITIALIZED_PTR;
const char *attr_name;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "Oz#", &obj, &attr_name, &size)) {
return NULL;
}
NULLABLE(obj);
switch (PyMapping_GetOptionalItemString(obj, attr_name, &value)) {
case -1:
assert(value == NULL);
return NULL;
case 0:
assert(value == NULL);
return Py_NewRef(PyExc_KeyError);
case 1:
return value;
default:
Py_FatalError("PyMapping_GetOptionalItemString() returned invalid code");
Py_UNREACHABLE();
}
}
static PyObject *
mapping_getoptionalitem(PyObject *self, PyObject *args)
{
PyObject *obj, *attr_name, *value = UNINITIALIZED_PTR;
if (!PyArg_ParseTuple(args, "OO", &obj, &attr_name)) {
return NULL;
}
NULLABLE(obj);
NULLABLE(attr_name);
switch (PyMapping_GetOptionalItem(obj, attr_name, &value)) {
case -1:
assert(value == NULL);
return NULL;
case 0:
assert(value == NULL);
return Py_NewRef(PyExc_KeyError);
case 1:
return value;
default:
Py_FatalError("PyMapping_GetOptionalItem() returned invalid code");
Py_UNREACHABLE();
}
}
static PyObject *
pyiter_next(PyObject *self, PyObject *iter)
{
PyObject *item = PyIter_Next(iter);
if (item == NULL && !PyErr_Occurred()) {
Py_RETURN_NONE;
}
return item;
}
static PyObject *
pyiter_nextitem(PyObject *self, PyObject *iter)
{
PyObject *item;
int rc = PyIter_NextItem(iter, &item);
if (rc < 0) {
assert(PyErr_Occurred());
assert(item == NULL);
return NULL;
}
assert(!PyErr_Occurred());
if (item == NULL) {
Py_RETURN_NONE;
}
return item;
}
static PyMethodDef test_methods[] = {
{"object_getoptionalattr", object_getoptionalattr, METH_VARARGS},
{"object_getoptionalattrstring", object_getoptionalattrstring, METH_VARARGS},
{"object_hasattrwitherror", object_hasattrwitherror, METH_VARARGS},
{"object_hasattrstringwitherror", object_hasattrstringwitherror, METH_VARARGS},
{"mapping_getoptionalitem", mapping_getoptionalitem, METH_VARARGS},
{"mapping_getoptionalitemstring", mapping_getoptionalitemstring, METH_VARARGS},
{"PyIter_Next", pyiter_next, METH_O},
{"PyIter_NextItem", pyiter_nextitem, METH_O},
{NULL},
};
int
_PyTestCapi_Init_Abstract(PyObject *m)
{
if (PyModule_AddFunctions(m, test_methods) < 0) {
return -1;
}
return 0;
}