| Index: Python/sysmodule.c |
| =================================================================== |
| --- Python/sysmodule.c (revision 64518) |
| +++ Python/sysmodule.c (working copy) |
| @@ -640,10 +640,18 @@ |
| #endif /* USE_MALLOPT */ |
| static PyObject * |
| -sys_getsizeof(PyObject *self, PyObject *args) |
| +sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds) |
| { |
| - static PyObject * str__sizeof__ = NULL; |
| + PyObject *res = NULL; |
| + static PyObject *str__sizeof__, *gc_head_size = NULL; |
| + static char *kwlist[] = {"object", "default", "gc_head", 0}; |
| + PyObject *o, *dflt = NULL; |
| + int gc_head; |
| + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:getsizeof", |
| + kwlist, &o, &dflt, &gc_head)) |
| + return NULL; |
| + |
| /* Initialize static variable needed by _PyType_Lookup */ |
| if (str__sizeof__ == NULL) { |
| str__sizeof__ = PyString_InternFromString("__sizeof__"); |
| @@ -651,30 +659,54 @@ |
| return NULL; |
| } |
| - /* Type objects */ |
| - if (PyType_Check(args)){ |
| - PyObject *method = _PyType_Lookup(Py_TYPE(args), |
| - str__sizeof__); |
| - if (method == NULL) { |
| + /* Initialize static variable for GC head size */ |
| + if (gc_head_size == NULL) { |
| + gc_head_size = PyInt_FromSsize_t(sizeof(PyGC_Head)); |
| + if (gc_head_size == NULL) |
| + return NULL; |
| + } |
| + |
| + /* Make sure the type is initialized. float gets initialized late */ |
| + if (PyType_Ready(Py_TYPE(o)) < 0) |
| + return NULL; |
| + |
| + /* non-type objects */ |
| + else if (!PyType_Check(o)) |
| + res = PyObject_CallMethod(o, "__sizeof__", NULL); |
| + /* type objects and objects which do not have the __sizeof__ attribute */ |
| + if (PyType_Check(o) || |
| + (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError))) { |
| + PyObject *method = _PyType_Lookup(Py_TYPE(o), str__sizeof__); |
| + if (method == NULL) |
| PyErr_Format(PyExc_TypeError, |
| "Type %.100s doesn't define __sizeof__", |
| - Py_TYPE(args)->tp_name); |
| - return NULL; |
| - } |
| - return PyObject_CallFunctionObjArgs(method, args, NULL); |
| - } |
| - /* Instance of old-style classes */ |
| - else if (PyInstance_Check(args)) |
| - return PyInt_FromSsize_t(PyInstance_Type.tp_basicsize); |
| - /* Old-style classes */ |
| - else if (PyClass_Check(args)) |
| - return PyInt_FromSsize_t(PyClass_Type.tp_basicsize); |
| - else |
| - return PyObject_CallMethod(args, "__sizeof__", NULL); |
| + Py_TYPE(o)->tp_name); |
| + else |
| + res = PyObject_CallFunctionObjArgs(method, o, NULL); |
| + } |
| + |
| + /* failed. is default value is given? */ |
|
Martin v. Löwis
2008/07/07 05:24:06
"Has a default value been given" or "Was a default
|
| + if ((res == NULL) && (dflt != NULL) && |
| + PyErr_ExceptionMatches(PyExc_TypeError)) |
| + { |
| + PyErr_Clear(); |
| + Py_INCREF(dflt); |
| + return dflt; |
| + } |
| + else if (res == NULL) |
| + return res; |
| + |
| + /* add gc_head size if object is tracked by gc */ |
| + if (gc_head && PyObject_IS_GC(o)) { |
| + PyObject *tmp = res; |
| + res = PyNumber_Add(tmp, gc_head_size); |
| + Py_DECREF(tmp); |
| + } |
| + return res; |
| } |
| PyDoc_STRVAR(getsizeof_doc, |
| -"getsizeof(object) -> int\n\ |
| +"getsizeof(object, default, gc_head=True) -> int\n\ |
| \n\ |
| Return the size of object in bytes."); |
| @@ -889,7 +921,8 @@ |
| {"getrefcount", (PyCFunction)sys_getrefcount, METH_O, getrefcount_doc}, |
| {"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_NOARGS, |
| getrecursionlimit_doc}, |
| - {"getsizeof", sys_getsizeof, METH_O, getsizeof_doc}, |
| + {"getsizeof", (PyCFunction)sys_getsizeof, |
| + METH_VARARGS | METH_KEYWORDS, getsizeof_doc}, |
| {"_getframe", sys_getframe, METH_VARARGS, getframe_doc}, |
| #ifdef MS_WINDOWS |
| {"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS, |