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