Skip to content

Commit c345b90

Browse files
committed
Fix __sizeof__ for subclasses of int
1 parent 84483aa commit c345b90

File tree

3 files changed

+42
-7
lines changed

3 files changed

+42
-7
lines changed

Lib/test/test_long.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,5 +1601,44 @@ def test_square(self):
16011601
self.assertEqual(n**2,
16021602
(1 << (2 * bitlen)) - (1 << (bitlen + 1)) + 1)
16031603

1604+
def test___sizeof__(self):
1605+
self.assertEqual(int.__itemsize__, sys.int_info.sizeof_digit)
1606+
1607+
# Pairs (test_value, number of allocated digits)
1608+
test_values = [
1609+
# We always allocate space for at least one digit, even for
1610+
# a value of zero; sys.getsizeof should reflect that.
1611+
(0, 1),
1612+
(1, 1),
1613+
(-1, 1),
1614+
(BASE-1, 1),
1615+
(1-BASE, 1),
1616+
(BASE, 2),
1617+
(-BASE, 2),
1618+
(BASE*BASE - 1, 2),
1619+
(BASE*BASE, 3),
1620+
]
1621+
1622+
for value, ndigits in test_values:
1623+
with self.subTest(value):
1624+
self.assertEqual(
1625+
value.__sizeof__(),
1626+
int.__basicsize__ + int.__itemsize__ * ndigits
1627+
)
1628+
1629+
# Same test for a subclass of int.
1630+
class MyInt(int):
1631+
pass
1632+
1633+
self.assertEqual(MyInt.__itemsize__, sys.int_info.sizeof_digit)
1634+
1635+
for value, ndigits in test_values:
1636+
with self.subTest(value):
1637+
self.assertEqual(
1638+
MyInt(value).__sizeof__(),
1639+
MyInt.__basicsize__ + MyInt.__itemsize__ * ndigits
1640+
)
1641+
1642+
16041643
if __name__ == "__main__":
16051644
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix :func:`sys.getsizeof` reporting for `int` subclasses.

Objects/longobject.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5882,13 +5882,8 @@ static Py_ssize_t
58825882
int___sizeof___impl(PyObject *self)
58835883
/*[clinic end generated code: output=3303f008eaa6a0a5 input=9b51620c76fc4507]*/
58845884
{
5885-
Py_ssize_t res;
5886-
5887-
res = offsetof(PyLongObject, ob_digit)
5888-
/* using Py_MAX(..., 1) because we always allocate space for at least
5889-
one digit, even though the integer zero has a Py_SIZE of 0 */
5890-
+ Py_MAX(Py_ABS(Py_SIZE(self)), 1)*sizeof(digit);
5891-
return res;
5885+
Py_ssize_t ndigits = Py_MAX(Py_ABS(Py_SIZE(self)), 1);
5886+
return Py_TYPE(self)->tp_basicsize + Py_TYPE(self)->tp_itemsize * ndigits;
58925887
}
58935888

58945889
/*[clinic input]

0 commit comments

Comments
 (0)