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

Appearance settings

Commit 7515dae

Browse filesBrowse files
committed
Add PyMapping_GetOptionalItem() function
1 parent 157d6d4 commit 7515dae
Copy full SHA for 7515dae

File tree

Expand file treeCollapse file tree

4 files changed

+101
-5
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+101
-5
lines changed

‎docs/api.rst

Copy file name to clipboardExpand all lines: docs/api.rst
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ Python 3.13
4343
4444
See `PyObject_GetOptionalAttrString() documentation <https://docs.python.org/dev/c-api/object.html#c.PyObject_GetOptionalAttrString>`__.
4545
46+
.. c:function:: int PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result)
47+
48+
See `PyMapping_GetOptionalItem() documentation <https://docs.python.org/dev/c-api/mapping.html#c.PyMapping_GetOptionalItem>`__.
49+
50+
.. c:function:: int PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result)
51+
52+
See `PyMapping_GetOptionalItemString() documentation <https://docs.python.org/dev/c-api/mapping.html#c.PyMapping_GetOptionalItemString>`__.
53+
4654
4755
Python 3.12
4856
-----------

‎docs/changelog.rst

Copy file name to clipboardExpand all lines: docs/changelog.rst
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
Changelog
22
=========
33

4-
* 2023-07-12: Add ``PyObject_GetOptionalAttr()`` and
5-
``PyObject_GetOptionalAttrString()`` functions.
4+
* 2023-07-12: Add ``PyObject_GetOptionalAttr()``,
5+
``PyObject_GetOptionalAttrString()``,
6+
``PyMapping_GetOptionalItem()``
7+
and ``PyMapping_GetOptionalItemString()`` functions.
68
* 2023-07-05: Add ``PyObject_Vectorcall()`` function.
79
* 2023-06-21: Add ``PyWeakref_GetRef()`` function.
810
* 2023-06-20: Add ``PyImport_AddModuleRef()`` function.

‎pythoncapi_compat.h

Copy file name to clipboardExpand all lines: pythoncapi_compat.h
+44-3Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,11 @@ PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
284284
PyFrame_GetVarString(PyFrameObject *frame, const char *name)
285285
{
286286
PyObject *name_obj, *value;
287+
#if PY_VERSION_HEX >= 0x03000000
287288
name_obj = PyUnicode_FromString(name);
289+
#else
290+
name_obj = PyString_FromString(name);
291+
#endif
288292
if (name_obj == NULL) {
289293
return NULL;
290294
}
@@ -723,9 +727,10 @@ PyObject_GetOptionalAttr(PyObject *obj, PyObject *name, PyObject **result)
723727
}
724728

725729
PYCAPI_COMPAT_STATIC_INLINE(int)
726-
PyObject_GetOptionalAttrString(PyObject *obj, const char *name, PyObject **presult)
730+
PyObject_GetOptionalAttrString(PyObject *obj, const char *name, PyObject **result)
727731
{
728732
PyObject *name_obj;
733+
int rc;
729734
#if PY_VERSION_HEX >= 0x03000000
730735
name_obj = PyUnicode_FromString(name);
731736
#else
@@ -734,9 +739,45 @@ PyObject_GetOptionalAttrString(PyObject *obj, const char *name, PyObject **presu
734739
if (name_obj == NULL) {
735740
return -1;
736741
}
737-
int res = PyObject_GetOptionalAttr(obj, name_obj, presult);
742+
rc = PyObject_GetOptionalAttr(obj, name_obj, result);
738743
Py_DECREF(name_obj);
739-
return res;
744+
return rc;
745+
}
746+
#endif
747+
748+
749+
// gh-106307 added PyObject_GetOptionalAttr() to Python 3.13.0a1
750+
#if PY_VERSION_HEX < 0x030D00A1
751+
PYCAPI_COMPAT_STATIC_INLINE(int)
752+
PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result)
753+
{
754+
*result = PyObject_GetItem(obj, key);
755+
if (*result) {
756+
return 1;
757+
}
758+
if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
759+
return -1;
760+
}
761+
PyErr_Clear();
762+
return 0;
763+
}
764+
765+
PYCAPI_COMPAT_STATIC_INLINE(int)
766+
PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result)
767+
{
768+
PyObject *key_obj;
769+
int rc;
770+
#if PY_VERSION_HEX >= 0x03000000
771+
key_obj = PyUnicode_FromString(key);
772+
#else
773+
key_obj = PyString_FromString(key);
774+
#endif
775+
if (key_obj == NULL) {
776+
return -1;
777+
}
778+
rc = PyMapping_GetOptionalItem(obj, key_obj, result);
779+
Py_DECREF(key_obj);
780+
return rc;
740781
}
741782
#endif
742783

‎tests/test_pythoncapi_compat_cext.c

Copy file name to clipboardExpand all lines: tests/test_pythoncapi_compat_cext.c
+45Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,50 @@ test_getattr(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
990990
}
991991

992992

993+
static PyObject *
994+
test_getitem(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
995+
{
996+
assert(!PyErr_Occurred());
997+
998+
PyObject *value = Py_BuildValue("s", "value");
999+
assert(value != NULL);
1000+
PyObject *obj = Py_BuildValue("{sO}", "key", value);
1001+
assert(obj != NULL);
1002+
PyObject *key;
1003+
PyObject *item;
1004+
1005+
// test PyMapping_GetOptionalItem(): key is present
1006+
key = create_string("key");
1007+
item = Py_True; // marker value
1008+
assert(PyMapping_GetOptionalItem(obj, key, &item) == 1);
1009+
assert(item == value);
1010+
Py_DECREF(item);
1011+
Py_DECREF(key);
1012+
1013+
// test PyMapping_GetOptionalItemString(): key is present
1014+
item = Py_True; // marker value
1015+
assert(PyMapping_GetOptionalItemString(obj, "key", &item) == 1);
1016+
assert(item == value);
1017+
Py_DECREF(item);
1018+
1019+
// test PyMapping_GetOptionalItem(): missing key
1020+
key = create_string("dontexist");
1021+
item = Py_True; // marker value
1022+
assert(PyMapping_GetOptionalItem(obj, key, &item) == 0);
1023+
assert(item == NULL);
1024+
Py_DECREF(key);
1025+
1026+
// test PyMapping_GetOptionalItemString(): missing key
1027+
item = Py_True; // marker value
1028+
assert(PyMapping_GetOptionalItemString(obj, "dontexist", &item) == 0);
1029+
assert(item == NULL);
1030+
1031+
Py_DECREF(obj);
1032+
Py_DECREF(value);
1033+
Py_RETURN_NONE;
1034+
}
1035+
1036+
9931037
static struct PyMethodDef methods[] = {
9941038
{"test_object", test_object, METH_NOARGS, _Py_NULL},
9951039
{"test_py_is", test_py_is, METH_NOARGS, _Py_NULL},
@@ -1013,6 +1057,7 @@ static struct PyMethodDef methods[] = {
10131057
{"func_varargs", (PyCFunction)(void*)func_varargs, METH_VARARGS | METH_KEYWORDS, _Py_NULL},
10141058
{"test_vectorcall", test_vectorcall, METH_NOARGS, _Py_NULL},
10151059
{"test_getattr", test_getattr, METH_NOARGS, _Py_NULL},
1060+
{"test_getitem", test_getitem, METH_NOARGS, _Py_NULL},
10161061
{_Py_NULL, _Py_NULL, 0, _Py_NULL}
10171062
};
10181063

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.