# weakcallableproxy
check(weakref.proxy(int), size('2Pn2P'))
+ def check_slots(self, obj, base, extra):
+ expected = sys.getsizeof(base) + struct.calcsize(extra)
+ if gc.is_tracked(obj) and not gc.is_tracked(base):
+ expected += struct.calcsize('2Pn') # PyGC_Head
+ self.assertEqual(sys.getsizeof(obj), expected)
+
+ def test_slots(self):
+ # check all subclassable types defined in Objects/ that allow
+ # non-empty __slots__
+ check = self.check_slots
+ class BA(bytearray):
+ __slots__ = 'a', 'b', 'c'
+ check(BA(), bytearray(), '3P')
+ class D(dict):
+ __slots__ = 'a', 'b', 'c'
+ check(D(x=[]), {'x': []}, '3P')
+ class L(list):
+ __slots__ = 'a', 'b', 'c'
+ check(L(), [], '3P')
+ class S(set):
+ __slots__ = 'a', 'b', 'c'
+ check(S(), set(), '3P')
+ class FS(frozenset):
+ __slots__ = 'a', 'b', 'c'
+ check(FS(), frozenset(), '3P')
+ from collections import OrderedDict
+ class OD(OrderedDict):
+ __slots__ = 'a', 'b', 'c'
+ check(OD(x=[]), OrderedDict(x=[]), '3P')
+
def test_pythontypes(self):
# check all types defined in Python/
size = test.support.calcobjsize
Core and Builtins
-----------------
+- Issue #25421: __sizeof__ methods of builtin types now use dynamic basic size.
+ This allows sys.getsize() to work correctly with their subclasses with
+ __slots__ defined.
+
- Issue #25709: Fixed problem with in-place string concatenation and utf-8 cache.
- Issue #24097: Fixed crash in object.__reduce__() if slot name is freed inside
Py_ssize_t res;
Py_ssize_t blocks;
- res = sizeof(dequeobject);
+ res = _PyObject_SIZE(Py_TYPE(deque));
blocks = (deque->leftindex + Py_SIZE(deque) + BLOCKLEN - 1) / BLOCKLEN;
assert(deque->leftindex + Py_SIZE(deque) - 1 ==
(blocks - 1) * BLOCKLEN + deque->rightindex);
{
Py_ssize_t res;
- res = sizeof(PyDecObject);
+ res = _PyObject_SIZE(Py_TYPE(v));
if (mpd_isdynamic_data(MPD(v))) {
res += MPD(v)->alloc * sizeof(mpd_uint_t);
}
_elementtree_Element___sizeof___impl(ElementObject *self)
/*[clinic end generated code: output=bf73867721008000 input=70f4b323d55a17c1]*/
{
- Py_ssize_t result = sizeof(ElementObject);
+ Py_ssize_t result = _PyObject_SIZE(Py_TYPE(self));
if (self->extra) {
result += sizeof(ElementObjectExtra);
if (self->extra->children != self->extra->_children)
{
Py_ssize_t res;
- res = sizeof(buffered);
+ res = _PyObject_SIZE(Py_TYPE(self));
if (self->buffer)
res += self->buffer_size;
return PyLong_FromSsize_t(res);
{
Py_ssize_t res;
- res = sizeof(bytesio);
+ res = _PyObject_SIZE(Py_TYPE(self));
if (self->buf && !SHARED_BUF(self))
res += _PySys_GetSizeOf(self->buf);
return PyLong_FromSsize_t(res);
{
Py_ssize_t res, s;
- res = sizeof(PicklerObject);
+ res = _PyObject_SIZE(Py_TYPE(self));
if (self->memo != NULL) {
res += sizeof(PyMemoTable);
res += self->memo->mt_allocated * sizeof(PyMemoEntry);
{
Py_ssize_t res;
- res = sizeof(UnpicklerObject);
+ res = _PyObject_SIZE(Py_TYPE(self));
if (self->memo != NULL)
res += self->memo_size * sizeof(PyObject *);
if (self->marks != NULL)
Py_ssize_t size;
formatcode *code;
- size = sizeof(PyStructObject) + sizeof(formatcode);
+ size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode);
for (code = self->s_codes; code->fmtdef != NULL; code++)
size += sizeof(formatcode);
return PyLong_FromSsize_t(size);
/*[clinic end generated code: output=d8e1c61ebbe3eaed input=805586565bf2b3c6]*/
{
Py_ssize_t res;
- res = sizeof(arrayobject) + self->allocated * self->ob_descr->itemsize;
+ res = _PyObject_SIZE(Py_TYPE(self)) + self->allocated * self->ob_descr->itemsize;
return PyLong_FromSsize_t(res);
}
{
Py_ssize_t res;
- res = sizeof(productobject);
+ res = _PyObject_SIZE(Py_TYPE(lz));
res += PyTuple_GET_SIZE(lz->pools) * sizeof(Py_ssize_t);
return PyLong_FromSsize_t(res);
}
{
Py_ssize_t res;
- res = sizeof(combinationsobject);
+ res = _PyObject_SIZE(Py_TYPE(co));
res += co->r * sizeof(Py_ssize_t);
return PyLong_FromSsize_t(res);
}
{
Py_ssize_t res;
- res = sizeof(cwrobject);
+ res = _PyObject_SIZE(Py_TYPE(co));
res += co->r * sizeof(Py_ssize_t);
return PyLong_FromSsize_t(res);
}
{
Py_ssize_t res;
- res = sizeof(permutationsobject);
+ res = _PyObject_SIZE(Py_TYPE(po));
res += PyTuple_GET_SIZE(po->pool) * sizeof(Py_ssize_t);
res += po->r * sizeof(Py_ssize_t);
return PyLong_FromSsize_t(res);
{
Py_ssize_t res;
- res = sizeof(mmap_object);
+ res = _PyObject_SIZE(Py_TYPE(self));
if (self->tagname)
res += strlen(self->tagname) + 1;
return PyLong_FromSsize_t(res);
{
Py_ssize_t res;
- res = sizeof(PyST_Object) + _PyNode_SizeOf(st->st_node);
+ res = _PyObject_SIZE(Py_TYPE(st)) + _PyNode_SizeOf(st->st_node);
return PyLong_FromSsize_t(res);
}
{
Py_ssize_t res;
- res = sizeof(PyByteArrayObject) + self->ob_alloc * sizeof(char);
+ res = _PyObject_SIZE(Py_TYPE(self)) + self->ob_alloc * sizeof(char);
return PyLong_FromSsize_t(res);
}
{
Py_ssize_t res;
- res = sizeof(PyCodeObject);
+ res = _PyObject_SIZE(Py_TYPE(co));
if (co->co_cell2arg != NULL && co->co_cellvars != NULL)
res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(unsigned char);
return PyLong_FromSsize_t(res);
Py_ssize_t size, res;
size = DK_SIZE(mp->ma_keys);
- res = sizeof(PyDictObject);
+ res = _PyObject_SIZE(Py_TYPE(mp));
if (mp->ma_values)
res += size * sizeof(PyObject*);
/* If the dictionary is split, the keys portion is accounted-for
{
Py_ssize_t res;
- res = sizeof(PyListObject) + self->allocated * sizeof(void*);
+ res = _PyObject_SIZE(Py_TYPE(self)) + self->allocated * sizeof(void*);
return PyLong_FromSsize_t(res);
}
if (res == -1 && PyErr_Occurred())
return NULL;
- res += sizeof(PyODictObject) - sizeof(PyDictObject);
-
/* instance dict */
pylong = _PyDict_SizeOf((PyDictObject *)od->od_inst_dict);
if (pylong == NULL)
{
Py_ssize_t res;
- res = sizeof(PySetObject);
+ res = _PyObject_SIZE(Py_TYPE(so));
if (so->table != so->smalltable)
res = res + (so->mask + 1) * sizeof(setentry);
return PyLong_FromSsize_t(res);