Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit38e2d32

Browse files
authored
Add PyIter_NextItem() function (#113)
1 parent3f1c06d commit38e2d32

File tree

4 files changed

+84
-4
lines changed

4 files changed

+84
-4
lines changed

‎docs/api.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ Python 3.14
3333

3434
See `PyLong_GetSign() documentation <https://docs.python.org/dev/c-api/long.html#c.PyLong_GetSign>`__.
3535

36+
.. c:function:: PyObject* PyIter_NextItem(PyObject *sep, PyObject *iterable)
37+
38+
See `PyIter_NextItem() documentation <https://docs.python.org/dev/c-api/iter.html#c.PyIter_NextItem>`__.
39+
3640
.. c:function:: PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable)
3741

3842
See `PyBytes_Join() documentation <https://docs.python.org/dev/c-api/bytes.html#c.PyBytes_Join>`__.

‎docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Changelog
44
* 2024-10-09: Add functions:
55

66
* ``PyBytes_Join()``
7+
* ``PyIter_NextItem()``
78
* ``PyUnicode_Equal()``
89
* ``Py_HashBuffer()``
910

‎pythoncapi_compat.h

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,14 +1519,12 @@ static inline int PyLong_GetSign(PyObject *obj, int *sign)
15191519
staticinlineintPyUnicode_Equal(PyObject *str1, PyObject *str2)
15201520
{
15211521
if (!PyUnicode_Check(str1)) {
1522-
PyErr_Format(PyExc_TypeError,
1523-
"first argument must be str, not %s",
1522+
PyErr_Format(PyExc_TypeError,"first argument must be str, not %s",
15241523
Py_TYPE(str1)->tp_name);
15251524
return -1;
15261525
}
15271526
if (!PyUnicode_Check(str2)) {
1528-
PyErr_Format(PyExc_TypeError,
1529-
"second argument must be str, not %s",
1527+
PyErr_Format(PyExc_TypeError,"second argument must be str, not %s",
15301528
Py_TYPE(str2)->tp_name);
15311529
return -1;
15321530
}
@@ -1576,6 +1574,37 @@ static inline Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len)
15761574
#endif
15771575

15781576

1577+
#if PY_VERSION_HEX < 0x030E00A0
1578+
staticinlineintPyIter_NextItem(PyObject *iter, PyObject **item)
1579+
{
1580+
iternextfunc tp_iternext;
1581+
1582+
assert(iter !=NULL);
1583+
assert(item !=NULL);
1584+
1585+
tp_iternext =Py_TYPE(iter)->tp_iternext;
1586+
if (tp_iternext ==NULL) {
1587+
*item =NULL;
1588+
PyErr_Format(PyExc_TypeError,"expected an iterator, got '%s'",
1589+
Py_TYPE(iter)->tp_name);
1590+
return -1;
1591+
}
1592+
1593+
if ((*item =tp_iternext(iter))) {
1594+
return1;
1595+
}
1596+
if (!PyErr_Occurred()) {
1597+
return0;
1598+
}
1599+
if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
1600+
PyErr_Clear();
1601+
return0;
1602+
}
1603+
return -1;
1604+
}
1605+
#endif
1606+
1607+
15791608
#ifdef __cplusplus
15801609
}
15811610
#endif

‎tests/test_pythoncapi_compat_cext.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,12 +1437,14 @@ static int
14371437
heapmanaged_traverse(PyObject*self,visitprocvisit,void*arg)
14381438
{
14391439
Py_VISIT(Py_TYPE(self));
1440+
// Test PyObject_VisitManagedDict()
14401441
returnPyObject_VisitManagedDict(self,visit,arg);
14411442
}
14421443

14431444
staticint
14441445
heapmanaged_clear(PyObject*self)
14451446
{
1447+
// Test PyObject_ClearManagedDict()
14461448
PyObject_ClearManagedDict(self);
14471449
return0;
14481450
}
@@ -1475,6 +1477,7 @@ static PyType_Spec HeapCTypeWithManagedDict_spec = {
14751477
staticPyObject*
14761478
test_managed_dict(PyObject*Py_UNUSED(module),PyObject*Py_UNUSED(args))
14771479
{
1480+
// Test PyObject_VisitManagedDict() and PyObject_ClearManagedDict()
14781481
PyObject*type=PyType_FromSpec(&HeapCTypeWithManagedDict_spec);
14791482
if (type==NULL) {
14801483
returnNULL;
@@ -1926,6 +1929,48 @@ test_bytes(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
19261929
}
19271930

19281931

1932+
staticPyObject*
1933+
test_iter(PyObject*Py_UNUSED(module),PyObject*Py_UNUSED(args))
1934+
{
1935+
// Test PyIter_NextItem()
1936+
PyObject*tuple=Py_BuildValue("(i)",123);
1937+
if (tuple==NULL) {
1938+
returnNULL;
1939+
}
1940+
PyObject*iter=PyObject_GetIter(tuple);
1941+
Py_DECREF(tuple);
1942+
if (iter==NULL) {
1943+
returnNULL;
1944+
}
1945+
1946+
// first item
1947+
PyObject*item=UNINITIALIZED_OBJ;
1948+
assert(PyIter_NextItem(iter,&item)==1);
1949+
{
1950+
PyObject*expected=PyLong_FromLong(123);
1951+
assert(PyObject_RichCompareBool(item,expected,Py_EQ)==1);
1952+
assert(expected!=NULL);
1953+
Py_DECREF(expected);
1954+
}
1955+
1956+
// StopIteration
1957+
item=UNINITIALIZED_OBJ;
1958+
assert(PyIter_NextItem(iter,&item)==0);
1959+
assert(item==NULL);
1960+
assert(!PyErr_Occurred());
1961+
1962+
// non-iterable object
1963+
item=UNINITIALIZED_OBJ;
1964+
assert(PyIter_NextItem(Py_None,&item)==-1);
1965+
assert(item==NULL);
1966+
assert(PyErr_ExceptionMatches(PyExc_TypeError));
1967+
PyErr_Clear();
1968+
1969+
Py_DECREF(iter);
1970+
Py_RETURN_NONE;
1971+
}
1972+
1973+
19291974
staticstructPyMethodDefmethods[]= {
19301975
{"test_object",test_object,METH_NOARGS,_Py_NULL},
19311976
{"test_py_is",test_py_is,METH_NOARGS,_Py_NULL},
@@ -1970,6 +2015,7 @@ static struct PyMethodDef methods[] = {
19702015
{"test_unicodewriter_format",test_unicodewriter_format,METH_NOARGS,_Py_NULL},
19712016
#endif
19722017
{"test_bytes",test_bytes,METH_NOARGS,_Py_NULL},
2018+
{"test_iter",test_iter,METH_NOARGS,_Py_NULL},
19732019
{_Py_NULL,_Py_NULL,0,_Py_NULL}
19742020
};
19752021

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp