diff -r db1b4aab53eb Include/sysmodule.h --- a/Include/sysmodule.h Tue Aug 07 11:57:47 2012 -0700 +++ b/Include/sysmodule.h Tue Aug 14 23:46:46 2012 +0300 @@ -21,6 +21,7 @@ PyAPI_DATA(PyObject *) _PySys_TraceFunc, *_PySys_ProfileFunc; PyAPI_DATA(int) _PySys_CheckInterval; +PyAPI_DATA(PyObject *) _PySys_GetSizeOf(PyObject *); PyAPI_FUNC(void) PySys_ResetWarnOptions(void); PyAPI_FUNC(void) PySys_AddWarnOption(char *); diff -r db1b4aab53eb Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py Tue Aug 07 11:57:47 2012 -0700 +++ b/Lib/test/test_memoryio.py Tue Aug 14 23:46:46 2012 +0300 @@ -12,6 +12,8 @@ import io import _pyio as pyio import pickle +import sys +import os class MemorySeekTestMixin: @@ -697,6 +699,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(b'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 b'', b'\n', b'\r', b'\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 db1b4aab53eb Modules/_io/stringio.c --- a/Modules/_io/stringio.c Tue Aug 07 11:57:47 2012 -0700 +++ b/Modules/_io/stringio.c Tue Aug 14 23:46:46 2012 +0300 @@ -506,6 +506,7 @@ static int stringio_clear(stringio *self) { + Py_CLEAR(self->decoder); Py_CLEAR(self->dict); return 0; } @@ -631,6 +632,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) @@ -823,6 +853,7 @@ {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS}, {"__setstate__", (PyCFunction)stringio_setstate, METH_O}, + {"__sizeof__", (PyCFunction)stringio_sizeof, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; diff -r db1b4aab53eb Python/sysmodule.c --- a/Python/sysmodule.c Tue Aug 07 11:57:47 2012 -0700 +++ b/Python/sysmodule.c Tue Aug 14 23:46:46 2012 +0300 @@ -681,17 +681,11 @@ } #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; - - 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) { @@ -723,15 +717,7 @@ } } - /* Has a default value been given? */ - if ((res == NULL) && (dflt != NULL) && - PyErr_ExceptionMatches(PyExc_TypeError)) - { - PyErr_Clear(); - Py_INCREF(dflt); - return dflt; - } - else if (res == NULL) + if (res == NULL) return res; /* add gc_head size */ @@ -743,6 +729,31 @@ 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)) + { + PyErr_Clear(); + Py_INCREF(dflt); + return dflt; + } + + return res; +} + PyDoc_STRVAR(getsizeof_doc, "getsizeof(object, default) -> int\n\ \n\