Skip to content

Commit 4734c8e

Browse files
authored
Add PyDict_ContainsString() function (#71)
1 parent 5b5b547 commit 4734c8e

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

pythoncapi_compat.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,21 @@ static inline int Py_IsFinalizing(void)
819819
#endif
820820

821821

822+
// gh-108323 added PyDict_ContainsString() to Python 3.13.0a1
823+
#if PY_VERSION_HEX < 0x030D00A1
824+
static inline int PyDict_ContainsString(PyObject *op, const char *key)
825+
{
826+
PyObject *key_obj = PyUnicode_FromString(key);
827+
if (key_obj == NULL) {
828+
return -1;
829+
}
830+
int res = PyDict_Contains(op, key_obj);
831+
Py_DECREF(key_obj);
832+
return res;
833+
}
834+
#endif
835+
836+
822837
#ifdef __cplusplus
823838
}
824839
#endif

tests/test_pythoncapi_compat_cext.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,7 @@ test_getitem(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
10921092

10931093

10941094
static PyObject *
1095-
test_dict_getitemref(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
1095+
test_dict_api(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
10961096
{
10971097
assert(!PyErr_Occurred());
10981098

@@ -1112,12 +1112,18 @@ test_dict_getitemref(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
11121112
if (key == NULL) {
11131113
goto error;
11141114
}
1115+
invalid_dict = key; // borrowed reference
11151116

11161117
missing_key = PyUnicode_FromString("missing_key");
11171118
if (missing_key == NULL) {
11181119
goto error;
11191120
}
11201121

1122+
invalid_key = PyList_New(0); // not hashable key
1123+
if (invalid_key == NULL) {
1124+
goto error;
1125+
}
1126+
11211127
value = PyUnicode_FromString("value");
11221128
if (value == NULL) {
11231129
goto error;
@@ -1129,6 +1135,17 @@ test_dict_getitemref(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
11291135
}
11301136
assert(res == 0);
11311137

1138+
// test PyDict_Contains()
1139+
assert(PyDict_Contains(dict, key) == 1);
1140+
assert(PyDict_Contains(dict, missing_key) == 0);
1141+
1142+
// test PyDict_ContainsString()
1143+
assert(PyDict_ContainsString(dict, "key") == 1);
1144+
assert(PyDict_ContainsString(dict, "missing_key") == 0);
1145+
assert(PyDict_ContainsString(dict, "\xff") == -1);
1146+
assert(PyErr_ExceptionMatches(PyExc_UnicodeDecodeError));
1147+
PyErr_Clear();
1148+
11321149
// test PyDict_GetItemRef(), key is present
11331150
get_value = Py_Ellipsis; // marker value
11341151
assert(PyDict_GetItemRef(dict, key, &get_value) == 1);
@@ -1154,7 +1171,6 @@ test_dict_getitemref(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
11541171
assert(get_value == NULL);
11551172

11561173
// test PyDict_GetItemRef(), invalid dict
1157-
invalid_dict = key; // borrowed reference
11581174
get_value = Py_Ellipsis; // marker value
11591175
assert(PyDict_GetItemRef(invalid_dict, key, &get_value) == -1);
11601176
assert(PyErr_ExceptionMatches(PyExc_SystemError));
@@ -1168,11 +1184,6 @@ test_dict_getitemref(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
11681184
PyErr_Clear();
11691185
assert(get_value == NULL);
11701186

1171-
invalid_key = PyList_New(0); // not hashable key
1172-
if (invalid_key == NULL) {
1173-
goto error;
1174-
}
1175-
11761187
// test PyDict_GetItemRef(), invalid key
11771188
get_value = Py_Ellipsis; // marker value
11781189
assert(PyDict_GetItemRef(dict, invalid_key, &get_value) == -1);
@@ -1222,7 +1233,7 @@ static struct PyMethodDef methods[] = {
12221233
{"test_vectorcall", test_vectorcall, METH_NOARGS, _Py_NULL},
12231234
{"test_getattr", test_getattr, METH_NOARGS, _Py_NULL},
12241235
{"test_getitem", test_getitem, METH_NOARGS, _Py_NULL},
1225-
{"test_dict_getitemref", test_dict_getitemref, METH_NOARGS, _Py_NULL},
1236+
{"test_dict_api", test_dict_api, METH_NOARGS, _Py_NULL},
12261237
{_Py_NULL, _Py_NULL, 0, _Py_NULL}
12271238
};
12281239

0 commit comments

Comments
 (0)