Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fa618e6

Browse files
committed
Add tests
1 parent 22bb430 commit fa618e6

File tree

2 files changed

+83
-4
lines changed

2 files changed

+83
-4
lines changed

Lib/test/test_capi/test_dict.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,21 +435,34 @@ def test_dict_mergefromseq2(self):
435435
def test_dict_pop(self):
436436
# Test PyDict_Pop()
437437
dict_pop = _testcapi.dict_pop
438+
dict_pop_null = _testcapi.dict_pop_null
438439

439-
# key present
440+
# key present, get removed value
440441
mydict = {"key": "value", "key2": "value2"}
441442
self.assertEqual(dict_pop(mydict, "key"), (1, "value"))
442443
self.assertEqual(mydict, {"key2": "value2"})
443444
self.assertEqual(dict_pop(mydict, "key2"), (1, "value2"))
444445
self.assertEqual(mydict, {})
445446

446-
# key missing; empty dict has a fast path
447+
# key present, ignore removed value
448+
mydict = {"key": "value", "key2": "value2"}
449+
self.assertEqual(dict_pop_null(mydict, "key"), 1)
450+
self.assertEqual(mydict, {"key2": "value2"})
451+
self.assertEqual(dict_pop_null(mydict, "key2"), 1)
452+
self.assertEqual(mydict, {})
453+
454+
# key missing, expect removed value; empty dict has a fast path
447455
self.assertEqual(dict_pop({}, "key"), (0, NULL))
448456
self.assertEqual(dict_pop({"a": 1}, "key"), (0, NULL))
449457

458+
# key missing, ignored removed value; empty dict has a fast path
459+
self.assertEqual(dict_pop_null({}, "key"), 0)
460+
self.assertEqual(dict_pop_null({"a": 1}, "key"), 0)
461+
450462
# dict error
451-
not_dict = "string"
463+
not_dict = UserDict({1: 2})
452464
self.assertRaises(SystemError, dict_pop, not_dict, "key")
465+
self.assertRaises(SystemError, dict_pop_null, not_dict, "key")
453466

454467
# key error; don't hash key if dict is empty
455468
not_hashable_key = ["list"]
@@ -459,7 +472,29 @@ def test_dict_pop(self):
459472
dict_pop({}, NULL) # key is not checked if dict is empty
460473

461474
# CRASHES dict_pop(NULL, "key")
462-
# CRASHES dict_pop({"a": 1}, NULL, default)
475+
# CRASHES dict_pop({"a": 1}, NULL)
476+
477+
def test_dict_popstring(self):
478+
# Test PyDict_PopString()
479+
dict_popstring = _testcapi.dict_popstring
480+
481+
# key present
482+
mydict = {"key": "value", "key2": "value2"}
483+
self.assertEqual(dict_popstring(mydict, "key"), (1, "value"))
484+
self.assertEqual(mydict, {"key2": "value2"})
485+
self.assertEqual(dict_popstring(mydict, "key2"), (1, "value2"))
486+
self.assertEqual(mydict, {})
487+
488+
# key missing; empty dict has a fast path
489+
self.assertEqual(dict_popstring({}, "key"), (0, NULL))
490+
self.assertEqual(dict_popstring({"a": 1}, "key"), (0, NULL))
491+
492+
# dict error
493+
not_dict = UserDict({1: 2})
494+
self.assertRaises(SystemError, dict_popstring, not_dict, "key")
495+
496+
# CRASHES dict_popstring(NULL, "key")
497+
# CRASHES dict_popstring({"a": 1}, NULL)
463498

464499

465500
if __name__ == "__main__":

Modules/_testcapi/dict.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ dict_mergefromseq2(PyObject *self, PyObject *args)
334334
static PyObject *
335335
dict_pop(PyObject *self, PyObject *args)
336336
{
337+
// Test PyDict_Pop(dict, key, &value)
337338
PyObject *dict, *key;
338339
if (!PyArg_ParseTuple(args, "OO", &dict, &key)) {
339340
return NULL;
@@ -353,6 +354,47 @@ dict_pop(PyObject *self, PyObject *args)
353354
}
354355

355356

357+
static PyObject *
358+
dict_pop_null(PyObject *self, PyObject *args)
359+
{
360+
// Test PyDict_Pop(dict, key, NULL)
361+
PyObject *dict, *key;
362+
if (!PyArg_ParseTuple(args, "OO", &dict, &key)) {
363+
return NULL;
364+
}
365+
NULLABLE(dict);
366+
NULLABLE(key);
367+
int res = PyDict_Pop(dict, key, NULL);
368+
if (res < 0) {
369+
return NULL;
370+
}
371+
return PyLong_FromLong(res);
372+
}
373+
374+
375+
static PyObject *
376+
dict_popstring(PyObject *self, PyObject *args)
377+
{
378+
PyObject *dict;
379+
const char *key;
380+
Py_ssize_t key_size;
381+
if (!PyArg_ParseTuple(args, "Oz#", &dict, &key, &key_size)) {
382+
return NULL;
383+
}
384+
NULLABLE(dict);
385+
PyObject *result = UNINITIALIZED_PTR;
386+
int res = PyDict_PopString(dict, key, &result);
387+
if (res < 0) {
388+
assert(result == NULL);
389+
return NULL;
390+
}
391+
if (result == NULL) {
392+
result = Py_NewRef(Py_None);
393+
}
394+
return Py_BuildValue("iN", res, result);
395+
}
396+
397+
356398
static PyMethodDef test_methods[] = {
357399
{"dict_check", dict_check, METH_O},
358400
{"dict_checkexact", dict_checkexact, METH_O},
@@ -381,6 +423,8 @@ static PyMethodDef test_methods[] = {
381423
{"dict_update", dict_update, METH_VARARGS},
382424
{"dict_mergefromseq2", dict_mergefromseq2, METH_VARARGS},
383425
{"dict_pop", dict_pop, METH_VARARGS},
426+
{"dict_pop_null", dict_pop_null, METH_VARARGS},
427+
{"dict_popstring", dict_popstring, METH_VARARGS},
384428
{NULL},
385429
};
386430

0 commit comments

Comments
 (0)