Update of /cvsroot/python/python/dist/src/Include In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19812/Include Modified Files: cellobject.h funcobject.h intobject.h listobject.h methodobject.h rangeobject.h setobject.h sliceobject.h stringobject.h tupleobject.h Log Message: Wrote down the invariants of some common objects whose structure is exposed in header files. Fixed a few comments in these headers. As we might have expected, writing down invariants systematically exposed a (minor) bug. In this case, function objects have a writeable func_code attribute, which could be set to code objects with the wrong number of free variables. Calling the resulting function segfaulted the interpreter. Added a corresponding test. Index: cellobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/cellobject.h,v retrieving revision 2.3 retrieving revision 2.4 diff -u -d -r2.3 -r2.4 --- cellobject.h 12 Aug 2002 07:21:56 -0000 2.3 +++ cellobject.h 28 Oct 2004 16:31:57 -0000 2.4 @@ -8,7 +8,7 @@ typedef struct { PyObject_HEAD - PyObject *ob_ref; + PyObject *ob_ref; /* Content of the cell or NULL when empty */ } PyCellObject; PyAPI_DATA(PyTypeObject) PyCell_Type; Index: funcobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/funcobject.h,v retrieving revision 2.26 retrieving revision 2.27 diff -u -d -r2.26 -r2.27 --- funcobject.h 31 Jan 2003 18:33:15 -0000 2.26 +++ funcobject.h 28 Oct 2004 16:31:57 -0000 2.27 @@ -7,17 +7,34 @@ extern "C" { #endif +/* Function objects and code objects should not be confused with each other: + * + * Function objects are created by the execution of the 'def' statement. + * They reference a code object in their func_code attribute, which is a + * purely syntactic object, i.e. nothing more than a compiled version of some + * source code lines. There is one code object per source code "fragment", + * but each code object can be referenced by zero or many function objects + * depending only on how many times the 'def' statement in the source was + * executed so far. + */ + typedef struct { PyObject_HEAD - PyObject *func_code; - PyObject *func_globals; - PyObject *func_defaults; - PyObject *func_closure; - PyObject *func_doc; - PyObject *func_name; - PyObject *func_dict; - PyObject *func_weakreflist; - PyObject *func_module; + PyObject *func_code; /* A code object */ + PyObject *func_globals; /* A dictionary (other mappings won't do) */ + PyObject *func_defaults; /* NULL or a tuple */ + PyObject *func_closure; /* NULL or a tuple of cell objects */ + PyObject *func_doc; /* The __doc__ attribute, can be anything */ + PyObject *func_name; /* The __name__ attribute, a string object */ + PyObject *func_dict; /* The __dict__ attribute, a dict or NULL */ + PyObject *func_weakreflist; /* List of weak references */ + PyObject *func_module; /* The __module__ attribute, can be anything */ + + /* Invariant: + * func_closure contains the bindings for func_code->co_freevars, so + * PyTuple_Size(func_closure) == PyCode_GetNumFree(func_code) + * (func_closure may be NULL if PyCode_GetNumFree(func_code) == 0). + */ } PyFunctionObject; PyAPI_DATA(PyTypeObject) PyFunction_Type; Index: intobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/intobject.h,v retrieving revision 2.30 retrieving revision 2.31 diff -u -d -r2.30 -r2.31 --- intobject.h 17 Apr 2003 18:55:11 -0000 2.30 +++ intobject.h 28 Oct 2004 16:31:58 -0000 2.31 @@ -11,7 +11,7 @@ None of the functions should be applied to nil objects. The type PyIntObject is (unfortunately) exposed here so we can declare -_Py_TrueStruct and _Py_ZeroStruct below; don't use this. +_Py_TrueStruct and _Py_ZeroStruct in boolobject.h; don't use this. */ #ifndef Py_INTOBJECT_H Index: listobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/listobject.h,v retrieving revision 2.32 retrieving revision 2.33 diff -u -d -r2.32 -r2.33 --- listobject.h 1 Aug 2004 22:45:27 -0000 2.32 +++ listobject.h 28 Oct 2004 16:31:58 -0000 2.33 @@ -31,6 +31,9 @@ * len(list) == ob_size * ob_item == NULL implies ob_size == allocated == 0 * list.sort() temporarily sets allocated to -1 to detect mutations. + * + * Items must normally not be NULL, except during construction when + * the list is not yet visible outside the function that builds it. */ int allocated; } PyListObject; Index: methodobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/methodobject.h,v retrieving revision 2.27 retrieving revision 2.28 diff -u -d -r2.27 -r2.28 --- methodobject.h 13 Dec 2003 11:26:10 -0000 2.27 +++ methodobject.h 28 Oct 2004 16:31:58 -0000 2.28 @@ -7,6 +7,10 @@ extern "C" { #endif +/* This is about the type 'builtin_function_or_method', + not Python methods in user-defined classes. See classobject.h + for the latter. */ + PyAPI_DATA(PyTypeObject) PyCFunction_Type; #define PyCFunction_Check(op) ((op)->ob_type == &PyCFunction_Type) @@ -31,10 +35,11 @@ PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *); struct PyMethodDef { - char *ml_name; - PyCFunction ml_meth; - int ml_flags; - char *ml_doc; + char *ml_name; /* The name of the built-in function/method */ + PyCFunction ml_meth; /* The C function that implements it */ + int ml_flags; /* Combination of METH_xxx flags, which mostly + describe the args expected by the C func */ + char *ml_doc; /* The __doc__ attribute, or NULL */ }; typedef struct PyMethodDef PyMethodDef; @@ -75,9 +80,9 @@ typedef struct { PyObject_HEAD - PyMethodDef *m_ml; - PyObject *m_self; - PyObject *m_module; + PyMethodDef *m_ml; /* Description of the C function to call */ + PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */ + PyObject *m_module; /* The __module__ attribute, can be anything */ } PyCFunctionObject; #ifdef __cplusplus Index: rangeobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/rangeobject.h,v retrieving revision 2.19 retrieving revision 2.20 diff -u -d -r2.19 -r2.20 --- rangeobject.h 12 Aug 2002 07:21:57 -0000 2.19 +++ rangeobject.h 28 Oct 2004 16:31:58 -0000 2.20 @@ -7,6 +7,9 @@ extern "C" { #endif +/* This is about the type 'xrange', not the built-in function range(), which + returns regular lists. */ + /* A range object represents an integer range. This is an immutable object; a range cannot change its value after creation. Index: setobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/setobject.h,v retrieving revision 2.4 retrieving revision 2.5 diff -u -d -r2.4 -r2.5 --- setobject.h 30 May 2004 07:26:45 -0000 2.4 +++ setobject.h 28 Oct 2004 16:31:59 -0000 2.5 @@ -16,6 +16,14 @@ PyObject *data; long hash; /* only used by frozenset objects */ PyObject *weakreflist; /* List of weak references */ + + /* Invariants: + * data is a dictionary whose values are all True. + * data points to the same dict for the whole life of the set. + * For frozensets only: + * data is immutable. + * hash is the hash of the frozenset or -1 if not computed yet. + */ } PySetObject; PyAPI_DATA(PyTypeObject) PySet_Type; Index: sliceobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/sliceobject.h,v retrieving revision 2.7 retrieving revision 2.8 diff -u -d -r2.7 -r2.8 --- sliceobject.h 12 Aug 2002 07:21:57 -0000 2.7 +++ sliceobject.h 28 Oct 2004 16:31:59 -0000 2.8 @@ -16,12 +16,12 @@ A slice object containing start, stop, and step data members (the names are from range). After much talk with Guido, it was decided to -let these be any arbitrary python type. +let these be any arbitrary python type. Py_None stands for omitted values. */ typedef struct { PyObject_HEAD - PyObject *start, *stop, *step; + PyObject *start, *stop, *step; /* not NULL */ } PySliceObject; PyAPI_DATA(PyTypeObject) PySlice_Type; Index: stringobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/stringobject.h,v retrieving revision 2.39 retrieving revision 2.40 diff -u -d -r2.39 -r2.40 --- stringobject.h 1 Jul 2003 20:15:21 -0000 2.39 +++ stringobject.h 28 Oct 2004 16:31:59 -0000 2.40 @@ -37,6 +37,15 @@ long ob_shash; int ob_sstate; char ob_sval[1]; + + /* Invariants: + * ob_sval contains space for 'ob_size+1' elements. + * ob_sval[ob_size] == 0. + * ob_shash is the hash of the string or -1 if not computed yet. + * ob_sstate != 0 iff the string object is in stringobject.c's + * 'interned' dictionary; in this case the two references + * from 'interned' to this object are *not counted* in ob_refcnt. + */ } PyStringObject; #define SSTATE_NOT_INTERNED 0 Index: tupleobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/tupleobject.h,v retrieving revision 2.29 retrieving revision 2.30 diff -u -d -r2.29 -r2.30 --- tupleobject.h 12 Oct 2003 18:24:33 -0000 2.29 +++ tupleobject.h 28 Oct 2004 16:31:59 -0000 2.30 @@ -8,9 +8,11 @@ #endif /* -Another generally useful object type is an tuple of object pointers. -This is a mutable type: the tuple items can be changed (but not their -number). Out-of-range indices or non-tuple objects are ignored. +Another generally useful object type is a tuple of object pointers. +For Python, this is an immutable type. C code can change the tuple items +(but not their number), and even use tuples are general-purpose arrays of +object references, but in general only brand new tuples should be mutated, +not ones that might already have been exposed to Python code. *** WARNING *** PyTuple_SetItem does not increment the new item's reference count, but does decrement the reference count of the item it replaces, @@ -22,6 +24,11 @@ typedef struct { PyObject_VAR_HEAD PyObject *ob_item[1]; + + /* ob_item contains space for 'ob_size' elements. + * Items must normally not be NULL, except during construction when + * the tuple is not yet visible outside the function that builds it. + */ } PyTupleObject; PyAPI_DATA(PyTypeObject) PyTuple_Type;