[Python-checkins] r64856 - in python/trunk: Doc/library/sys.rst Lib/test/test_sys.py Modules/_testcapimodule.c Python/sysmodule.c

robert.schuppenies python-checkins at python.org
Thu Jul 10 19:13:55 CEST 2008


Author: robert.schuppenies
Date: Thu Jul 10 19:13:55 2008
New Revision: 64856
Log:
Added garbage collector overhead and optional default return value to
sys.getsizeof.
Modified:
 python/trunk/Doc/library/sys.rst
 python/trunk/Lib/test/test_sys.py
 python/trunk/Modules/_testcapimodule.c
 python/trunk/Python/sysmodule.c
Modified: python/trunk/Doc/library/sys.rst
==============================================================================
--- python/trunk/Doc/library/sys.rst	(original)
+++ python/trunk/Doc/library/sys.rst	Thu Jul 10 19:13:55 2008
@@ -393,13 +393,20 @@
 :func:`setrecursionlimit`.
 
 
-.. function:: getsizeof(object)
+.. function:: getsizeof(object[, default])
 
 Return the size of an object in bytes. The object can be any type of
 object. All built-in objects will return correct results, but this
- does not have to hold true for third-party extensions as it is implementation 
+ does not have to hold true for third-party extensions as it is implementation
 specific.
 
+ The *default* argument allows to define a value which will be returned
+ if the object type does not provide means to retrieve the size and would
+ cause a `TypeError`. 
+
+ func:`getsizeof` calls the object's __sizeof__ method and adds an additional
+ garbage collector overhead if the object is managed by the garbage collector.
+
 .. versionadded:: 2.6
 
 
Modified: python/trunk/Lib/test/test_sys.py
==============================================================================
--- python/trunk/Lib/test/test_sys.py	(original)
+++ python/trunk/Lib/test/test_sys.py	Thu Jul 10 19:13:55 2008
@@ -389,6 +389,9 @@
 
 class SizeofTest(unittest.TestCase):
 
+ TPFLAGS_HAVE_GC = 1<<14
+ TPFLAGS_HEAPTYPE = 1L<<9
+
 def setUp(self):
 self.c = len(struct.pack('c', ' '))
 self.H = len(struct.pack('H', 0))
@@ -402,6 +405,8 @@
 if hasattr(sys, "gettotalrefcount"):
 self.header += '2P'
 self.vheader += '2P'
+ import _testcapi
+ self.gc_headsize = _testcapi.SIZEOF_PYGC_HEAD
 self.file = open(test.test_support.TESTFN, 'wb')
 
 def tearDown(self):
@@ -410,6 +415,9 @@
 
 def check_sizeof(self, o, size):
 result = sys.getsizeof(o)
+ if ((type(o) == type) and (o.__flags__ & self.TPFLAGS_HEAPTYPE) or\
+ ((type(o) != type) and (type(o).__flags__ & self.TPFLAGS_HAVE_GC))):
+ size += self.gc_headsize
 msg = 'wrong size for %s: got %d, expected %d' \
 % (type(o), result, size)
 self.assertEqual(result, size, msg)
@@ -423,6 +431,21 @@
 """
 return struct.calcsize(fmt + '0P')
 
+ def test_gc_head_size(self):
+ # Check that the gc header size is added to objects tracked by the gc.
+ h = self.header
+ size = self.calcsize
+ gc_header_size = self.gc_headsize
+ # bool objects are not gc tracked
+ self.assertEqual(sys.getsizeof(True), size(h + 'l'))
+ # but lists are
+ self.assertEqual(sys.getsizeof([]), size(h + 'P PP') + gc_header_size)
+
+ def test_default(self):
+ h = self.header
+ size = self.calcsize
+ self.assertEqual(sys.getsizeof(True, -1), size(h + 'l'))
+
 def test_objecttypes(self):
 # check all types defined in Objects/
 h = self.header
Modified: python/trunk/Modules/_testcapimodule.c
==============================================================================
--- python/trunk/Modules/_testcapimodule.c	(original)
+++ python/trunk/Modules/_testcapimodule.c	Thu Jul 10 19:13:55 2008
@@ -967,6 +967,7 @@
 	PyModule_AddObject(m, "ULLONG_MAX", PyLong_FromUnsignedLongLong(PY_ULLONG_MAX));
 	PyModule_AddObject(m, "PY_SSIZE_T_MAX", PyInt_FromSsize_t(PY_SSIZE_T_MAX));
 	PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyInt_FromSsize_t(PY_SSIZE_T_MIN));
+	PyModule_AddObject(m, "SIZEOF_PYGC_HEAD", PyInt_FromSsize_t(sizeof(PyGC_Head)));
 
 	TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
 	Py_INCREF(TestError);
Modified: python/trunk/Python/sysmodule.c
==============================================================================
--- python/trunk/Python/sysmodule.c	(original)
+++ python/trunk/Python/sysmodule.c	Thu Jul 10 19:13:55 2008
@@ -640,9 +640,16 @@
 #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", 0};
+	PyObject *o, *dflt = NULL;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof",
+					 kwlist, &o, &dflt))
+		return NULL;
 
 	/* Initialize static variable needed by _PyType_Lookup */
 	if (str__sizeof__ == NULL) {
@@ -651,29 +658,54 @@
 			return 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(args)) < 0)
+	if (PyType_Ready(Py_TYPE(o)) < 0)
 		return NULL;
 
 	/* Instance of old-style class */
-	if (PyInstance_Check(args))
-		return PyInt_FromSsize_t(PyInstance_Type.tp_basicsize);
+	if (PyInstance_Check(o))
+		res = PyInt_FromSsize_t(PyInstance_Type.tp_basicsize);
 	/* all other objects */
 	else {
-		PyObject *method = _PyType_Lookup(Py_TYPE(args),
+		PyObject *method = _PyType_Lookup(Py_TYPE(o),
 						 str__sizeof__);
-		if (method == NULL) {
+		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);
+				 Py_TYPE(o)->tp_name);
+		else
+			res = PyObject_CallFunctionObjArgs(method, o, NULL);
+	}
+	
+	/* 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)
+		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;
 }
 
 PyDoc_STRVAR(getsizeof_doc,
-"getsizeof(object) -> int\n\
+"getsizeof(object, default) -> int\n\
 \n\
 Return the size of object in bytes.");
 
@@ -868,7 +900,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,


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /