summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/dictobject.h2
-rw-r--r--Lib/test/test_ordered_dict.py32
-rw-r--r--Misc/NEWS2
-rw-r--r--Objects/dictobject.c12
-rw-r--r--Objects/odictobject.c22
5 files changed, 45 insertions, 25 deletions
diff --git a/Include/dictobject.h b/Include/dictobject.h
index 80bd330..ba90aaf 100644
--- a/Include/dictobject.h
+++ b/Include/dictobject.h
@@ -98,7 +98,7 @@ PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused);
PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp);
PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp);
Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys);
-PyObject *_PyDict_SizeOf(PyDictObject *);
+Py_ssize_t _PyDict_SizeOf(PyDictObject *);
PyObject *_PyDict_Pop(PyDictObject *, PyObject *, PyObject *);
PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *);
#define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL)
diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py
index e64c7e5..9f9922c 100644
--- a/Lib/test/test_ordered_dict.py
+++ b/Lib/test/test_ordered_dict.py
@@ -2,6 +2,7 @@ import contextlib
import copy
import pickle
from random import randrange, shuffle
+import struct
import sys
import unittest
from collections.abc import MutableMapping
@@ -604,6 +605,37 @@ class CPythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
module = c_coll
OrderedDict = c_coll.OrderedDict
+ check_sizeof = support.check_sizeof
+
+ @support.cpython_only
+ def test_sizeof_exact(self):
+ OrderedDict = self.OrderedDict
+ calcsize = struct.calcsize
+ size = support.calcobjsize
+ check = self.check_sizeof
+
+ basicsize = size('n2P' + '3PnPn2P') + calcsize('2nPn')
+ entrysize = calcsize('n2P') + calcsize('P')
+ nodesize = calcsize('Pn2P')
+
+ od = OrderedDict()
+ check(od, basicsize + 8*entrysize)
+ od.x = 1
+ check(od, basicsize + 8*entrysize)
+ od.update([(i, i) for i in range(3)])
+ check(od, basicsize + 8*entrysize + 3*nodesize)
+ od.update([(i, i) for i in range(3, 10)])
+ check(od, basicsize + 16*entrysize + 10*nodesize)
+
+ check(od.keys(), size('P'))
+ check(od.items(), size('P'))
+ check(od.values(), size('P'))
+
+ itersize = size('iP2n2P')
+ check(iter(od), itersize)
+ check(iter(od.keys()), itersize)
+ check(iter(od.items()), itersize)
+ check(iter(od.values()), itersize)
def test_key_change_during_iteration(self):
OrderedDict = self.OrderedDict
diff --git a/Misc/NEWS b/Misc/NEWS
index 0d9c7dd..4a94f76 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -115,6 +115,8 @@ Core and Builtins
Library
-------
+- Issue #25914: Fixed and simplified OrderedDict.__sizeof__.
+
- Issue #25869: Optimized deepcopying ElementTree; it is now 20 times faster.
- Issue #25873: Optimized iterating ElementTree. Iterating elements
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 752853f..6f57db0 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -2557,7 +2557,7 @@ dict_tp_clear(PyObject *op)
static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
-PyObject *
+Py_ssize_t
_PyDict_SizeOf(PyDictObject *mp)
{
Py_ssize_t size, res;
@@ -2570,7 +2570,7 @@ _PyDict_SizeOf(PyDictObject *mp)
in the type object. */
if (mp->ma_keys->dk_refcnt == 1)
res += sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry);
- return PyLong_FromSsize_t(res);
+ return res;
}
Py_ssize_t
@@ -2579,6 +2579,12 @@ _PyDict_KeysSize(PyDictKeysObject *keys)
return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry);
}
+PyObject *
+dict_sizeof(PyDictObject *mp)
+{
+ return PyLong_FromSsize_t(_PyDict_SizeOf(mp));
+}
+
PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
PyDoc_STRVAR(sizeof__doc__,
@@ -2626,7 +2632,7 @@ static PyMethodDef mapp_methods[] = {
DICT___CONTAINS___METHODDEF
{"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST,
getitem__doc__},
- {"__sizeof__", (PyCFunction)_PyDict_SizeOf, METH_NOARGS,
+ {"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS,
sizeof__doc__},
{"get", (PyCFunction)dict_get, METH_VARARGS,
get__doc__},
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index 4e51f4d..c15b408 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -940,27 +940,7 @@ PyDoc_STRVAR(odict_sizeof__doc__, "");
static PyObject *
odict_sizeof(PyODictObject *od)
{
- PyObject *pylong;
- Py_ssize_t res, temp;
-
- pylong = _PyDict_SizeOf((PyDictObject *)od);
- if (pylong == NULL)
- return NULL;
- res = PyLong_AsSsize_t(pylong);
- Py_DECREF(pylong);
- if (res == -1 && PyErr_Occurred())
- return NULL;
-
- /* instance dict */
- pylong = _PyDict_SizeOf((PyDictObject *)od->od_inst_dict);
- if (pylong == NULL)
- return NULL;
- temp = PyLong_AsSsize_t(pylong);
- Py_DECREF(pylong);
- if (temp == -1 && PyErr_Occurred())
- return NULL;
- res += temp;
-
+ Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
res += sizeof(_ODictNode *) * _odict_FAST_SIZE(od); /* od_fast_nodes */
if (!_odict_EMPTY(od)) {
res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */