diff --git a/peps/conf.py b/peps/conf.py index 9a747aa8f..a29404086 100644 --- a/peps/conf.py +++ b/peps/conf.py @@ -62,6 +62,7 @@ intersphinx_mapping = { "py3.11": ("https://docs.python.org/3.11/", None), "py3.12": ("https://docs.python.org/3.12/", None), "py3.13": ("https://docs.python.org/3.13/", None), + "py3.14": ("https://docs.python.org/3.14/", None), } intersphinx_disabled_reftypes = [] diff --git a/peps/pep-0757.rst b/peps/pep-0757.rst index 3ae1d1d1a..636e71cee 100644 --- a/peps/pep-0757.rst +++ b/peps/pep-0757.rst @@ -3,10 +3,12 @@ Title: C API to import-export Python integers Author: Sergey B Kirpichev , Victor Stinner PEP-Delegate: C API Working Group +Discussions-To: https://discuss.python.org/t/63895 Status: Draft Type: Standards Track Created: 13-Sep-2024 Python-Version: 3.14 +Post-History: `14-Sep-2024 `__ .. highlight:: c @@ -14,7 +16,7 @@ Python-Version: 3.14 Abstract ======== -Add a new C API to import and export Python integers, ``int`` objects: +Add a new C API to import and export Python integers, :class:`int` objects: especially ``PyLongWriter_Create()`` and ``PyLong_AsDigitArray()`` functions. @@ -27,7 +29,7 @@ Projects such as `gmpy2 `_, `SAGE `_ access directly Python "internals" (the ``PyLongObject`` structure) or use an inefficient temporary format (hex strings for Python-FLINT) to import and -export Python ``int`` objects. The Python ``int`` implementation +export Python :class:`int` objects. The Python :class:`int` implementation changed in Python 3.12 to add a tag and "compact values". In the 3.13 alpha 1 release, the private undocumented ``_PyLong_New()`` @@ -75,9 +77,11 @@ Data needed by `GMP `_-like import-export functions. PyLong_GetNativeLayout() ^^^^^^^^^^^^^^^^^^^^^^^^ -API: ``const PyLongLayout* PyLong_GetNativeLayout(void)``. +API:: -Get the native layout of Python ``int`` objects. + const PyLongLayout* PyLong_GetNativeLayout(void) + +Get the native layout of Python :class:`int` objects. Export API @@ -109,21 +113,23 @@ On CPython 3.14, no memory copy is needed, it's just a thin wrapper to expose Python int internal digits array. ``PyLong_DigitArray.obj`` stores a strong reference to the Python -``int`` object to make sure that that structure remains valid until +:class:`int` object to make sure that that structure remains valid until ``PyLong_FreeDigitArray()`` is called. PyLong_AsDigitArray() ^^^^^^^^^^^^^^^^^^^^^ -API: ``int PyLong_AsDigitArray(PyObject *obj, PyLong_DigitArray *array)``. +API:: -Export a Python ``int`` object as a digits array. + int PyLong_AsDigitArray(PyObject *obj, PyLong_DigitArray *array) + +Export a Python :class:`int` object as a digits array. On success, set *\*array* and return 0. On error, set an exception and return -1. -This function always succeeds if *obj* is a Python ``int`` object or a +This function always succeeds if *obj* is a Python :class:`int` object or a subclass. ``PyLong_FreeDigitArray()`` must be called once done with using @@ -133,7 +139,9 @@ subclass. PyLong_FreeDigitArray() ^^^^^^^^^^^^^^^^^^^^^^^ -API: ``void PyLong_FreeDigitArray(PyLong_DigitArray *array)``. +API:: + + void PyLong_FreeDigitArray(PyLong_DigitArray *array) Release the export *array* created by ``PyLong_AsDigitArray()``. @@ -164,7 +172,9 @@ convert the object to a compact integer if needed. PyLongWriter_Create() ^^^^^^^^^^^^^^^^^^^^^ -API: ``PyLongWriter* PyLongWriter_Create(int negative, Py_ssize_t ndigits, void **digits)``. +API:: + + PyLongWriter* PyLongWriter_Create(int negative, Py_ssize_t ndigits, void **digits) Create a ``PyLongWriter``. @@ -177,7 +187,7 @@ On error, set an exception and return ``NULL``. greater than or equal to 0. The caller must initialize the digits array *digits* and then call -``PyLongWriter_Finish()`` to get a Python ``int``. Digits must be +``PyLongWriter_Finish()`` to get a Python :class:`int`. Digits must be in the range [``0``; ``PyLong_BASE - 1``]. Unused digits must be set to ``0``. @@ -185,18 +195,22 @@ in the range [``0``; ``PyLong_BASE - 1``]. Unused digits must be set to PyLongWriter_Finish() ^^^^^^^^^^^^^^^^^^^^^ -API: ``PyObject* PyLongWriter_Finish(PyLongWriter *writer)``. +API:: + + PyObject* PyLongWriter_Finish(PyLongWriter *writer) Finish a ``PyLongWriter`` created by ``PyLongWriter_Create()``. -On success, return a Python ``int`` object. +On success, return a Python :class:`int` object. On error, set an exception and return ``NULL``. PyLongWriter_Discard() ^^^^^^^^^^^^^^^^^^^^^^ -API: ``void PyLongWriter_Discard(PyLongWriter *writer)``. +API:: + + void PyLongWriter_Discard(PyLongWriter *writer) Discard the internal object and destroy the writer instance. @@ -211,12 +225,11 @@ performance overhead on small integers. For small integers of a few digits (for example, 1 or 2 digits), existing APIs can be used. Examples to import / export: -* ``PyLong_FromUInt64()`` / ``PyLong_AsUInt64()``; -* ``PyLong_FromLong()`` / ``PyLong_AsLong()`` or ``PyLong_AsInt()``; -* ``PyUnstable_PyLong_IsCompact()`` and - ``PyUnstable_PyLong_CompactValue()``; -* ``PyLong_FromNativeBytes()`` / ``PyLong_AsNativeBytes()``; -* etc. +* :external+py3.14:c:func:`PyLong_FromUInt64()` / :external+py3.14:c:func:`PyLong_AsUInt64()`; +* :c:func:`PyLong_FromLong()` / :c:func:`PyLong_AsLong()` or :c:func:`PyLong_AsInt()`; +* :external+py3.13:c:func:`PyUnstable_Long_IsCompact()` and + :external+py3.13:c:func:`PyUnstable_Long_CompactValue()`; +* :c:func:`PyLong_FromNativeBytes()` / :c:func:`PyLong_AsNativeBytes()`; Implementation @@ -362,14 +375,21 @@ There is no impact on the backward compatibility, only new APIs are added. -Open Question -============= +Open Questions +============== -* Should we add *digits_order* and *endian* members to ``sys.int_info`` +* Should we add *digits_order* and *endian* members to :data:`sys.int_info` and remove ``PyLong_GetNativeLayout()``? The ``PyLong_GetNativeLayout()`` function returns a C structure - which is more convenient to use in C than ``sys.int_info`` which uses + which is more convenient to use in C than :data:`sys.int_info` which uses Python objects. +* Currenly, all required information for :class:`int` import/export is + already available via :c:func:`PyLong_GetInfo()` or :data:`sys.int_info`. + Native endianness of "digits" and current order of digits (least + significant digit first) --- is a common denominator of all libraries + for aribitrary precision integer arithmetic. So, shouldn't we just remove + from API both ``PyLongLayout`` and ``PyLong_GetNativeLayout()`` (which + is actually just a minor convenience)? Rejected Ideas