]> granicus.if.org Git - python/commitdiff
This is my patch
authorMichael W. Hudson <mwh@python.net>
Thu, 12 Aug 2004 18:12:44 +0000 (18:12 +0000)
committerMichael W. Hudson <mwh@python.net>
Thu, 12 Aug 2004 18:12:44 +0000 (18:12 +0000)
1004703 ] Make func_name writable

plus fixing a couple of nits in the documentation changes spotted by MvL
and a Misc/NEWS entry.

Doc/lib/libstdtypes.tex
Doc/ref/ref3.tex
Lib/test/test_funcattrs.py
Misc/NEWS
Objects/funcobject.c

index 01e800ad6fe414dace0d431ad0a38e396d8174c1..e97009e52691493672830a0c837f5c790128ad72 100644 (file)
@@ -1682,25 +1682,8 @@ and user-defined functions.  Both support the same operation (to call
 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.
+See the \citetitle[../ref/ref.html]{Python Reference Manual} for more
+information.
 
 \subsubsection{Methods \label{typesmethods}}
 \obindex{method}
index 7f337f67ca681b3ef88f7bd8e1e039f63c9c6297..973275f55829062e3b0e62233bce4ace5d807a60 100644 (file)
@@ -433,28 +433,55 @@ parameter list.
 \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.
+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}{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.
+
+\versionchanged[\code{func_name} is now writable]{2.4}
+
+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 2c31d366d797ef12a0568b7611a9a7402f387b55..3ccb2638635d419710bc707d48b8e2c75ea8aee0 100644 (file)
@@ -268,8 +268,15 @@ def test_func_name():
     def f(): pass
     verify(f.__name__ == "f")
     verify(f.func_name == "f")
-    cantset(f, "func_name", "f")
-    cantset(f, "__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 15d73e1be0d28b6ab7de259e857cb89a4391707f..f6e2faff19b26a5fee6fe47ed9752cc674cebd7f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.4 alpha 3?
 Core and builtins
 -----------------
 
+- The ``func_name`` (a.k.a. ``__name__``) attribute of user-defined
+  functions is now writable.
+
 - code_new (a.k.a new.code()) now checks its arguments sufficiently
   carefully that passing them on to PyCode_New() won't trigger calls
   to Py_FatalError() or PyErr_BadInternalCall().  It is still the case
index 971eb1cd0d601547f6d0e376162043b78c4b24e8..c46887c96b553b9a993c01eec25545d04bac1390 100644 (file)
@@ -163,8 +163,6 @@ static PyMemberDef func_memberlist[] = {
         {"__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 */
 };
@@ -249,6 +247,36 @@ func_set_code(PyFunctionObject *op, PyObject *value)
        return 0;
 }
 
+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)
 {
@@ -291,6 +319,8 @@ static PyGetSetDef func_getsetlist[] = {
         (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,8 +446,6 @@ func_dealloc(PyFunctionObject *op)
 static PyObject*
 func_repr(PyFunctionObject *op)
 {
-       if (op->func_name == Py_None)
-               return PyString_FromFormat("<anonymous function at %p>", op);
        return PyString_FromFormat("<function %s at %p>",
                                   PyString_AsString(op->func_name),
                                   op);