Index: Doc/lib/libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.162 diff -c -r1.162 libstdtypes.tex *** Doc/lib/libstdtypes.tex 7 Aug 2004 16:41:34 -0000 1.162 --- Doc/lib/libstdtypes.tex 7 Aug 2004 16:56:16 -0000 *************** *** 1682,1706 **** the function), but the implementation is different, hence the different object types. ! The implementation adds two special read-only attributes: ! \code{\var{f}.func_code} is a function's \dfn{code ! object}\obindex{code} (see below) and \code{\var{f}.func_globals} is ! the dictionary used as the function's global namespace (this is the ! same as \code{\var{m}.__dict__} where \var{m} is the module in which ! the function \var{f} was defined). ! ! Function objects also support getting and setting arbitrary ! attributes, which can be used, for example, to attach metadata to ! functions. Regular attribute dot-notation is used to get and set such ! attributes. \emph{Note that the current implementation only supports ! function attributes on user-defined functions. Function attributes on ! built-in functions may be supported in the future.} ! ! Functions have another special attribute \code{\var{f}.__dict__} ! (a.k.a. \code{\var{f}.func_dict}) which contains the namespace used to ! support function attributes. \code{__dict__} and \code{func_dict} can ! be accessed directly or set to a dictionary object. A function's ! dictionary cannot be deleted. \subsubsection{Methods \label{typesmethods}} \obindex{method} --- 1682,1689 ---- the function), but the implementation is different, hence the different object types. ! See the \citetitle[../ref/ref.html]{Python Reference Manual} for more ! information. \subsubsection{Methods \label{typesmethods}} \obindex{method} Index: Doc/ref/ref3.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref3.tex,v retrieving revision 1.120 diff -c -r1.120 ref3.tex *** Doc/ref/ref3.tex 29 Jun 2004 04:14:02 -0000 1.120 --- Doc/ref/ref3.tex 7 Aug 2004 16:56:16 -0000 *************** *** 433,460 **** \obindex{function} \obindex{user-defined function} ! Special attributes: \member{func_doc} or \member{__doc__} is the ! function's documentation string, or \code{None} if unavailable; ! \member{func_name} or \member{__name__} is the function's name; ! \member{__module__} is the name of the module the function was defined ! in, or \code{None} if unavailable; ! \member{func_defaults} is a tuple containing default argument values for ! those arguments that have defaults, or \code{None} if no arguments ! have a default value; \member{func_code} is the code object representing ! the compiled function body; \member{func_globals} is (a reference to) ! the dictionary that holds the function's global variables --- it ! defines the global namespace of the module in which the function was ! defined; \member{func_dict} or \member{__dict__} contains the ! namespace supporting arbitrary function attributes; ! \member{func_closure} is \code{None} or a tuple of cells that contain ! bindings for the function's free variables. ! ! Of these, \member{func_code}, \member{func_defaults}, ! \member{func_doc}/\member{__doc__}, and ! \member{func_dict}/\member{__dict__} may be writable; the ! others can never be changed. Additional information about a ! function's definition can be retrieved from its code object; see the ! description of internal types below. \withsubitem{(function attribute)}{ \ttindex{func_doc} --- 433,485 ---- \obindex{function} \obindex{user-defined function} ! Special attributes: ! ! \begin{tableiii}{lll}{member}{Attribute}{Meaning}{} ! \lineiii{func_doc}{The function's documentation string, or ! \code{None} if unavailable}{Writable} ! ! \lineiii{__doc__}{Another way of spelling ! \member{func_doc}}{Writable} ! ! \lineiii{func_name}{The function's name}{Writable} ! ! \lineiii{__name__}{Another way of spelling ! \member{func_name}}{Writable} ! ! \lineiii{__module__}{The name of the module the function was defined ! in, or \code{None} if unavailable.}{Writable} ! ! \lineiii{func_defaults}{Atuple containing default argument values ! for those arguments that have defaults, or \code{None} if no ! arguments have a default value}{Writable} ! ! \lineiii{func_code}{The code object representing the compiled ! function body.}{Writable} ! ! \lineiii{func_globals}{A reference to the dictionary that holds the ! function's global variables --- the global namespace of the module ! in which the function was defined.}{Read-only} ! ! \lineiii{func_dict}{Contains the namespace supporting arbitrary ! function attributes.}{Writable} ! ! \lineiii{func_closure}{\code{None} or a tuple of cells that contain ! bindings for the function's free variables.}{Read-only} ! \end{tableiii} ! ! Most of the attributes labelled ``Writable'' check the type of the ! assigned value. ! ! Function objects also support getting and setting arbitrary ! attributes, which can be used, for example, to attach metadata to ! functions. Regular attribute dot-notation is used to get and set such ! attributes. \emph{Note that the current implementation only supports ! function attributes on user-defined functions. Function attributes on ! built-in functions may be supported in the future.} ! ! Additional information about a function's definition can be retrieved ! from its code object; see the description of internal types below. \withsubitem{(function attribute)}{ \ttindex{func_doc} Index: Lib/test/test_funcattrs.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_funcattrs.py,v retrieving revision 1.13 diff -c -r1.13 test_funcattrs.py *** Lib/test/test_funcattrs.py 31 Jan 2003 18:33:17 -0000 1.13 --- Lib/test/test_funcattrs.py 7 Aug 2004 16:56:16 -0000 *************** *** 268,275 **** def f(): pass verify(f.__name__ == "f") verify(f.func_name == "f") ! cantset(f, "func_name", "f") ! cantset(f, "__name__", "f") def test_func_code(): def f(): pass --- 268,282 ---- def f(): pass verify(f.__name__ == "f") verify(f.func_name == "f") ! f.__name__ = "g" ! verify(f.__name__ == "g") ! verify(f.func_name == "g") ! f.func_name = "h" ! verify(f.__name__ == "h") ! verify(f.func_name == "h") ! cantset(f, "func_globals", 1) ! cantset(f, "__name__", 1) ! def test_func_code(): def f(): pass Index: Objects/funcobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/funcobject.c,v retrieving revision 2.65 diff -c -r2.65 funcobject.c *** Objects/funcobject.c 8 Jul 2004 01:48:59 -0000 2.65 --- Objects/funcobject.c 7 Aug 2004 16:56:16 -0000 *************** *** 163,170 **** {"__doc__", T_OBJECT, OFF(func_doc), WRITE_RESTRICTED}, {"func_globals", T_OBJECT, OFF(func_globals), RESTRICTED|READONLY}, - {"func_name", T_OBJECT, OFF(func_name), READONLY}, - {"__name__", T_OBJECT, OFF(func_name), READONLY}, {"__module__", T_OBJECT, OFF(func_module), WRITE_RESTRICTED}, {NULL} /* Sentinel */ }; --- 163,168 ---- *************** *** 250,255 **** --- 248,283 ---- } static PyObject * + func_get_name(PyFunctionObject *op) + { + if (restricted()) + return NULL; + Py_INCREF(op->func_name); + return op->func_name; + } + + static int + func_set_name(PyFunctionObject *op, PyObject *value) + { + PyObject *tmp; + + if (restricted()) + return -1; + /* Not legal to del f.func_name or to set it to anything + * other than a string object. */ + if (value == NULL || !PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "func_name must be set to a string object"); + return -1; + } + tmp = op->func_name; + Py_INCREF(value); + op->func_name = value; + Py_DECREF(tmp); + return 0; + } + + static PyObject * func_get_defaults(PyFunctionObject *op) { if (restricted()) *************** *** 291,296 **** --- 319,326 ---- (setter)func_set_defaults}, {"func_dict", (getter)func_get_dict, (setter)func_set_dict}, {"__dict__", (getter)func_get_dict, (setter)func_set_dict}, + {"func_name", (getter)func_get_name, (setter)func_set_name}, + {"__name__", (getter)func_get_name, (setter)func_set_name}, {NULL} /* Sentinel */ }; *************** *** 416,423 **** static PyObject* func_repr(PyFunctionObject *op) { - if (op->func_name == Py_None) - return PyString_FromFormat("", op); return PyString_FromFormat("", PyString_AsString(op->func_name), op); --- 446,451 ----