Skip to content

Commit 7c84afb

Browse files
committed
Add more tests
1 parent 93f84ad commit 7c84afb

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

Lib/test/test_capi/test_dict.py

+24-1
Original file line numberDiff line numberDiff line change
@@ -477,23 +477,46 @@ def test_dict_pop(self):
477477
def test_dict_popstring(self):
478478
# Test PyDict_PopString()
479479
dict_popstring = _testcapi.dict_popstring
480+
dict_popstring_null = _testcapi.dict_popstring_null
480481

481-
# key present
482+
# key present, get removed value
482483
mydict = {"key": "value", "key2": "value2"}
483484
self.assertEqual(dict_popstring(mydict, "key"), (1, "value"))
484485
self.assertEqual(mydict, {"key2": "value2"})
485486
self.assertEqual(dict_popstring(mydict, "key2"), (1, "value2"))
486487
self.assertEqual(mydict, {})
487488

489+
# key present, ignore removed value
490+
mydict = {"key": "value", "key2": "value2"}
491+
self.assertEqual(dict_popstring_null(mydict, "key"), 1)
492+
self.assertEqual(mydict, {"key2": "value2"})
493+
self.assertEqual(dict_popstring_null(mydict, "key2"), 1)
494+
self.assertEqual(mydict, {})
495+
488496
# key missing; empty dict has a fast path
489497
self.assertEqual(dict_popstring({}, "key"), (0, NULL))
498+
self.assertEqual(dict_popstring_null({}, "key"), 0)
490499
self.assertEqual(dict_popstring({"a": 1}, "key"), (0, NULL))
500+
self.assertEqual(dict_popstring_null({"a": 1}, "key"), 0)
501+
502+
# non-ASCII key
503+
non_ascii = '\U0001f40d'
504+
dct = {'\U0001f40d': 123}
505+
self.assertEqual(dict_popstring(dct, '\U0001f40d'.encode()), (1, 123))
506+
dct = {'\U0001f40d': 123}
507+
self.assertEqual(dict_popstring_null(dct, '\U0001f40d'.encode()), 1)
491508

492509
# dict error
493510
not_dict = UserDict({1: 2})
494511
self.assertRaises(SystemError, dict_popstring, not_dict, "key")
512+
self.assertRaises(SystemError, dict_popstring_null, not_dict, "key")
513+
514+
# key error
515+
self.assertRaises(UnicodeDecodeError, dict_popstring, {1: 2}, INVALID_UTF8)
516+
self.assertRaises(UnicodeDecodeError, dict_popstring_null, {1: 2}, INVALID_UTF8)
495517

496518
# CRASHES dict_popstring(NULL, "key")
519+
# CRASHES dict_popstring({}, NULL)
497520
# CRASHES dict_popstring({"a": 1}, NULL)
498521

499522

Modules/_testcapi/dict.c

+16-5
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,7 @@ dict_pop_null(PyObject *self, PyObject *args)
368368
}
369369
NULLABLE(dict);
370370
NULLABLE(key);
371-
int res = PyDict_Pop(dict, key, NULL);
372-
if (res < 0) {
373-
return NULL;
374-
}
375-
return PyLong_FromLong(res);
371+
RETURN_INT(PyDict_Pop(dict, key, NULL));
376372
}
377373

378374

@@ -403,6 +399,20 @@ dict_popstring(PyObject *self, PyObject *args)
403399
}
404400

405401

402+
static PyObject *
403+
dict_popstring_null(PyObject *self, PyObject *args)
404+
{
405+
PyObject *dict;
406+
const char *key;
407+
Py_ssize_t key_size;
408+
if (!PyArg_ParseTuple(args, "Oz#", &dict, &key, &key_size)) {
409+
return NULL;
410+
}
411+
NULLABLE(dict);
412+
RETURN_INT(PyDict_PopString(dict, key, NULL));
413+
}
414+
415+
406416
static PyMethodDef test_methods[] = {
407417
{"dict_check", dict_check, METH_O},
408418
{"dict_checkexact", dict_checkexact, METH_O},
@@ -433,6 +443,7 @@ static PyMethodDef test_methods[] = {
433443
{"dict_pop", dict_pop, METH_VARARGS},
434444
{"dict_pop_null", dict_pop_null, METH_VARARGS},
435445
{"dict_popstring", dict_popstring, METH_VARARGS},
446+
{"dict_popstring_null", dict_popstring_null, METH_VARARGS},
436447
{NULL},
437448
};
438449

0 commit comments

Comments
 (0)