mirror of
https://github.com/python/cpython.git
synced 2024-11-21 21:09:37 +01:00
e006c7371d
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>
182 lines
4.7 KiB
C
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;
|
|
}
|