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

Skip to content

Commit 0ce7a3a

Browse files
Issue #25914: Fixed and simplified OrderedDict.__sizeof__.
1 parent 5af8564 commit 0ce7a3a

5 files changed

Lines changed: 45 additions & 25 deletions

File tree

Include/dictobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused);
9898
PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp);
9999
PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp);
100100
Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys);
101-
PyObject *_PyDict_SizeOf(PyDictObject *);
101+
Py_ssize_t _PyDict_SizeOf(PyDictObject *);
102102
PyObject *_PyDict_Pop(PyDictObject *, PyObject *, PyObject *);
103103
PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *);
104104
#define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL)

Lib/test/test_ordered_dict.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import copy
33
import pickle
44
from random import randrange, shuffle
5+
import struct
56
import sys
67
import unittest
78
from collections.abc import MutableMapping
@@ -596,6 +597,37 @@ class CPythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
596597

597598
module = c_coll
598599
OrderedDict = c_coll.OrderedDict
600+
check_sizeof = support.check_sizeof
601+
602+
@support.cpython_only
603+
def test_sizeof_exact(self):
604+
OrderedDict = self.OrderedDict
605+
calcsize = struct.calcsize
606+
size = support.calcobjsize
607+
check = self.check_sizeof
608+
609+
basicsize = size('n2P' + '3PnPn2P') + calcsize('2nPn')
610+
entrysize = calcsize('n2P') + calcsize('P')
611+
nodesize = calcsize('Pn2P')
612+
613+
od = OrderedDict()
614+
check(od, basicsize + 8*entrysize)
615+
od.x = 1
616+
check(od, basicsize + 8*entrysize)
617+
od.update([(i, i) for i in range(3)])
618+
check(od, basicsize + 8*entrysize + 3*nodesize)
619+
od.update([(i, i) for i in range(3, 10)])
620+
check(od, basicsize + 16*entrysize + 10*nodesize)
621+
622+
check(od.keys(), size('P'))
623+
check(od.items(), size('P'))
624+
check(od.values(), size('P'))
625+
626+
itersize = size('iP2n2P')
627+
check(iter(od), itersize)
628+
check(iter(od.keys()), itersize)
629+
check(iter(od.items()), itersize)
630+
check(iter(od.values()), itersize)
599631

600632
def test_key_change_during_iteration(self):
601633
OrderedDict = self.OrderedDict

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ Core and Builtins
2828
Library
2929
-------
3030

31+
- Issue #25914: Fixed and simplified OrderedDict.__sizeof__.
32+
3133
- Issue #25902: Fixed various refcount issues in ElementTree iteration.
3234

3335
- Issue #25717: Restore the previous behaviour of tolerating most fstat()

Objects/dictobject.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,7 +2554,7 @@ dict_tp_clear(PyObject *op)
25542554

25552555
static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
25562556

2557-
PyObject *
2557+
Py_ssize_t
25582558
_PyDict_SizeOf(PyDictObject *mp)
25592559
{
25602560
Py_ssize_t size, res;
@@ -2567,7 +2567,7 @@ _PyDict_SizeOf(PyDictObject *mp)
25672567
in the type object. */
25682568
if (mp->ma_keys->dk_refcnt == 1)
25692569
res += sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry);
2570-
return PyLong_FromSsize_t(res);
2570+
return res;
25712571
}
25722572

25732573
Py_ssize_t
@@ -2576,6 +2576,12 @@ _PyDict_KeysSize(PyDictKeysObject *keys)
25762576
return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry);
25772577
}
25782578

2579+
PyObject *
2580+
dict_sizeof(PyDictObject *mp)
2581+
{
2582+
return PyLong_FromSsize_t(_PyDict_SizeOf(mp));
2583+
}
2584+
25792585
PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
25802586

25812587
PyDoc_STRVAR(sizeof__doc__,
@@ -2623,7 +2629,7 @@ static PyMethodDef mapp_methods[] = {
26232629
DICT___CONTAINS___METHODDEF
26242630
{"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST,
26252631
getitem__doc__},
2626-
{"__sizeof__", (PyCFunction)_PyDict_SizeOf, METH_NOARGS,
2632+
{"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS,
26272633
sizeof__doc__},
26282634
{"get", (PyCFunction)dict_get, METH_VARARGS,
26292635
get__doc__},

Objects/odictobject.c

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -940,27 +940,7 @@ PyDoc_STRVAR(odict_sizeof__doc__, "");
940940
static PyObject *
941941
odict_sizeof(PyODictObject *od)
942942
{
943-
PyObject *pylong;
944-
Py_ssize_t res, temp;
945-
946-
pylong = _PyDict_SizeOf((PyDictObject *)od);
947-
if (pylong == NULL)
948-
return NULL;
949-
res = PyLong_AsSsize_t(pylong);
950-
Py_DECREF(pylong);
951-
if (res == -1 && PyErr_Occurred())
952-
return NULL;
953-
954-
/* instance dict */
955-
pylong = _PyDict_SizeOf((PyDictObject *)od->od_inst_dict);
956-
if (pylong == NULL)
957-
return NULL;
958-
temp = PyLong_AsSsize_t(pylong);
959-
Py_DECREF(pylong);
960-
if (temp == -1 && PyErr_Occurred())
961-
return NULL;
962-
res += temp;
963-
943+
Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
964944
res += sizeof(_ODictNode *) * _odict_FAST_SIZE(od); /* od_fast_nodes */
965945
if (!_odict_EMPTY(od)) {
966946
res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */

0 commit comments

Comments
 (0)