PEP 590: Mark the main API as private to allow changes in Python 3.9 (GH-1064)

This commit is contained in:
Petr Viktorin 2019-05-28 11:11:03 +02:00 committed by GitHub
parent 8470f2039f
commit 8363d1f06c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 34 additions and 7 deletions

View File

@ -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.