This is my patch
[ 1004703 ] Make func_name writable plus fixing a couple of nits in the documentation changes spotted by MvL and a Misc/NEWS entry.
This commit is contained in:
parent
5523c2517f
commit
5e897959db
@ -1682,25 +1682,8 @@ and user-defined functions. Both support the same operation (to call
|
|||||||
the function), but the implementation is different, hence the
|
the function), but the implementation is different, hence the
|
||||||
different object types.
|
different object types.
|
||||||
|
|
||||||
The implementation adds two special read-only attributes:
|
See the \citetitle[../ref/ref.html]{Python Reference Manual} for more
|
||||||
\code{\var{f}.func_code} is a function's \dfn{code
|
information.
|
||||||
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}}
|
\subsubsection{Methods \label{typesmethods}}
|
||||||
\obindex{method}
|
\obindex{method}
|
||||||
|
@ -433,28 +433,55 @@ parameter list.
|
|||||||
\obindex{function}
|
\obindex{function}
|
||||||
\obindex{user-defined function}
|
\obindex{user-defined function}
|
||||||
|
|
||||||
Special attributes: \member{func_doc} or \member{__doc__} is the
|
Special attributes:
|
||||||
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},
|
\begin{tableiii}{lll}{member}{Attribute}{Meaning}{}
|
||||||
\member{func_doc}/\member{__doc__}, and
|
\lineiii{func_doc}{The function's documentation string, or
|
||||||
\member{func_dict}/\member{__dict__} may be writable; the
|
\code{None} if unavailable}{Writable}
|
||||||
others can never be changed. Additional information about a
|
|
||||||
function's definition can be retrieved from its code object; see the
|
\lineiii{__doc__}{Another way of spelling
|
||||||
description of internal types below.
|
\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)}{
|
\withsubitem{(function attribute)}{
|
||||||
\ttindex{func_doc}
|
\ttindex{func_doc}
|
||||||
|
@ -268,8 +268,15 @@ def test_func_name():
|
|||||||
def f(): pass
|
def f(): pass
|
||||||
verify(f.__name__ == "f")
|
verify(f.__name__ == "f")
|
||||||
verify(f.func_name == "f")
|
verify(f.func_name == "f")
|
||||||
cantset(f, "func_name", "f")
|
f.__name__ = "g"
|
||||||
cantset(f, "__name__", "f")
|
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 test_func_code():
|
||||||
def f(): pass
|
def f(): pass
|
||||||
|
@ -12,6 +12,9 @@ What's New in Python 2.4 alpha 3?
|
|||||||
Core and builtins
|
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
|
- code_new (a.k.a new.code()) now checks its arguments sufficiently
|
||||||
carefully that passing them on to PyCode_New() won't trigger calls
|
carefully that passing them on to PyCode_New() won't trigger calls
|
||||||
to Py_FatalError() or PyErr_BadInternalCall(). It is still the case
|
to Py_FatalError() or PyErr_BadInternalCall(). It is still the case
|
||||||
|
@ -163,8 +163,6 @@ static PyMemberDef func_memberlist[] = {
|
|||||||
{"__doc__", T_OBJECT, OFF(func_doc), WRITE_RESTRICTED},
|
{"__doc__", T_OBJECT, OFF(func_doc), WRITE_RESTRICTED},
|
||||||
{"func_globals", T_OBJECT, OFF(func_globals),
|
{"func_globals", T_OBJECT, OFF(func_globals),
|
||||||
RESTRICTED|READONLY},
|
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},
|
{"__module__", T_OBJECT, OFF(func_module), WRITE_RESTRICTED},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
@ -249,6 +247,36 @@ func_set_code(PyFunctionObject *op, PyObject *value)
|
|||||||
return 0;
|
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 *
|
static PyObject *
|
||||||
func_get_defaults(PyFunctionObject *op)
|
func_get_defaults(PyFunctionObject *op)
|
||||||
{
|
{
|
||||||
@ -291,6 +319,8 @@ static PyGetSetDef func_getsetlist[] = {
|
|||||||
(setter)func_set_defaults},
|
(setter)func_set_defaults},
|
||||||
{"func_dict", (getter)func_get_dict, (setter)func_set_dict},
|
{"func_dict", (getter)func_get_dict, (setter)func_set_dict},
|
||||||
{"__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 */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -416,8 +446,6 @@ func_dealloc(PyFunctionObject *op)
|
|||||||
static PyObject*
|
static PyObject*
|
||||||
func_repr(PyFunctionObject *op)
|
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>",
|
return PyString_FromFormat("<function %s at %p>",
|
||||||
PyString_AsString(op->func_name),
|
PyString_AsString(op->func_name),
|
||||||
op);
|
op);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user