Skip to content

Commit ca97d96

Browse files
authored
[mypyc] Sync pythoncapi_compat.h (#17929)
Use functions added for Python 3.14 * `PyBytes_Join` added in python/cpython#121645 * `PyUnicode_Equal` added in python/cpython#124502
1 parent 0c10dc3 commit ca97d96

File tree

4 files changed

+341
-15
lines changed

4 files changed

+341
-15
lines changed

mypyc/lib-rt/bytes_ops.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ PyObject *CPyBytes_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end) {
9999
// (mostly commonly, for bytearrays)
100100
PyObject *CPyBytes_Join(PyObject *sep, PyObject *iter) {
101101
if (PyBytes_CheckExact(sep)) {
102-
return _PyBytes_Join(sep, iter);
102+
return PyBytes_Join(sep, iter);
103103
} else {
104104
_Py_IDENTIFIER(join);
105105
return _PyObject_CallMethodIdOneArg(sep, &PyId_join, iter);

mypyc/lib-rt/getargsfast.c

+1-8
Original file line numberDiff line numberDiff line change
@@ -271,16 +271,9 @@ find_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key)
271271
for (i = 0; i < nkwargs; i++) {
272272
PyObject *kwname = PyTuple_GET_ITEM(kwnames, i);
273273
assert(PyUnicode_Check(kwname));
274-
#if CPY_3_13_FEATURES
275-
if (_PyUnicode_Equal(kwname, key)) {
274+
if (PyUnicode_Equal(kwname, key)) {
276275
return kwstack[i];
277276
}
278-
#else
279-
if (_PyUnicode_EQ(kwname, key)) {
280-
return kwstack[i];
281-
}
282-
#endif
283-
284277
}
285278
return NULL;
286279
}

mypyc/lib-rt/pythoncapi_compat.h

+338-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ extern "C" {
4545
# define _PyObject_CAST(op) _Py_CAST(PyObject*, op)
4646
#endif
4747

48+
#ifndef Py_BUILD_ASSERT
49+
# define Py_BUILD_ASSERT(cond) \
50+
do { \
51+
(void)sizeof(char [1 - 2 * !(cond)]); \
52+
} while(0)
53+
#endif
54+
4855

4956
// bpo-42262 added Py_NewRef() to Python 3.10.0a3
5057
#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef)
@@ -1338,9 +1345,169 @@ PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value,
13381345
}
13391346
#endif
13401347

1348+
#if PY_VERSION_HEX < 0x030D00B3
1349+
# define Py_BEGIN_CRITICAL_SECTION(op) {
1350+
# define Py_END_CRITICAL_SECTION() }
1351+
# define Py_BEGIN_CRITICAL_SECTION2(a, b) {
1352+
# define Py_END_CRITICAL_SECTION2() }
1353+
#endif
1354+
1355+
#if PY_VERSION_HEX < 0x030E0000 && PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION)
1356+
typedef struct PyUnicodeWriter PyUnicodeWriter;
1357+
1358+
static inline void PyUnicodeWriter_Discard(PyUnicodeWriter *writer)
1359+
{
1360+
_PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer);
1361+
PyMem_Free(writer);
1362+
}
1363+
1364+
static inline PyUnicodeWriter* PyUnicodeWriter_Create(Py_ssize_t length)
1365+
{
1366+
if (length < 0) {
1367+
PyErr_SetString(PyExc_ValueError,
1368+
"length must be positive");
1369+
return NULL;
1370+
}
1371+
1372+
const size_t size = sizeof(_PyUnicodeWriter);
1373+
PyUnicodeWriter *pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size);
1374+
if (pub_writer == _Py_NULL) {
1375+
PyErr_NoMemory();
1376+
return _Py_NULL;
1377+
}
1378+
_PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer;
1379+
1380+
_PyUnicodeWriter_Init(writer);
1381+
if (_PyUnicodeWriter_Prepare(writer, length, 127) < 0) {
1382+
PyUnicodeWriter_Discard(pub_writer);
1383+
return NULL;
1384+
}
1385+
writer->overallocate = 1;
1386+
return pub_writer;
1387+
}
1388+
1389+
static inline PyObject* PyUnicodeWriter_Finish(PyUnicodeWriter *writer)
1390+
{
1391+
PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer);
1392+
assert(((_PyUnicodeWriter*)writer)->buffer == NULL);
1393+
PyMem_Free(writer);
1394+
return str;
1395+
}
1396+
1397+
static inline int
1398+
PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch)
1399+
{
1400+
if (ch > 0x10ffff) {
1401+
PyErr_SetString(PyExc_ValueError,
1402+
"character must be in range(0x110000)");
1403+
return -1;
1404+
}
1405+
1406+
return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch);
1407+
}
1408+
1409+
static inline int
1410+
PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj)
1411+
{
1412+
PyObject *str = PyObject_Str(obj);
1413+
if (str == NULL) {
1414+
return -1;
1415+
}
1416+
1417+
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
1418+
Py_DECREF(str);
1419+
return res;
1420+
}
1421+
1422+
static inline int
1423+
PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj)
1424+
{
1425+
PyObject *str = PyObject_Repr(obj);
1426+
if (str == NULL) {
1427+
return -1;
1428+
}
1429+
1430+
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
1431+
Py_DECREF(str);
1432+
return res;
1433+
}
1434+
1435+
static inline int
1436+
PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer,
1437+
const char *str, Py_ssize_t size)
1438+
{
1439+
if (size < 0) {
1440+
size = (Py_ssize_t)strlen(str);
1441+
}
1442+
1443+
PyObject *str_obj = PyUnicode_FromStringAndSize(str, size);
1444+
if (str_obj == _Py_NULL) {
1445+
return -1;
1446+
}
1447+
1448+
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj);
1449+
Py_DECREF(str_obj);
1450+
return res;
1451+
}
1452+
1453+
static inline int
1454+
PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer,
1455+
const wchar_t *str, Py_ssize_t size)
1456+
{
1457+
if (size < 0) {
1458+
size = (Py_ssize_t)wcslen(str);
1459+
}
1460+
1461+
PyObject *str_obj = PyUnicode_FromWideChar(str, size);
1462+
if (str_obj == _Py_NULL) {
1463+
return -1;
1464+
}
1465+
1466+
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj);
1467+
Py_DECREF(str_obj);
1468+
return res;
1469+
}
1470+
1471+
static inline int
1472+
PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str,
1473+
Py_ssize_t start, Py_ssize_t end)
1474+
{
1475+
if (!PyUnicode_Check(str)) {
1476+
PyErr_Format(PyExc_TypeError, "expect str, not %T", str);
1477+
return -1;
1478+
}
1479+
if (start < 0 || start > end) {
1480+
PyErr_Format(PyExc_ValueError, "invalid start argument");
1481+
return -1;
1482+
}
1483+
if (end > PyUnicode_GET_LENGTH(str)) {
1484+
PyErr_Format(PyExc_ValueError, "invalid end argument");
1485+
return -1;
1486+
}
1487+
1488+
return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str,
1489+
start, end);
1490+
}
1491+
1492+
static inline int
1493+
PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...)
1494+
{
1495+
va_list vargs;
1496+
va_start(vargs, format);
1497+
PyObject *str = PyUnicode_FromFormatV(format, vargs);
1498+
va_end(vargs);
1499+
if (str == _Py_NULL) {
1500+
return -1;
1501+
}
1502+
1503+
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
1504+
Py_DECREF(str);
1505+
return res;
1506+
}
1507+
#endif // PY_VERSION_HEX < 0x030E0000
13411508

1342-
// gh-116560 added PyLong_GetSign() to Python 3.14a4
1343-
#if PY_VERSION_HEX < 0x030E00A1
1509+
// gh-116560 added PyLong_GetSign() to Python 3.14.0a0
1510+
#if PY_VERSION_HEX < 0x030E00A0
13441511
static inline int PyLong_GetSign(PyObject *obj, int *sign)
13451512
{
13461513
if (!PyLong_Check(obj)) {
@@ -1354,6 +1521,175 @@ static inline int PyLong_GetSign(PyObject *obj, int *sign)
13541521
#endif
13551522

13561523

1524+
// gh-124502 added PyUnicode_Equal() to Python 3.14.0a0
1525+
#if PY_VERSION_HEX < 0x030E00A0
1526+
static inline int PyUnicode_Equal(PyObject *str1, PyObject *str2)
1527+
{
1528+
if (!PyUnicode_Check(str1)) {
1529+
PyErr_Format(PyExc_TypeError, "first argument must be str, not %s",
1530+
Py_TYPE(str1)->tp_name);
1531+
return -1;
1532+
}
1533+
if (!PyUnicode_Check(str2)) {
1534+
PyErr_Format(PyExc_TypeError, "second argument must be str, not %s",
1535+
Py_TYPE(str2)->tp_name);
1536+
return -1;
1537+
}
1538+
1539+
#if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION)
1540+
extern int _PyUnicode_Equal(PyObject *str1, PyObject *str2);
1541+
1542+
return _PyUnicode_Equal(str1, str2);
1543+
#elif PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION)
1544+
return _PyUnicode_EQ(str1, str2);
1545+
#elif PY_VERSION_HEX >= 0x03090000 && defined(PYPY_VERSION)
1546+
return _PyUnicode_EQ(str1, str2);
1547+
#else
1548+
return (PyUnicode_Compare(str1, str2) == 0);
1549+
#endif
1550+
}
1551+
#endif
1552+
1553+
1554+
// gh-121645 added PyBytes_Join() to Python 3.14.0a0
1555+
#if PY_VERSION_HEX < 0x030E00A0
1556+
static inline PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable)
1557+
{
1558+
return _PyBytes_Join(sep, iterable);
1559+
}
1560+
#endif
1561+
1562+
1563+
#if PY_VERSION_HEX < 0x030E00A0
1564+
static inline Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len)
1565+
{
1566+
#if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
1567+
extern Py_hash_t _Py_HashBytes(const void *src, Py_ssize_t len);
1568+
1569+
return _Py_HashBytes(ptr, len);
1570+
#else
1571+
Py_hash_t hash;
1572+
PyObject *bytes = PyBytes_FromStringAndSize((const char*)ptr, len);
1573+
if (bytes == NULL) {
1574+
return -1;
1575+
}
1576+
hash = PyObject_Hash(bytes);
1577+
Py_DECREF(bytes);
1578+
return hash;
1579+
#endif
1580+
}
1581+
#endif
1582+
1583+
1584+
#if PY_VERSION_HEX < 0x030E00A0
1585+
static inline int PyIter_NextItem(PyObject *iter, PyObject **item)
1586+
{
1587+
iternextfunc tp_iternext;
1588+
1589+
assert(iter != NULL);
1590+
assert(item != NULL);
1591+
1592+
tp_iternext = Py_TYPE(iter)->tp_iternext;
1593+
if (tp_iternext == NULL) {
1594+
*item = NULL;
1595+
PyErr_Format(PyExc_TypeError, "expected an iterator, got '%s'",
1596+
Py_TYPE(iter)->tp_name);
1597+
return -1;
1598+
}
1599+
1600+
if ((*item = tp_iternext(iter))) {
1601+
return 1;
1602+
}
1603+
if (!PyErr_Occurred()) {
1604+
return 0;
1605+
}
1606+
if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
1607+
PyErr_Clear();
1608+
return 0;
1609+
}
1610+
return -1;
1611+
}
1612+
#endif
1613+
1614+
1615+
#if PY_VERSION_HEX < 0x030E00A0
1616+
static inline PyObject* PyLong_FromInt32(int32_t value)
1617+
{
1618+
Py_BUILD_ASSERT(sizeof(long) >= 4);
1619+
return PyLong_FromLong(value);
1620+
}
1621+
1622+
static inline PyObject* PyLong_FromInt64(int64_t value)
1623+
{
1624+
Py_BUILD_ASSERT(sizeof(long long) >= 8);
1625+
return PyLong_FromLongLong(value);
1626+
}
1627+
1628+
static inline PyObject* PyLong_FromUInt32(uint32_t value)
1629+
{
1630+
Py_BUILD_ASSERT(sizeof(unsigned long) >= 4);
1631+
return PyLong_FromUnsignedLong(value);
1632+
}
1633+
1634+
static inline PyObject* PyLong_FromUInt64(uint64_t value)
1635+
{
1636+
Py_BUILD_ASSERT(sizeof(unsigned long long) >= 8);
1637+
return PyLong_FromUnsignedLongLong(value);
1638+
}
1639+
1640+
static inline int PyLong_AsInt32(PyObject *obj, int32_t *pvalue)
1641+
{
1642+
Py_BUILD_ASSERT(sizeof(int) == 4);
1643+
int value = PyLong_AsInt(obj);
1644+
if (value == -1 && PyErr_Occurred()) {
1645+
return -1;
1646+
}
1647+
*pvalue = (int32_t)value;
1648+
return 0;
1649+
}
1650+
1651+
static inline int PyLong_AsInt64(PyObject *obj, int64_t *pvalue)
1652+
{
1653+
Py_BUILD_ASSERT(sizeof(long long) == 8);
1654+
long long value = PyLong_AsLongLong(obj);
1655+
if (value == -1 && PyErr_Occurred()) {
1656+
return -1;
1657+
}
1658+
*pvalue = (int64_t)value;
1659+
return 0;
1660+
}
1661+
1662+
static inline int PyLong_AsUInt32(PyObject *obj, uint32_t *pvalue)
1663+
{
1664+
Py_BUILD_ASSERT(sizeof(long) >= 4);
1665+
unsigned long value = PyLong_AsUnsignedLong(obj);
1666+
if (value == (unsigned long)-1 && PyErr_Occurred()) {
1667+
return -1;
1668+
}
1669+
#if SIZEOF_LONG > 4
1670+
if ((unsigned long)UINT32_MAX < value) {
1671+
PyErr_SetString(PyExc_OverflowError,
1672+
"Python int too large to convert to C uint32_t");
1673+
return -1;
1674+
}
1675+
#endif
1676+
*pvalue = (uint32_t)value;
1677+
return 0;
1678+
}
1679+
1680+
static inline int PyLong_AsUInt64(PyObject *obj, uint64_t *pvalue)
1681+
{
1682+
Py_BUILD_ASSERT(sizeof(long long) == 8);
1683+
unsigned long long value = PyLong_AsUnsignedLongLong(obj);
1684+
if (value == (unsigned long long)-1 && PyErr_Occurred()) {
1685+
return -1;
1686+
}
1687+
*pvalue = (uint64_t)value;
1688+
return 0;
1689+
}
1690+
#endif
1691+
1692+
13571693
#ifdef __cplusplus
13581694
}
13591695
#endif

0 commit comments

Comments
 (0)