Skip to content

Commit f63a8c3

Browse files
committed
gh-139772: Add PyDict_NewPresized() function
1 parent c4e7d24 commit f63a8c3

File tree

7 files changed

+46
-4
lines changed

7 files changed

+46
-4
lines changed

Doc/c-api/dict.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ Dictionary Objects
3636
Return a new empty dictionary, or ``NULL`` on failure.
3737
3838
39+
.. c:function:: PyObject* PyDict_NewPresized(Py_ssize_t size)
40+
41+
Return a new empty dictionary with at least *size* preallocated items,
42+
or ``NULL`` on failure.
43+
44+
.. versionadded:: next
45+
46+
3947
.. c:function:: PyObject* PyDictProxy_New(PyObject *mapping)
4048
4149
Return a :class:`types.MappingProxyType` object for a mapping which

Doc/whatsnew/3.15.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,10 @@ New features
852852

853853
(Contributed by Victor Stinner in :gh:`129813`.)
854854

855+
* Add :c:func:`PyDict_NewPresized` function to create a new empty dictionary
856+
with at least *size* preallocated items.
857+
(Contributed by Victor Stinner in :gh:`139772`.)
858+
855859

856860
Porting to Python 3.15
857861
----------------------

Include/cpython/dictobject.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,12 @@ static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
6464

6565
PyAPI_FUNC(int) PyDict_ContainsString(PyObject *mp, const char *key);
6666

67-
PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused);
67+
PyAPI_FUNC(PyObject*) PyDict_NewPresized(Py_ssize_t size);
68+
Py_DEPRECATED(3.15) static inline PyObject*
69+
_PyDict_NewPresized(Py_ssize_t size)
70+
{
71+
return PyDict_NewPresized(size);
72+
}
6873

6974
PyAPI_FUNC(int) PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result);
7075
PyAPI_FUNC(int) PyDict_PopString(PyObject *dict, const char *key, PyObject **result);

Lib/test/test_capi/test_dict.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,17 @@ def test_dict_popstring(self):
545545
# CRASHES dict_popstring({}, NULL)
546546
# CRASHES dict_popstring({"a": 1}, NULL)
547547

548+
def test_dict_newpresized(self):
549+
# Test PyDict_NewPresized()
550+
dict_newpresized = _testcapi.dict_newpresized
551+
d = dict_newpresized(3)
552+
d[1] = 'a'
553+
d[2] = 'b'
554+
d[3] = 'c'
555+
self.assertEqual(len(d), 3)
556+
d[4] = 'd'
557+
self.assertEqual(len(d), 4)
558+
548559

549560
if __name__ == "__main__":
550561
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add :c:func:`PyDict_NewPresized` function to create a new empty dictionary with
2+
at least *size* preallocated items. Patch by Victor Stinner.

Modules/_testcapi/dict.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,17 @@ test_dict_iteration(PyObject* self, PyObject *Py_UNUSED(ignored))
258258
}
259259

260260

261+
static PyObject *
262+
dict_newpresized(PyObject *self, PyObject *args)
263+
{
264+
Py_ssize_t size;
265+
if (!PyArg_ParseTuple(args, "n", &size)) {
266+
return NULL;
267+
}
268+
return PyDict_NewPresized(size);
269+
}
270+
271+
261272
static PyMethodDef test_methods[] = {
262273
{"dict_containsstring", dict_containsstring, METH_VARARGS},
263274
{"dict_getitemref", dict_getitemref, METH_VARARGS},
@@ -268,7 +279,8 @@ static PyMethodDef test_methods[] = {
268279
{"dict_pop_null", dict_pop_null, METH_VARARGS},
269280
{"dict_popstring", dict_popstring, METH_VARARGS},
270281
{"dict_popstring_null", dict_popstring_null, METH_VARARGS},
271-
{"test_dict_iteration", test_dict_iteration, METH_NOARGS},
282+
{"test_dict_iteration", test_dict_iteration, METH_NOARGS},
283+
{"dict_newpresized", dict_newpresized, METH_VARARGS},
272284
{NULL},
273285
};
274286

Objects/dictobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,9 +2220,9 @@ dict_new_presized(Py_ssize_t minused, bool unicode)
22202220
}
22212221

22222222
PyObject *
2223-
_PyDict_NewPresized(Py_ssize_t minused)
2223+
PyDict_NewPresized(Py_ssize_t size)
22242224
{
2225-
return dict_new_presized(minused, false);
2225+
return dict_new_presized(size, false);
22262226
}
22272227

22282228
PyObject *

0 commit comments

Comments
 (0)