Skip to content

Commit 08e4869

Browse files
committed
fix: gh-140025 queue.SimpleQueue.__sizeof__() ignores the underlying data structure
1 parent 025b403 commit 08e4869

File tree

3 files changed

+102
-1
lines changed

3 files changed

+102
-1
lines changed

Lib/test/test_queue.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,60 @@ class C:
10091009
gc_collect() # For PyPy or other GCs.
10101010
self.assertIsNone(wr())
10111011

1012+
def test_sizeof(self):
1013+
# Test that __sizeof__() accounts for underlying data structure
1014+
q = self.q
1015+
1016+
# Get the size of an empty queue
1017+
empty_size = q.__sizeof__()
1018+
self.assertGreater(empty_size, 0, "Empty queue should have non-zero size")
1019+
1020+
# Size should include basic object structure
1021+
# For C implementation, this includes the ring buffer array
1022+
# For Python implementation, this includes the underlying list
1023+
1024+
# Add items within initial capacity (if applicable)
1025+
# For C SimpleQueue, initial capacity is 8 items
1026+
for i in range(8):
1027+
q.put(object())
1028+
1029+
size_after_8 = q.__sizeof__()
1030+
# Size may or may not change depending on implementation
1031+
# C implementation: no change (still within initial ring buffer capacity)
1032+
# Python implementation: may change (list growth)
1033+
1034+
# Add one more item to potentially trigger growth
1035+
q.put(object()) # Now 9 items
1036+
1037+
size_after_9 = q.__sizeof__()
1038+
self.assertGreaterEqual(size_after_9, size_after_8,
1039+
"Size should not decrease when adding items")
1040+
1041+
# Test with a larger number of items
1042+
large_q = self.type2test()
1043+
for i in range(1000):
1044+
large_q.put(object())
1045+
1046+
large_size = large_q.__sizeof__()
1047+
1048+
# For C implementation, size should grow with capacity
1049+
# For Python implementation, __sizeof__ may not account for underlying list
1050+
# (this is a known limitation of the Python implementation)
1051+
if self.__class__.__name__ == 'CSimpleQueueTest':
1052+
# This is the C implementation
1053+
self.assertGreater(large_size, empty_size,
1054+
"C SimpleQueue with many items should be larger than empty queue")
1055+
1056+
# Verify size is reasonable (should be proportional to capacity)
1057+
# For very large queues, size should be significantly larger
1058+
self.assertGreater(large_size, empty_size * 2,
1059+
"Large C SimpleQueue should be at least 2x size of empty queue")
1060+
else:
1061+
# This is the Python implementation
1062+
# The Python implementation doesn't properly implement __sizeof__
1063+
# but we can at least verify it returns a positive number
1064+
self.assertGreater(large_size, 0, "Python SimpleQueue should have positive size")
1065+
10121066

10131067
class PySimpleQueueTest(BaseSimpleQueueTest, unittest.TestCase):
10141068

Modules/_queuemodule.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,24 @@ _queue_SimpleQueue_qsize_impl(simplequeueobject *self)
500500
return RingBuf_Len(&self->buf);
501501
}
502502

503+
/*[clinic input]
504+
_queue.SimpleQueue.__sizeof__ -> Py_ssize_t
505+
506+
Return size of queue in bytes, including underlying data structure.
507+
[clinic start generated code]*/
508+
509+
static Py_ssize_t
510+
_queue_SimpleQueue___sizeof___impl(simplequeueobject *self)
511+
/*[clinic end generated code: output=58ce4e3bbc078fd4 input=7b9d000cdcb71b7d]*/
512+
{
513+
Py_ssize_t size = Py_TYPE(self)->tp_basicsize;
514+
// Add size of the ring buffer items array
515+
size += self->buf.items_cap * sizeof(PyObject *);
516+
return size;
517+
}
518+
519+
520+
503521
static int
504522
queue_traverse(PyObject *m, visitproc visit, void *arg)
505523
{
@@ -534,6 +552,7 @@ static PyMethodDef simplequeue_methods[] = {
534552
_QUEUE_SIMPLEQUEUE_PUT_METHODDEF
535553
_QUEUE_SIMPLEQUEUE_PUT_NOWAIT_METHODDEF
536554
_QUEUE_SIMPLEQUEUE_QSIZE_METHODDEF
555+
_QUEUE_SIMPLEQUEUE___SIZEOF___METHODDEF
537556
{"__class_getitem__", Py_GenericAlias,
538557
METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
539558
{NULL, NULL} /* sentinel */

Modules/clinic/_queuemodule.c.h

Lines changed: 29 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)