https://github.com/python/cpython/commit/09b624b80f54e1f97812981cfff9fa374bd5360f
commit: 09b624b80f54e1f97812981cfff9fa374bd5360f
branch: main
author: Steve Dower <steve.do...@python.org>
committer: zooba <steve.do...@microsoft.com>
date: 2025-04-21T15:59:03+01:00
summary:

gh-132639: Adds PyLong_AsNativeBytes, PyLong_FromNativeBytes and 
PyLong_FromUnsignedNativeBytes to the limited API (GH-132640)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-04-17-16-20-03.gh-issue-132639.zRVYU3.rst
M Doc/data/stable_abi.dat
M Include/cpython/longobject.h
M Include/longobject.h
M Lib/test/test_stable_abi_ctypes.py
M Misc/stable_abi.toml
M PC/python3dll.c

diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat
index c15f82603aa944..3d68487d07baf2 100644
--- a/Doc/data/stable_abi.dat
+++ b/Doc/data/stable_abi.dat
@@ -362,6 +362,7 @@ func,PyLong_AsLong,3.2,,
 func,PyLong_AsLongAndOverflow,3.2,,
 func,PyLong_AsLongLong,3.2,,
 func,PyLong_AsLongLongAndOverflow,3.2,,
+func,PyLong_AsNativeBytes,3.14,,
 func,PyLong_AsSize_t,3.2,,
 func,PyLong_AsSsize_t,3.2,,
 func,PyLong_AsUInt32,3.14,,
@@ -376,6 +377,7 @@ func,PyLong_FromInt32,3.14,,
 func,PyLong_FromInt64,3.14,,
 func,PyLong_FromLong,3.2,,
 func,PyLong_FromLongLong,3.2,,
+func,PyLong_FromNativeBytes,3.14,,
 func,PyLong_FromSize_t,3.2,,
 func,PyLong_FromSsize_t,3.2,,
 func,PyLong_FromString,3.2,,
@@ -383,6 +385,7 @@ func,PyLong_FromUInt32,3.14,,
 func,PyLong_FromUInt64,3.14,,
 func,PyLong_FromUnsignedLong,3.2,,
 func,PyLong_FromUnsignedLongLong,3.2,,
+func,PyLong_FromUnsignedNativeBytes,3.14,,
 func,PyLong_FromVoidPtr,3.2,,
 func,PyLong_GetInfo,3.2,,
 data,PyLong_Type,3.2,,
diff --git a/Include/cpython/longobject.h b/Include/cpython/longobject.h
index 7f28ad60b7467b..32e6fd73fb5c60 100644
--- a/Include/cpython/longobject.h
+++ b/Include/cpython/longobject.h
@@ -7,57 +7,6 @@
 
 PyAPI_FUNC(PyObject*) PyLong_FromUnicodeObject(PyObject *u, int base);
 
-#define Py_ASNATIVEBYTES_DEFAULTS -1
-#define Py_ASNATIVEBYTES_BIG_ENDIAN 0
-#define Py_ASNATIVEBYTES_LITTLE_ENDIAN 1
-#define Py_ASNATIVEBYTES_NATIVE_ENDIAN 3
-#define Py_ASNATIVEBYTES_UNSIGNED_BUFFER 4
-#define Py_ASNATIVEBYTES_REJECT_NEGATIVE 8
-#define Py_ASNATIVEBYTES_ALLOW_INDEX 16
-
-/* PyLong_AsNativeBytes: Copy the integer value to a native variable.
-   buffer points to the first byte of the variable.
-   n_bytes is the number of bytes available in the buffer. Pass 0 to request
-   the required size for the value.
-   flags is a bitfield of the following flags:
-   * 1 - little endian
-   * 2 - native endian
-   * 4 - unsigned destination (e.g. don't reject copying 255 into one byte)
-   * 8 - raise an exception for negative inputs
-   * 16 - call __index__ on non-int types
-   If flags is -1 (all bits set), native endian is used, value truncation
-   behaves most like C (allows negative inputs and allow MSB set), and non-int
-   objects will raise a TypeError.
-   Big endian mode will write the most significant byte into the address
-   directly referenced by buffer; little endian will write the least 
significant
-   byte into that address.
-
-   If an exception is raised, returns a negative value.
-   Otherwise, returns the number of bytes that are required to store the value.
-   To check that the full value is represented, ensure that the return value is
-   equal or less than n_bytes.
-   All n_bytes are guaranteed to be written (unless an exception occurs), and
-   so ignoring a positive return value is the equivalent of a downcast in C.
-   In cases where the full value could not be represented, the returned value
-   may be larger than necessary - this function is not an accurate way to
-   calculate the bit length of an integer object.
-   */
-PyAPI_FUNC(Py_ssize_t) PyLong_AsNativeBytes(PyObject* v, void* buffer,
-    Py_ssize_t n_bytes, int flags);
-
-/* PyLong_FromNativeBytes: Create an int value from a native integer
-   n_bytes is the number of bytes to read from the buffer. Passing 0 will
-   always produce the zero int.
-   PyLong_FromUnsignedNativeBytes always produces a non-negative int.
-   flags is the same as for PyLong_AsNativeBytes, but only supports selecting
-   the endianness or forcing an unsigned buffer.
-
-   Returns the int object, or NULL with an exception set. */
-PyAPI_FUNC(PyObject*) PyLong_FromNativeBytes(const void* buffer, size_t 
n_bytes,
-    int flags);
-PyAPI_FUNC(PyObject*) PyLong_FromUnsignedNativeBytes(const void* buffer,
-    size_t n_bytes, int flags);
-
 PyAPI_FUNC(int) PyUnstable_Long_IsCompact(const PyLongObject* op);
 PyAPI_FUNC(Py_ssize_t) PyUnstable_Long_CompactValue(const PyLongObject* op);
 
diff --git a/Include/longobject.h b/Include/longobject.h
index 45c0d218c13f2f..19f06977036d05 100644
--- a/Include/longobject.h
+++ b/Include/longobject.h
@@ -40,6 +40,58 @@ PyAPI_FUNC(int) PyLong_AsInt32(PyObject *obj, int32_t 
*value);
 PyAPI_FUNC(int) PyLong_AsUInt32(PyObject *obj, uint32_t *value);
 PyAPI_FUNC(int) PyLong_AsInt64(PyObject *obj, int64_t *value);
 PyAPI_FUNC(int) PyLong_AsUInt64(PyObject *obj, uint64_t *value);
+
+#define Py_ASNATIVEBYTES_DEFAULTS -1
+#define Py_ASNATIVEBYTES_BIG_ENDIAN 0
+#define Py_ASNATIVEBYTES_LITTLE_ENDIAN 1
+#define Py_ASNATIVEBYTES_NATIVE_ENDIAN 3
+#define Py_ASNATIVEBYTES_UNSIGNED_BUFFER 4
+#define Py_ASNATIVEBYTES_REJECT_NEGATIVE 8
+#define Py_ASNATIVEBYTES_ALLOW_INDEX 16
+
+/* PyLong_AsNativeBytes: Copy the integer value to a native variable.
+   buffer points to the first byte of the variable.
+   n_bytes is the number of bytes available in the buffer. Pass 0 to request
+   the required size for the value.
+   flags is a bitfield of the following flags:
+   * 1 - little endian
+   * 2 - native endian
+   * 4 - unsigned destination (e.g. don't reject copying 255 into one byte)
+   * 8 - raise an exception for negative inputs
+   * 16 - call __index__ on non-int types
+   If flags is -1 (all bits set), native endian is used, value truncation
+   behaves most like C (allows negative inputs and allow MSB set), and non-int
+   objects will raise a TypeError.
+   Big endian mode will write the most significant byte into the address
+   directly referenced by buffer; little endian will write the least 
significant
+   byte into that address.
+
+   If an exception is raised, returns a negative value.
+   Otherwise, returns the number of bytes that are required to store the value.
+   To check that the full value is represented, ensure that the return value is
+   equal or less than n_bytes.
+   All n_bytes are guaranteed to be written (unless an exception occurs), and
+   so ignoring a positive return value is the equivalent of a downcast in C.
+   In cases where the full value could not be represented, the returned value
+   may be larger than necessary - this function is not an accurate way to
+   calculate the bit length of an integer object.
+   */
+PyAPI_FUNC(Py_ssize_t) PyLong_AsNativeBytes(PyObject* v, void* buffer,
+    Py_ssize_t n_bytes, int flags);
+
+/* PyLong_FromNativeBytes: Create an int value from a native integer
+   n_bytes is the number of bytes to read from the buffer. Passing 0 will
+   always produce the zero int.
+   PyLong_FromUnsignedNativeBytes always produces a non-negative int.
+   flags is the same as for PyLong_AsNativeBytes, but only supports selecting
+   the endianness or forcing an unsigned buffer.
+
+   Returns the int object, or NULL with an exception set. */
+PyAPI_FUNC(PyObject*) PyLong_FromNativeBytes(const void* buffer, size_t 
n_bytes,
+    int flags);
+PyAPI_FUNC(PyObject*) PyLong_FromUnsignedNativeBytes(const void* buffer,
+    size_t n_bytes, int flags);
+
 #endif
 
 PyAPI_FUNC(PyObject *) PyLong_GetInfo(void);
diff --git a/Lib/test/test_stable_abi_ctypes.py 
b/Lib/test/test_stable_abi_ctypes.py
index f3724ce6d4d15a..1e6f69d49e9335 100644
--- a/Lib/test/test_stable_abi_ctypes.py
+++ b/Lib/test/test_stable_abi_ctypes.py
@@ -397,6 +397,7 @@ def test_windows_feature_macros(self):
     "PyLong_AsLongAndOverflow",
     "PyLong_AsLongLong",
     "PyLong_AsLongLongAndOverflow",
+    "PyLong_AsNativeBytes",
     "PyLong_AsSize_t",
     "PyLong_AsSsize_t",
     "PyLong_AsUInt32",
@@ -411,6 +412,7 @@ def test_windows_feature_macros(self):
     "PyLong_FromInt64",
     "PyLong_FromLong",
     "PyLong_FromLongLong",
+    "PyLong_FromNativeBytes",
     "PyLong_FromSize_t",
     "PyLong_FromSsize_t",
     "PyLong_FromString",
@@ -418,6 +420,7 @@ def test_windows_feature_macros(self):
     "PyLong_FromUInt64",
     "PyLong_FromUnsignedLong",
     "PyLong_FromUnsignedLongLong",
+    "PyLong_FromUnsignedNativeBytes",
     "PyLong_FromVoidPtr",
     "PyLong_GetInfo",
     "PyLong_Type",
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-17-16-20-03.gh-issue-132639.zRVYU3.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-17-16-20-03.gh-issue-132639.zRVYU3.rst
new file mode 100644
index 00000000000000..8d5446c8f9a315
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-17-16-20-03.gh-issue-132639.zRVYU3.rst
@@ -0,0 +1,2 @@
+Added :c:func:`PyLong_AsNativeBytes`, :c:func:`PyLong_FromNativeBytes` and
+:c:func:`PyLong_FromUnsignedNativeBytes` to the limited C API.
diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml
index 276526a1b6908e..d3e1f0db057023 100644
--- a/Misc/stable_abi.toml
+++ b/Misc/stable_abi.toml
@@ -2528,6 +2528,26 @@
     added = '3.14'
 [function.PyLong_AsUInt64]
     added = '3.14'
+[function.PyLong_AsNativeBytes]
+    added = '3.14'
+[function.PyLong_FromNativeBytes]
+    added = '3.14'
+[function.PyLong_FromUnsignedNativeBytes]
+    added = '3.14'
+[const.Py_ASNATIVEBYTES_DEFAULTS]
+    added = '3.14'
+[const.Py_ASNATIVEBYTES_BIG_ENDIAN]
+    added = '3.14'
+[const.Py_ASNATIVEBYTES_LITTLE_ENDIAN]
+    added = '3.14'
+[const.Py_ASNATIVEBYTES_NATIVE_ENDIAN]
+    added = '3.14'
+[const.Py_ASNATIVEBYTES_UNSIGNED_BUFFER]
+    added = '3.14'
+[const.Py_ASNATIVEBYTES_REJECT_NEGATIVE]
+    added = '3.14'
+[const.Py_ASNATIVEBYTES_ALLOW_INDEX]
+    added = '3.14'
 [const.Py_tp_vectorcall]
     added = '3.14'
 [function.PyType_GetBaseByToken]
diff --git a/PC/python3dll.c b/PC/python3dll.c
index 84b3c735240b73..f0c578e11c643b 100755
--- a/PC/python3dll.c
+++ b/PC/python3dll.c
@@ -351,6 +351,7 @@ EXPORT_FUNC(PyLong_AsLong)
 EXPORT_FUNC(PyLong_AsLongAndOverflow)
 EXPORT_FUNC(PyLong_AsLongLong)
 EXPORT_FUNC(PyLong_AsLongLongAndOverflow)
+EXPORT_FUNC(PyLong_AsNativeBytes)
 EXPORT_FUNC(PyLong_AsSize_t)
 EXPORT_FUNC(PyLong_AsSsize_t)
 EXPORT_FUNC(PyLong_AsUInt32)
@@ -365,6 +366,7 @@ EXPORT_FUNC(PyLong_FromInt32)
 EXPORT_FUNC(PyLong_FromInt64)
 EXPORT_FUNC(PyLong_FromLong)
 EXPORT_FUNC(PyLong_FromLongLong)
+EXPORT_FUNC(PyLong_FromNativeBytes)
 EXPORT_FUNC(PyLong_FromSize_t)
 EXPORT_FUNC(PyLong_FromSsize_t)
 EXPORT_FUNC(PyLong_FromString)
@@ -372,6 +374,7 @@ EXPORT_FUNC(PyLong_FromUInt32)
 EXPORT_FUNC(PyLong_FromUInt64)
 EXPORT_FUNC(PyLong_FromUnsignedLong)
 EXPORT_FUNC(PyLong_FromUnsignedLongLong)
+EXPORT_FUNC(PyLong_FromUnsignedNativeBytes)
 EXPORT_FUNC(PyLong_FromVoidPtr)
 EXPORT_FUNC(PyLong_GetInfo)
 EXPORT_FUNC(PyMapping_Check)

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to