PEP 580: update (#751)

This commit is contained in:
jdemeyer 2018-08-03 21:08:57 +02:00 committed by Brett Cannon
parent c567006fbc
commit 2270327061
1 changed files with 35 additions and 19 deletions

View File

@ -125,8 +125,12 @@ The ``cc_parent`` field (accessed for example by a ``__parent__``
or ``__objclass__`` descriptor from Python code) can be any Python object.
For methods of extension types, this is set to the class.
For functions of modules, this is set to the module.
However, custom classes are free to set ``cc_parent`` to whatever they want,
it can also be ``NULL``.
It is only used by the C call protocol if the ``CCALL_OBJCLASS`` flag is set.
The parent serves multiple purposes: for methods of extension types,
The parent serves multiple purposes: for methods of extension types
(more precisely, when the flag ``CCALL_OBJCLASS`` is set),
it is used for type checks like the following::
>>> list.append({}, "x")
@ -136,15 +140,20 @@ it is used for type checks like the following::
PEP 573 specifies that every function should have access to the
module in which it is defined.
For functions of a module, this is given by the parent.
It is recommended to use the parent for this,
which works directly for functions of a module.
For methods, this works indirectly through the class,
assuming that the class has a pointer to the module.
The parent would also typically be used to implement ``__qualname__``.
The new C API function ``PyCCall_GenericGetQualname()`` does exactly that.
Custom classes are free to set ``cc_parent`` to whatever they want.
It is only used by the C call protocol if the ``CCALL_OBJCLASS`` flag is set.
**NOTE**: for functions of modules,
the parent is exactly the same as ``__self__``.
However, using ``__self__`` for the module is a quirk of the current implementation:
in the future, we want to allow functions which use ``__self__``
in the normal way, for implementing methods.
Such functions can still use ``cc_parent`` instead to refer to the module.
Using tp_print
--------------
@ -172,7 +181,8 @@ if it has the ``Py_TPFLAGS_HAVE_CCALL`` flag set
Such a class must implement ``__call__`` as described in this section
(in practice, this just means setting ``tp_call`` to ``PyCCall_Call``).
The ``cc_func`` field is a C function pointer.
The ``cc_func`` field is a C function pointer,
which plays the same role as the existing ``ml_meth`` field of ``PyMethodDef``.
Its precise signature depends on flags.
Below are the possible values for ``cc_flags & CCALL_SIGNATURE``
together with the arguments that the C function takes.
@ -191,20 +201,29 @@ signature flags:
- ``CCALL_FASTCALL | CCALL_KEYWORDS``:
``cc_func(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)``
(``kwnames`` is either ``NULL`` or a non-empty tuple of keyword names)
- ``CCALL_NOARGS``:
``cc_func(PyObject *self)``
``cc_func(PyObject *self, PyObject *unused)`` (second argument is always ``NULL``)
- ``CCALL_O``:
``cc_func(PyObject *self, PyObject *arg)``
The flag ``CCALL_FUNCARG`` may be combined with any of these.
If so, the C function takes an additional argument as second argument
after ``self``.
This argument is used to pass the function object (the ``self`` in ``__call__``).
If so, the C function takes an additional argument
as first argument before ``self``.
This argument is used to pass the function object
(the ``self`` in ``__call__`` but see NOTE below).
For example, we have the following signature:
- ``CCALL_VARARGS | CCALL_FUNCARG``: ``cc_func(PyObject *self, PyObject *func, PyObject *args)``
- ``CCALL_FUNCARG | CCALL_VARARGS``:
``cc_func(PyObject *func, PyObject *self, PyObject *args)``
One exception is ``CCALL_FUNCARG | CCALL_NOARGS``:
the ``unused`` argument is dropped, so the signature becomes
- ``CCALL_FUNCARG | CCALL_NOARGS``:
``cc_func(PyObject *func, PyObject *self)``
**NOTE**: in the case of bound methods, it is currently unspecified
whether the "function object" in the paragraph above refers
@ -215,10 +234,6 @@ Despite this ambiguity, the implementation of bound methods
guarantees that ``PyCCall_CCALLDEF(func)``
points to the ``PyCCallDef`` of the original function.
**NOTE**: ``METH_NOARGS`` takes a second unused argument.
This is compatible with ``CCALL_NOARGS | CCALL_FUNCARG``,
which also takes two arguments.
**NOTE**: unlike the existing ``METH_...`` flags,
the ``CCALL_...`` constants do not necessarily represent single bits.
So checking ``(cc_flags & CCALL_VARARGS) == 0`` is not a valid way
@ -250,12 +265,12 @@ then the first positional argument is removed from
Effectively, the first positional argument is treated as ``__self__``.
If there are no positional arguments, ``TypeError`` is raised.
This process is called self slicing and a function is said to have self
This process is called "self slicing" and a function is said to have self
slicing if ``cr_self`` is NULL and ``CCALL_SELFARG`` is set.
Note that a ``METH_NULLARG`` function with self slicing effectively has
Note that a ``CCALL_NOARGS`` function with self slicing effectively has
one argument, namely ``self``.
Analogously, a ``METH_O`` function with self slicing has two arguments.
Analogously, a ``CCALL_O`` function with self slicing has two arguments.
Descriptor behavior
-------------------
@ -411,8 +426,9 @@ The following function is added (also to the stable ABI [#pep384]_):
- ``PyObject * PyCFunction_ClsNew(PyTypeObject *cls, PyMethodDef *ml, PyObject *self, PyObject *module, PyObject *parent)``:
create a new object with object structure ``PyCFunctionObject`` and class ``cls``.
Note that the entries of the ``PyMethodDef`` structure are used to construct
the new object, but it is no longer stored in the object.
The entries of the ``PyMethodDef`` structure are used to construct
the new object, but the pointer to the ``PyMethodDef`` structure
is not stored.
The flags for the C call protocol are automatically determined in terms
of ``ml->ml_flags``, ``self`` and ``parent``.