77// https://github.com/python/pythoncapi_compat
88//
99// Latest version:
10- // https://raw.githubusercontent.com/python/pythoncapi_compat/master /pythoncapi_compat.h
10+ // https://raw.githubusercontent.com/python/pythoncapi-compat/main /pythoncapi_compat.h
1111//
1212// SPDX-License-Identifier: 0BSD
1313
@@ -24,6 +24,9 @@ extern "C" {
2424#if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION)
2525# include " frameobject.h" // PyFrameObject, PyFrame_GetBack()
2626#endif
27+ #if PY_VERSION_HEX < 0x030C00A3
28+ # include < structmember.h> // T_SHORT, READONLY
29+ #endif
2730
2831
2932#ifndef _Py_CAST
@@ -287,7 +290,7 @@ PyFrame_GetVarString(PyFrameObject *frame, const char *name)
287290
288291
289292// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5
290- #if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
293+ #if PY_VERSION_HEX < 0x030900A5 || ( defined(PYPY_VERSION) && PY_VERSION_HEX < 0x030B0000 )
291294static inline PyInterpreterState *
292295PyThreadState_GetInterpreter (PyThreadState *tstate)
293296{
@@ -918,7 +921,7 @@ static inline int
918921PyObject_VisitManagedDict (PyObject *obj, visitproc visit, void *arg)
919922{
920923 PyObject **dict = _PyObject_GetDictPtr (obj);
921- if (*dict == NULL ) {
924+ if (dict == NULL || *dict == NULL ) {
922925 return -1 ;
923926 }
924927 Py_VISIT (*dict);
@@ -929,7 +932,7 @@ static inline void
929932PyObject_ClearManagedDict (PyObject *obj)
930933{
931934 PyObject **dict = _PyObject_GetDictPtr (obj);
932- if (*dict == NULL ) {
935+ if (dict == NULL || *dict == NULL ) {
933936 return ;
934937 }
935938 Py_CLEAR (*dict);
@@ -1204,11 +1207,11 @@ static inline int PyTime_PerfCounter(PyTime_t *result)
12041207#endif
12051208
12061209// gh-111389 added hash constants to Python 3.13.0a5. These constants were
1207- // added first as private macros to Python 3.4.0b1 and PyPy 7.3.9 .
1210+ // added first as private macros to Python 3.4.0b1 and PyPy 7.3.8 .
12081211#if (!defined(PyHASH_BITS) \
12091212 && ((!defined (PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1 ) \
12101213 || (defined (PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \
1211- && PYPY_VERSION_NUM >= 0x07090000 )))
1214+ && PYPY_VERSION_NUM >= 0x07030800 )))
12121215# define PyHASH_BITS _PyHASH_BITS
12131216# define PyHASH_MODULUS _PyHASH_MODULUS
12141217# define PyHASH_INF _PyHASH_INF
@@ -1520,6 +1523,36 @@ static inline int PyLong_GetSign(PyObject *obj, int *sign)
15201523}
15211524#endif
15221525
1526+ // gh-126061 added PyLong_IsPositive/Negative/Zero() to Python in 3.14.0a2
1527+ #if PY_VERSION_HEX < 0x030E00A2
1528+ static inline int PyLong_IsPositive (PyObject *obj)
1529+ {
1530+ if (!PyLong_Check (obj)) {
1531+ PyErr_Format (PyExc_TypeError, " expected int, got %s" , Py_TYPE (obj)->tp_name );
1532+ return -1 ;
1533+ }
1534+ return _PyLong_Sign (obj) == 1 ;
1535+ }
1536+
1537+ static inline int PyLong_IsNegative (PyObject *obj)
1538+ {
1539+ if (!PyLong_Check (obj)) {
1540+ PyErr_Format (PyExc_TypeError, " expected int, got %s" , Py_TYPE (obj)->tp_name );
1541+ return -1 ;
1542+ }
1543+ return _PyLong_Sign (obj) == -1 ;
1544+ }
1545+
1546+ static inline int PyLong_IsZero (PyObject *obj)
1547+ {
1548+ if (!PyLong_Check (obj)) {
1549+ PyErr_Format (PyExc_TypeError, " expected int, got %s" , Py_TYPE (obj)->tp_name );
1550+ return -1 ;
1551+ }
1552+ return _PyLong_Sign (obj) == 0 ;
1553+ }
1554+ #endif
1555+
15231556
15241557// gh-124502 added PyUnicode_Equal() to Python 3.14.0a0
15251558#if PY_VERSION_HEX < 0x030E00A0
@@ -1690,6 +1723,216 @@ static inline int PyLong_AsUInt64(PyObject *obj, uint64_t *pvalue)
16901723#endif
16911724
16921725
1726+ // gh-102471 added import and export API for integers to 3.14.0a2.
1727+ #if PY_VERSION_HEX < 0x030E00A2 && PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
1728+ // Helpers to access PyLongObject internals.
1729+ static inline void
1730+ _PyLong_SetSignAndDigitCount (PyLongObject *op, int sign, Py_ssize_t size)
1731+ {
1732+ #if PY_VERSION_HEX >= 0x030C0000
1733+ op->long_value .lv_tag = (uintptr_t )(1 - sign) | ((uintptr_t )(size) << 3 );
1734+ #elif PY_VERSION_HEX >= 0x030900A4
1735+ Py_SET_SIZE (op, sign * size);
1736+ #else
1737+ Py_SIZE (op) = sign * size;
1738+ #endif
1739+ }
1740+
1741+ static inline Py_ssize_t
1742+ _PyLong_DigitCount (const PyLongObject *op)
1743+ {
1744+ #if PY_VERSION_HEX >= 0x030C0000
1745+ return (Py_ssize_t)(op->long_value .lv_tag >> 3 );
1746+ #else
1747+ return _PyLong_Sign ((PyObject*)op) < 0 ? -Py_SIZE (op) : Py_SIZE (op);
1748+ #endif
1749+ }
1750+
1751+ static inline digit*
1752+ _PyLong_GetDigits (const PyLongObject *op)
1753+ {
1754+ #if PY_VERSION_HEX >= 0x030C0000
1755+ return (digit*)(op->long_value .ob_digit );
1756+ #else
1757+ return (digit*)(op->ob_digit );
1758+ #endif
1759+ }
1760+
1761+ typedef struct PyLongLayout {
1762+ uint8_t bits_per_digit;
1763+ uint8_t digit_size;
1764+ int8_t digits_order;
1765+ int8_t digit_endianness;
1766+ } PyLongLayout;
1767+
1768+ typedef struct PyLongExport {
1769+ int64_t value;
1770+ uint8_t negative;
1771+ Py_ssize_t ndigits;
1772+ const void *digits;
1773+ Py_uintptr_t _reserved;
1774+ } PyLongExport;
1775+
1776+ typedef struct PyLongWriter PyLongWriter;
1777+
1778+ static inline const PyLongLayout*
1779+ PyLong_GetNativeLayout (void )
1780+ {
1781+ static const PyLongLayout PyLong_LAYOUT = {
1782+ PyLong_SHIFT,
1783+ sizeof (digit),
1784+ -1 , // least significant first
1785+ PY_LITTLE_ENDIAN ? -1 : 1 ,
1786+ };
1787+
1788+ return &PyLong_LAYOUT;
1789+ }
1790+
1791+ static inline int
1792+ PyLong_Export (PyObject *obj, PyLongExport *export_long)
1793+ {
1794+ if (!PyLong_Check (obj)) {
1795+ memset (export_long, 0 , sizeof (*export_long));
1796+ PyErr_Format (PyExc_TypeError, " expected int, got %s" ,
1797+ Py_TYPE (obj)->tp_name );
1798+ return -1 ;
1799+ }
1800+
1801+ // Fast-path: try to convert to a int64_t
1802+ PyLongObject *self = (PyLongObject*)obj;
1803+ int overflow;
1804+ #if SIZEOF_LONG == 8
1805+ long value = PyLong_AsLongAndOverflow (obj, &overflow);
1806+ #else
1807+ // Windows has 32-bit long, so use 64-bit long long instead
1808+ long long value = PyLong_AsLongLongAndOverflow (obj, &overflow);
1809+ #endif
1810+ Py_BUILD_ASSERT (sizeof (value) == sizeof (int64_t ));
1811+ // the function cannot fail since obj is a PyLongObject
1812+ assert (!(value == -1 && PyErr_Occurred ()));
1813+
1814+ if (!overflow) {
1815+ export_long->value = value;
1816+ export_long->negative = 0 ;
1817+ export_long->ndigits = 0 ;
1818+ export_long->digits = 0 ;
1819+ export_long->_reserved = 0 ;
1820+ }
1821+ else {
1822+ export_long->value = 0 ;
1823+ export_long->negative = _PyLong_Sign (obj) < 0 ;
1824+ export_long->ndigits = _PyLong_DigitCount (self);
1825+ if (export_long->ndigits == 0 ) {
1826+ export_long->ndigits = 1 ;
1827+ }
1828+ export_long->digits = _PyLong_GetDigits (self);
1829+ export_long->_reserved = (Py_uintptr_t)Py_NewRef (obj);
1830+ }
1831+ return 0 ;
1832+ }
1833+
1834+ static inline void
1835+ PyLong_FreeExport (PyLongExport *export_long)
1836+ {
1837+ PyObject *obj = (PyObject*)export_long->_reserved ;
1838+
1839+ if (obj) {
1840+ export_long->_reserved = 0 ;
1841+ Py_DECREF (obj);
1842+ }
1843+ }
1844+
1845+ static inline PyLongWriter*
1846+ PyLongWriter_Create (int negative, Py_ssize_t ndigits, void **digits)
1847+ {
1848+ if (ndigits <= 0 ) {
1849+ PyErr_SetString (PyExc_ValueError, " ndigits must be positive" );
1850+ return NULL ;
1851+ }
1852+ assert (digits != NULL );
1853+
1854+ PyLongObject *obj = _PyLong_New (ndigits);
1855+ if (obj == NULL ) {
1856+ return NULL ;
1857+ }
1858+ _PyLong_SetSignAndDigitCount (obj, negative?-1 :1 , ndigits);
1859+
1860+ *digits = _PyLong_GetDigits (obj);
1861+ return (PyLongWriter*)obj;
1862+ }
1863+
1864+ static inline void
1865+ PyLongWriter_Discard (PyLongWriter *writer)
1866+ {
1867+ PyLongObject *obj = (PyLongObject *)writer;
1868+
1869+ assert (Py_REFCNT (obj) == 1 );
1870+ Py_DECREF (obj);
1871+ }
1872+
1873+ static inline PyObject*
1874+ PyLongWriter_Finish (PyLongWriter *writer)
1875+ {
1876+ PyObject *obj = (PyObject *)writer;
1877+ PyLongObject *self = (PyLongObject*)obj;
1878+ Py_ssize_t j = _PyLong_DigitCount (self);
1879+ Py_ssize_t i = j;
1880+ int sign = _PyLong_Sign (obj);
1881+
1882+ assert (Py_REFCNT (obj) == 1 );
1883+
1884+ // Normalize and get singleton if possible
1885+ while (i > 0 && _PyLong_GetDigits (self)[i-1 ] == 0 ) {
1886+ --i;
1887+ }
1888+ if (i != j) {
1889+ if (i == 0 ) {
1890+ sign = 0 ;
1891+ }
1892+ _PyLong_SetSignAndDigitCount (self, sign, i);
1893+ }
1894+ if (i <= 1 ) {
1895+ long val = sign * (long )(_PyLong_GetDigits (self)[0 ]);
1896+ Py_DECREF (obj);
1897+ return PyLong_FromLong (val);
1898+ }
1899+
1900+ return obj;
1901+ }
1902+ #endif
1903+
1904+
1905+ #if PY_VERSION_HEX < 0x030C00A3
1906+ # define Py_T_SHORT T_SHORT
1907+ # define Py_T_INT T_INT
1908+ # define Py_T_LONG T_LONG
1909+ # define Py_T_FLOAT T_FLOAT
1910+ # define Py_T_DOUBLE T_DOUBLE
1911+ # define Py_T_STRING T_STRING
1912+ # define _Py_T_OBJECT T_OBJECT
1913+ # define Py_T_CHAR T_CHAR
1914+ # define Py_T_BYTE T_BYTE
1915+ # define Py_T_UBYTE T_UBYTE
1916+ # define Py_T_USHORT T_USHORT
1917+ # define Py_T_UINT T_UINT
1918+ # define Py_T_ULONG T_ULONG
1919+ # define Py_T_STRING_INPLACE T_STRING_INPLACE
1920+ # define Py_T_BOOL T_BOOL
1921+ # define Py_T_OBJECT_EX T_OBJECT_EX
1922+ # define Py_T_LONGLONG T_LONGLONG
1923+ # define Py_T_ULONGLONG T_ULONGLONG
1924+ # define Py_T_PYSSIZET T_PYSSIZET
1925+
1926+ # if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
1927+ # define _Py_T_NONE T_NONE
1928+ # endif
1929+
1930+ # define Py_READONLY READONLY
1931+ # define Py_AUDIT_READ READ_RESTRICTED
1932+ # define _Py_WRITE_RESTRICTED PY_WRITE_RESTRICTED
1933+ #endif
1934+
1935+
16931936#ifdef __cplusplus
16941937}
16951938#endif
0 commit comments