PEP 590: Mark the main API as private to allow changes in Python 3.9 (GH-1064)
This commit is contained in:
parent
8470f2039f
commit
8363d1f06c
41
pep-0590.rst
41
pep-0590.rst
|
@ -17,6 +17,9 @@ It introduces a new "vectorcall" protocol and calling convention.
|
|||
This is based on the "fastcall" convention, which is already used internally by CPython.
|
||||
The new features can be used by any user-defined extension class.
|
||||
|
||||
Most of the new API is private in CPython 3.8.
|
||||
The plan is to finalize semantics and make it public in Python 3.9.
|
||||
|
||||
**NOTE**: This PEP deals only with the Python/C API,
|
||||
it does not affect the Python language or standard library.
|
||||
|
||||
|
@ -44,6 +47,13 @@ This is inefficient for calls to classes as several intermediate objects need to
|
|||
For a class ``cls``, at least one intermediate object is created for each call in the sequence
|
||||
``type.__call__``, ``cls.__new__``, ``cls.__init__``.
|
||||
|
||||
This PEP proposes an interface for use by extension modules.
|
||||
Such interfaces cannot effectively be tested, or designed, without having the
|
||||
consumers in the loop.
|
||||
For that reason, we provide private (underscore-prefixed) names.
|
||||
The API may change (based on consumer feedback) in Python 3.9, where we expect
|
||||
it to be finalized, and the underscores removed.
|
||||
|
||||
|
||||
Specification
|
||||
=============
|
||||
|
@ -65,12 +75,12 @@ Changes to the ``PyTypeObject`` struct
|
|||
--------------------------------------
|
||||
|
||||
The unused slot ``printfunc tp_print`` is replaced with ``tp_vectorcall_offset``. It has the type ``Py_ssize_t``.
|
||||
A new ``tp_flags`` flag is added, ``Py_TPFLAGS_HAVE_VECTORCALL``,
|
||||
A new ``tp_flags`` flag is added, ``_Py_TPFLAGS_HAVE_VECTORCALL``,
|
||||
which must be set for any class that uses the vectorcall protocol.
|
||||
|
||||
If ``Py_TPFLAGS_HAVE_VECTORCALL`` is set, then ``tp_vectorcall_offset`` must be a positive integer.
|
||||
If ``_Py_TPFLAGS_HAVE_VECTORCALL`` is set, then ``tp_vectorcall_offset`` must be a positive integer.
|
||||
It is the offset into the object of the vectorcall function pointer of type ``vectorcallfunc``.
|
||||
This pointer may be ``NULL``, in which case the behavior is the same as if ``Py_TPFLAGS_HAVE_VECTORCALL`` was not set.
|
||||
This pointer may be ``NULL``, in which case the behavior is the same as if ``_Py_TPFLAGS_HAVE_VECTORCALL`` was not set.
|
||||
|
||||
The ``tp_print`` slot is reused as the ``tp_vectorcall_offset`` slot to make it easier for for external projects to backport the vectorcall protocol to earlier Python versions.
|
||||
In particular, the Cython project has shown interest in doing that (see https://mail.python.org/pipermail/python-dev/2018-June/153927.html).
|
||||
|
@ -80,7 +90,7 @@ Descriptor behavior
|
|||
|
||||
One additional type flag is specified: ``Py_TPFLAGS_METHOD_DESCRIPTOR``.
|
||||
|
||||
``Py_TPFLAGS_METHOD_DESCRIPTOR`` should be set if the the callable uses the descriptor protocol to create a bound method-like object.
|
||||
``Py_TPFLAGS_METHOD_DESCRIPTOR`` should be set if the callable uses the descriptor protocol to create a bound method-like object.
|
||||
This is used by the interpreter to avoid creating temporary objects when calling methods
|
||||
(see ``_PyObject_GetMethod`` and the ``LOAD_METHOD``/``CALL_METHOD`` opcodes).
|
||||
|
||||
|
@ -128,7 +138,7 @@ New C API and changes to CPython
|
|||
|
||||
The following functions or macros are added to the C API:
|
||||
|
||||
- ``PyObject *PyObject_Vectorcall(PyObject *obj, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords)``:
|
||||
- ``PyObject *_PyObject_Vectorcall(PyObject *obj, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords)``:
|
||||
Calls ``obj`` with the given arguments.
|
||||
Note that ``nargs`` may include the flag ``PY_VECTORCALL_ARGUMENTS_OFFSET``.
|
||||
The actual number of positional arguments is given by ``PyVectorcall_NARGS(nargs)``.
|
||||
|
@ -149,7 +159,7 @@ The following functions or macros are added to the C API:
|
|||
Subclassing
|
||||
-----------
|
||||
|
||||
Extension types inherit the type flag ``Py_TPFLAGS_HAVE_VECTORCALL``
|
||||
Extension types inherit the type flag ``_Py_TPFLAGS_HAVE_VECTORCALL``
|
||||
and the value ``tp_vectorcall_offset`` from the base class,
|
||||
provided that they implement ``tp_call`` the same way as the base class.
|
||||
Additionally, the flag ``Py_TPFLAGS_METHOD_DESCRIPTOR``
|
||||
|
@ -161,6 +171,23 @@ This restriction may be lifted in the future, but that would require
|
|||
special-casing ``__call__`` in ``type.__setattribute__``.
|
||||
|
||||
|
||||
Finalizing the API
|
||||
==================
|
||||
|
||||
The underscore in the names ``_PyObject_Vectorcall`` and
|
||||
``_Py_TPFLAGS_HAVE_VECTORCALL`` indicates that this API may change in minor
|
||||
Python versions.
|
||||
When finalized (which is planned for Python 3.9), they will be renamed to
|
||||
``PyObject_Vectorcall`` and ``Py_TPFLAGS_HAVE_VECTORCALL``.
|
||||
The old underscore-prefixed names will remain available as aliases.
|
||||
|
||||
The new API will be documented as normal, but will warn of the above.
|
||||
|
||||
Semantics for the other names introduced in this PEP (``PyVectorcall_NARGS``,
|
||||
``PyVectorcall_Call``, ``Py_TPFLAGS_METHOD_DESCRIPTOR``,
|
||||
``PY_VECTORCALL_ARGUMENTS_OFFSET``) are final.
|
||||
|
||||
|
||||
Internal CPython changes
|
||||
========================
|
||||
|
||||
|
@ -203,7 +230,7 @@ Third-party extension classes using vectorcall
|
|||
|
||||
To enable call performance on a par with Python functions and built-in functions,
|
||||
third-party callables should include a ``vectorcallfunc`` function pointer,
|
||||
set ``tp_vectorcall_offset`` to the correct value and add the ``Py_TPFLAGS_HAVE_VECTORCALL`` flag.
|
||||
set ``tp_vectorcall_offset`` to the correct value and add the ``_Py_TPFLAGS_HAVE_VECTORCALL`` flag.
|
||||
Any class that does this must implement the ``tp_call`` function and make sure its behaviour is consistent with the ``vectorcallfunc`` function.
|
||||
Setting ``tp_call`` to ``PyVectorcall_Call`` is sufficient.
|
||||
|
||||
|
|
Loading…
Reference in New Issue