diff -r 84899daa4309 Include/sysmodule.h --- a/Include/sysmodule.h Tue Aug 14 18:41:40 2012 +0300 +++ b/Include/sysmodule.h Tue Aug 14 23:50:11 2012 +0300 @@ -22,6 +22,7 @@ #ifndef Py_LIMITED_API PyAPI_DATA(PyObject *) _PySys_TraceFunc, *_PySys_ProfileFunc; +PyAPI_DATA(PyObject *) _PySys_GetSizeOf(PyObject *); #endif PyAPI_FUNC(void) PySys_ResetWarnOptions(void); diff -r 84899daa4309 Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py Tue Aug 14 18:41:40 2012 +0300 +++ b/Lib/test/test_memoryio.py Tue Aug 14 23:50:11 2012 +0300 @@ -9,6 +9,8 @@ import io import _pyio as pyio import pickle +import sys +import os class MemorySeekTestMixin: @@ -712,6 +714,25 @@ memio.close() self.assertRaises(ValueError, memio.__setstate__, ("closed", "", 0, None)) + check_sizeof = support.check_sizeof + + @support.cpython_only + def test_sizeof(self): + basesize = support.calcobjsize('P2PP4c5P') + usize = len('\0'.encode('unicode-internal')) + stdsize = basesize + 2 * usize + sys.getsizeof(os.linesep) + check = self.check_sizeof + self.assertEqual(object.__sizeof__(io.StringIO()), basesize) + check(io.StringIO(), stdsize) + # newline + for newline in '', '\n', '\r', '\r\n': + check(io.StringIO(newline=newline), + basesize + 2 * usize + sys.getsizeof(newline)) + # UCS4 buffer + for c in 'a', '\x80', '\u0100', '\U00010000': + check(io.StringIO(c * 1000), + stdsize + len((c * 1000).encode('unicode-internal'))) + class CStringIOPickleTest(PyStringIOPickleTest): UnsupportedOperation = io.UnsupportedOperation diff -r 84899daa4309 Modules/_io/stringio.c --- a/Modules/_io/stringio.c Tue Aug 14 18:41:40 2012 +0300 +++ b/Modules/_io/stringio.c Tue Aug 14 23:50:11 2012 +0300 @@ -500,6 +500,7 @@ static int stringio_clear(stringio *self) { + Py_CLEAR(self->decoder); Py_CLEAR(self->dict); return 0; } @@ -649,6 +650,35 @@ return 0; } +#define ADD_NUM(res,num) do { \ + PyObject *x = res; \ + PyObject *y = (num); \ + if (x == NULL) \ + return NULL; \ + res = PyNumber_InPlaceAdd(x, y); \ + Py_DECREF(x); \ + if (res == NULL) { \ + Py_DECREF(y); \ + return NULL; \ + } \ + } while (0) + +static PyObject * +stringio_sizeof(stringio *self, void *unused) +{ + PyObject *res; + + res = PyLong_FromSsize_t(sizeof(stringio)); + if (res == NULL) + return NULL; + + if (self->buf) + ADD_NUM(res, PyLong_FromSsize_t(self->buf_size * sizeof(Py_UNICODE))); + if (self->readnl) + ADD_NUM(res, _PySys_GetSizeOf(self->readnl)); + return res; +} + /* Properties and pseudo-properties */ static PyObject * stringio_seekable(stringio *self, PyObject *args) @@ -841,6 +871,7 @@ {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS}, {"__setstate__", (PyCFunction)stringio_setstate, METH_O}, + {"__sizeof__", (PyCFunction)stringio_sizeof, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; diff -r 84899daa4309 Python/sysmodule.c --- a/Python/sysmodule.c Tue Aug 14 18:41:40 2012 +0300 +++ b/Python/sysmodule.c Tue Aug 14 23:50:11 2012 +0300 @@ -807,19 +807,13 @@ } #endif /* USE_MALLOPT */ -static PyObject * -sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds) +PyObject * +_PySys_GetSizeOf(PyObject *o) { PyObject *res = NULL; static PyObject *str__sizeof__ = NULL, *gc_head_size = NULL; - static char *kwlist[] = {"object", "default", 0}; - PyObject *o, *dflt = NULL; PyObject *method; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof", - kwlist, &o, &dflt)) - return NULL; - /* Initialize static variable for GC head size */ if (gc_head_size == NULL) { gc_head_size = PyLong_FromSsize_t(sizeof(PyGC_Head)); @@ -844,6 +838,31 @@ Py_DECREF(method); } + if (res == NULL) + return res; + + /* add gc_head size */ + if (PyObject_IS_GC(o)) { + PyObject *tmp = res; + res = PyNumber_Add(tmp, gc_head_size); + Py_DECREF(tmp); + } + return res; +} + +static PyObject * +sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"object", "default", 0}; + PyObject *res; + PyObject *o, *dflt = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof", + kwlist, &o, &dflt)) + return NULL; + + res = _PySys_GetSizeOf(o); + /* Has a default value been given */ if ((res == NULL) && (dflt != NULL) && PyErr_ExceptionMatches(PyExc_TypeError)) @@ -852,15 +871,7 @@ Py_INCREF(dflt); return dflt; } - else if (res == NULL) - return res; - /* add gc_head size */ - if (PyObject_IS_GC(o)) { - PyObject *tmp = res; - res = PyNumber_Add(tmp, gc_head_size); - Py_DECREF(tmp); - } return res; }