Matej Cepl
2abad7d325
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:numeric/python-numba?expand=0&rev=98
4128 lines
145 KiB
Diff
4128 lines
145 KiB
Diff
From 3e89582a41fc2712a0ce86528be98cf3dd768a23 Mon Sep 17 00:00:00 2001
|
||
From: Siu Kwan Lam <1929845+sklam@users.noreply.github.com>
|
||
Date: Tue, 16 Jan 2024 14:31:01 -0600
|
||
Subject: [PATCH 01/61] Minimal changes to get compiling
|
||
|
||
Added pythoncapi_compat.h from https://github.com/python/pythoncapi-compat
|
||
---
|
||
numba/_devicearray.cpp | 2 +-
|
||
numba/_dispatcher.cpp | 8 +-
|
||
numba/_dynfunc.c | 12 +-
|
||
numba/_helperlib.c | 4 +-
|
||
numba/_pymodule.h | 4 +
|
||
numba/_typeof.cpp | 8 +
|
||
numba/core/runtime/_nrt_python.c | 2 +-
|
||
numba/experimental/jitclass/_box.c | 2 +-
|
||
numba/mviewbuf.c | 2 +-
|
||
numba/np/ufunc/_internal.c | 4 +-
|
||
numba/pythoncapi_compat.h | 1114 ++++++++++++++++++++++++++++
|
||
setup.py | 2 +-
|
||
12 files changed, 1148 insertions(+), 16 deletions(-)
|
||
create mode 100644 numba/pythoncapi_compat.h
|
||
|
||
Index: numba-0.60.0/numba/_devicearray.cpp
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/_devicearray.cpp
|
||
+++ numba-0.60.0/numba/_devicearray.cpp
|
||
@@ -96,7 +96,7 @@ PyTypeObject DeviceArrayType = {
|
||
/* WARNING: Do not remove this, only modify it! It is a version guard to
|
||
* act as a reminder to update this struct on Python version update! */
|
||
#if (PY_MAJOR_VERSION == 3)
|
||
-#if ! ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12))
|
||
+#if ! (NB_SUPPORTED_PYTHON_MINOR)
|
||
#error "Python minor version is not supported."
|
||
#endif
|
||
#else
|
||
Index: numba-0.60.0/numba/_dispatcher.cpp
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/_dispatcher.cpp
|
||
+++ numba-0.60.0/numba/_dispatcher.cpp
|
||
@@ -27,7 +27,7 @@
|
||
*
|
||
*/
|
||
|
||
-#if (PY_MAJOR_VERSION >= 3) && (PY_MINOR_VERSION == 12)
|
||
+#if (PY_MAJOR_VERSION >= 3) && (PY_MINOR_VERSION == 12) || (PY_MAJOR_VERSION >= 3) && (PY_MINOR_VERSION == 13)
|
||
|
||
#ifndef Py_BUILD_CORE
|
||
#define Py_BUILD_CORE 1
|
||
@@ -39,7 +39,10 @@
|
||
# undef HAVE_STD_ATOMIC
|
||
#endif
|
||
#undef _PyGC_FINALIZED
|
||
-#include "internal/pycore_atomic.h"
|
||
+
|
||
+#if (PY_MINOR_VERSION == 12)
|
||
+ #include "internal/pycore_atomic.h"
|
||
+#endif
|
||
#include "internal/pycore_interp.h"
|
||
#include "internal/pycore_pyerrors.h"
|
||
#include "internal/pycore_instruments.h"
|
||
@@ -780,7 +783,7 @@ call_cfunc(Dispatcher *self, PyObject *c
|
||
}
|
||
}
|
||
|
||
-#elif (PY_MAJOR_VERSION >= 3) && (PY_MINOR_VERSION == 12)
|
||
+#elif (PY_MAJOR_VERSION >= 3) && ((PY_MINOR_VERSION == 12) || (PY_MINOR_VERSION == 13))
|
||
|
||
// Python 3.12 has a completely new approach to tracing and profiling due to
|
||
// the new `sys.monitoring` system.
|
||
@@ -1589,7 +1592,7 @@ static PyTypeObject DispatcherType = {
|
||
0, /* tp_version_tag */
|
||
0, /* tp_finalize */
|
||
0, /* tp_vectorcall */
|
||
-#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION == 12)
|
||
+#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION == 12) || (PY_MAJOR_VERSION >= 3) && (PY_MINOR_VERSION == 13)
|
||
/* This was introduced first in 3.12
|
||
* https://github.com/python/cpython/issues/91051
|
||
*/
|
||
@@ -1599,7 +1602,7 @@ static PyTypeObject DispatcherType = {
|
||
/* WARNING: Do not remove this, only modify it! It is a version guard to
|
||
* act as a reminder to update this struct on Python version update! */
|
||
#if (PY_MAJOR_VERSION == 3)
|
||
-#if ! ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12))
|
||
+#if ! (NB_SUPPORTED_PYTHON_MINOR)
|
||
#error "Python minor version is not supported."
|
||
#endif
|
||
#else
|
||
Index: numba-0.60.0/numba/_dynfunc.c
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/_dynfunc.c
|
||
+++ numba-0.60.0/numba/_dynfunc.c
|
||
@@ -7,6 +7,12 @@
|
||
|
||
#include <string.h>
|
||
|
||
+
|
||
+// if python version is 3.13
|
||
+#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION == 13)
|
||
+ #include "pythoncapi_compat.h"
|
||
+ #define _Py_IsFinalizing Py_IsFinalizing
|
||
+#endif
|
||
/* NOTE: EnvironmentObject and ClosureObject must be kept in sync with
|
||
* the definitions in numba/targets/base.py (EnvBody and ClosureBody).
|
||
*/
|
||
@@ -146,7 +152,7 @@ static PyTypeObject EnvironmentType = {
|
||
/* WARNING: Do not remove this, only modify it! It is a version guard to
|
||
* act as a reminder to update this struct on Python version update! */
|
||
#if (PY_MAJOR_VERSION == 3)
|
||
-#if ! ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12))
|
||
+#if ! (NB_SUPPORTED_PYTHON_MINOR)
|
||
#error "Python minor version is not supported."
|
||
#endif
|
||
#else
|
||
@@ -265,7 +271,7 @@ static PyTypeObject ClosureType = {
|
||
/* WARNING: Do not remove this, only modify it! It is a version guard to
|
||
* act as a reminder to update this struct on Python version update! */
|
||
#if (PY_MAJOR_VERSION == 3)
|
||
-#if ! ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12))
|
||
+#if ! (NB_SUPPORTED_PYTHON_MINOR)
|
||
#error "Python minor version is not supported."
|
||
#endif
|
||
#else
|
||
@@ -485,7 +491,7 @@ static PyTypeObject GeneratorType = {
|
||
/* WARNING: Do not remove this, only modify it! It is a version guard to
|
||
* act as a reminder to update this struct on Python version update! */
|
||
#if (PY_MAJOR_VERSION == 3)
|
||
-#if ! ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12))
|
||
+#if ! (NB_SUPPORTED_PYTHON_MINOR)
|
||
#error "Python minor version is not supported."
|
||
#endif
|
||
#else
|
||
Index: numba-0.60.0/numba/_helperlib.c
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/_helperlib.c
|
||
+++ numba-0.60.0/numba/_helperlib.c
|
||
@@ -293,7 +293,7 @@ numba_recreate_record(void *pdata, int s
|
||
return NULL;
|
||
}
|
||
|
||
- numpy = PyImport_ImportModuleNoBlock("numpy");
|
||
+ numpy = PyImport_ImportModule("numpy");
|
||
if (!numpy) goto CLEANUP;
|
||
|
||
numpy_record = PyObject_GetAttrString(numpy, "record");
|
||
@@ -833,7 +833,7 @@ static void traceback_add(const char *fu
|
||
if (!frame)
|
||
goto error;
|
||
|
||
-#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION == 12) /* 3.12 */
|
||
+#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION == 12) || (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION == 13) /* 3.12 or 3.13 */
|
||
#elif (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION == 11) /* 3.11 */
|
||
|
||
/* unsafe cast to our copy of _frame to access the f_lineno field */
|
||
@@ -851,7 +851,7 @@ static void traceback_add(const char *fu
|
||
Py_DECREF(frame);
|
||
return;
|
||
|
||
-#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION == 12) /* 3.12 */
|
||
+#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION == 12) || (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION == 13) /* 3.12 or 3.13 */
|
||
error:
|
||
_PyErr_ChainExceptions1(exc);
|
||
#elif (PY_MAJOR_VERSION == 3) && ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11)) /* 3.11 and below */
|
||
Index: numba-0.60.0/numba/_pymodule.h
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/_pymodule.h
|
||
+++ numba-0.60.0/numba/_pymodule.h
|
||
@@ -29,4 +29,7 @@
|
||
PyObject_SetAttrString(m, #name, tmp); \
|
||
Py_DECREF(tmp); } while (0)
|
||
|
||
+
|
||
+#define NB_SUPPORTED_PYTHON_MINOR ((PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12) || (PY_MINOR_VERSION == 13))
|
||
+
|
||
#endif /* NUMBA_PY_MODULE_H_ */
|
||
Index: numba-0.60.0/numba/_typeof.cpp
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/_typeof.cpp
|
||
+++ numba-0.60.0/numba/_typeof.cpp
|
||
@@ -16,6 +16,14 @@
|
||
#include <numpy/npy_2_compat.h>
|
||
#endif
|
||
|
||
+#if (PY_MAJOR_VERSION >= 3) && (PY_MINOR_VERSION == 13)
|
||
+ #ifndef Py_BUILD_CORE
|
||
+ #define Py_BUILD_CORE 1
|
||
+ #endif
|
||
+ #include "internal/pycore_setobject.h" // _PySet_NextEntry()
|
||
+#endif
|
||
+
|
||
+
|
||
/* Cached typecodes for basic scalar types */
|
||
static int tc_int8;
|
||
static int tc_int16;
|
||
Index: numba-0.60.0/numba/core/runtime/_nrt_python.c
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/runtime/_nrt_python.c
|
||
+++ numba-0.60.0/numba/core/runtime/_nrt_python.c
|
||
@@ -229,7 +229,7 @@ static PyTypeObject MemInfoType = {
|
||
/* WARNING: Do not remove this, only modify it! It is a version guard to
|
||
* act as a reminder to update this struct on Python version update! */
|
||
#if (PY_MAJOR_VERSION == 3)
|
||
-#if ! ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12))
|
||
+#if ! (NB_SUPPORTED_PYTHON_MINOR)
|
||
#error "Python minor version is not supported."
|
||
#endif
|
||
#else
|
||
Index: numba-0.60.0/numba/experimental/jitclass/_box.c
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/experimental/jitclass/_box.c
|
||
+++ numba-0.60.0/numba/experimental/jitclass/_box.c
|
||
@@ -110,7 +110,7 @@ static PyTypeObject BoxType = {
|
||
/* WARNING: Do not remove this, only modify it! It is a version guard to
|
||
* act as a reminder to update this struct on Python version update! */
|
||
#if (PY_MAJOR_VERSION == 3)
|
||
-#if ! ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12))
|
||
+#if ! (NB_SUPPORTED_PYTHON_MINOR)
|
||
#error "Python minor version is not supported."
|
||
#endif
|
||
#else
|
||
Index: numba-0.60.0/numba/mviewbuf.c
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/mviewbuf.c
|
||
+++ numba-0.60.0/numba/mviewbuf.c
|
||
@@ -344,7 +344,7 @@ static PyTypeObject MemAllocType = {
|
||
/* WARNING: Do not remove this, only modify it! It is a version guard to
|
||
* act as a reminder to update this struct on Python version update! */
|
||
#if (PY_MAJOR_VERSION == 3)
|
||
-#if ! ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12))
|
||
+#if ! (NB_SUPPORTED_PYTHON_MINOR)
|
||
#error "Python minor version is not supported."
|
||
#endif
|
||
#else
|
||
Index: numba-0.60.0/numba/np/ufunc/_internal.c
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/np/ufunc/_internal.c
|
||
+++ numba-0.60.0/numba/np/ufunc/_internal.c
|
||
@@ -100,7 +100,7 @@ PyTypeObject PyUFuncCleaner_Type = {
|
||
/* WARNING: Do not remove this, only modify it! It is a version guard to
|
||
* act as a reminder to update this struct on Python version update! */
|
||
#if (PY_MAJOR_VERSION == 3)
|
||
-#if ! ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12))
|
||
+#if ! (NB_SUPPORTED_PYTHON_MINOR)
|
||
#error "Python minor version is not supported."
|
||
#endif
|
||
#else
|
||
@@ -753,7 +753,7 @@ PyTypeObject PyDUFunc_Type = {
|
||
/* WARNING: Do not remove this, only modify it! It is a version guard to
|
||
* act as a reminder to update this struct on Python version update! */
|
||
#if (PY_MAJOR_VERSION == 3)
|
||
-#if ! ((PY_MINOR_VERSION == 9) || (PY_MINOR_VERSION == 10) || (PY_MINOR_VERSION == 11) || (PY_MINOR_VERSION == 12))
|
||
+#if ! (NB_SUPPORTED_PYTHON_MINOR)
|
||
#error "Python minor version is not supported."
|
||
#endif
|
||
#else
|
||
Index: numba-0.60.0/numba/core/bytecode.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/bytecode.py
|
||
+++ numba-0.60.0/numba/core/bytecode.py
|
||
@@ -9,7 +9,7 @@ from numba.core import errors, utils, se
|
||
from numba.core.utils import PYVERSION
|
||
|
||
|
||
-if PYVERSION in ((3, 12), ):
|
||
+if PYVERSION in ((3, 12), (3, 13)):
|
||
from opcode import _inline_cache_entries
|
||
# Instruction/opcode length in bytes
|
||
INSTR_LEN = 2
|
||
@@ -104,7 +104,12 @@ class ByteCodeInst(object):
|
||
# https://bugs.python.org/issue27129
|
||
# https://github.com/python/cpython/pull/25069
|
||
assert self.is_jump
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ if self.opcode in (dis.opmap[k]
|
||
+ for k in ["JUMP_BACKWARD",
|
||
+ "JUMP_BACKWARD_NO_INTERRUPT"]):
|
||
+ return self.next - (self.arg * 2)
|
||
+ elif PYVERSION in ((3, 12),):
|
||
if self.opcode in (dis.opmap[k]
|
||
for k in ["JUMP_BACKWARD"]):
|
||
return self.offset - (self.arg - 1) * 2
|
||
@@ -121,7 +126,7 @@ class ByteCodeInst(object):
|
||
else:
|
||
raise NotImplementedError(PYVERSION)
|
||
|
||
- if PYVERSION in ((3, 10), (3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)):
|
||
if self.opcode in JREL_OPS:
|
||
return self.next + self.arg * 2
|
||
else:
|
||
@@ -160,7 +165,7 @@ OPCODE_NOP = dis.opname.index('NOP')
|
||
|
||
|
||
# Adapted from Lib/dis.py
|
||
-def _unpack_opargs(code):
|
||
+def _unpack_opargs_pre_3_13(code):
|
||
"""
|
||
Returns a 4-int-tuple of
|
||
(bytecode offset, opcode, argument, offset of next bytecode).
|
||
@@ -176,7 +181,7 @@ def _unpack_opargs(code):
|
||
for j in range(ARG_LEN):
|
||
arg |= code[i + j] << (8 * j)
|
||
i += ARG_LEN
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12),):
|
||
# Python 3.12 introduced cache slots. We need to account for
|
||
# cache slots when we determine the offset of the next opcode.
|
||
# The number of cache slots is specific to each opcode and can
|
||
@@ -200,7 +205,7 @@ def _unpack_opargs(code):
|
||
else:
|
||
arg = None
|
||
i += NO_ARG_LEN
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12),):
|
||
# Python 3.12 introduced cache slots. We need to account for
|
||
# cache slots when we determine the offset of the next opcode.
|
||
# The number of cache slots is specific to each opcode and can
|
||
@@ -216,6 +221,80 @@ def _unpack_opargs(code):
|
||
offset = i # Mark inst offset at first extended
|
||
|
||
|
||
+# Adapted from Lib/dis.py
|
||
+def _unpack_opargs_pre_3_13(code):
|
||
+ """
|
||
+ Returns a 4-int-tuple of
|
||
+ (bytecode offset, opcode, argument, offset of next bytecode).
|
||
+ """
|
||
+ extended_arg = 0
|
||
+ n = len(code)
|
||
+ offset = i = 0
|
||
+ while i < n:
|
||
+ op = code[i]
|
||
+ i += CODE_LEN
|
||
+ if op >= HAVE_ARGUMENT:
|
||
+ arg = code[i] | extended_arg
|
||
+ for j in range(ARG_LEN):
|
||
+ arg |= code[i + j] << (8 * j)
|
||
+ i += ARG_LEN
|
||
+ if PYVERSION in ((3, 12),):
|
||
+ # Python 3.12 introduced cache slots. We need to account for
|
||
+ # cache slots when we determine the offset of the next opcode.
|
||
+ # The number of cache slots is specific to each opcode and can
|
||
+ # be looked up in the _inline_cache_entries dictionary.
|
||
+ i += _inline_cache_entries[op] * INSTR_LEN
|
||
+ elif PYVERSION in ((3, 10), (3, 11)):
|
||
+ pass
|
||
+ else:
|
||
+ raise NotImplementedError(PYVERSION)
|
||
+ if op == EXTENDED_ARG:
|
||
+ # This is a deviation from what dis does...
|
||
+ # In python 3.11 it seems like EXTENDED_ARGs appear more often
|
||
+ # and are also used as jump targets. So as to not have to do
|
||
+ # "book keeping" for where EXTENDED_ARGs have been "skipped"
|
||
+ # they are replaced with NOPs so as to provide a legal jump
|
||
+ # target and also ensure that the bytecode offsets are correct.
|
||
+ yield (offset, OPCODE_NOP, arg, i)
|
||
+ extended_arg = arg << 8 * ARG_LEN
|
||
+ offset = i
|
||
+ continue
|
||
+ else:
|
||
+ arg = None
|
||
+ i += NO_ARG_LEN
|
||
+ if PYVERSION in ((3, 12),):
|
||
+ # Python 3.12 introduced cache slots. We need to account for
|
||
+ # cache slots when we determine the offset of the next opcode.
|
||
+ # The number of cache slots is specific to each opcode and can
|
||
+ # be looked up in the _inline_cache_entries dictionary.
|
||
+ i += _inline_cache_entries[op] * INSTR_LEN
|
||
+ elif PYVERSION in ((3, 10), (3, 11)):
|
||
+ pass
|
||
+ else:
|
||
+ raise NotImplementedError(PYVERSION)
|
||
+
|
||
+ extended_arg = 0
|
||
+ yield (offset, op, arg, i)
|
||
+ offset = i # Mark inst offset at first extended
|
||
+
|
||
+
|
||
+if PYVERSION in ((3, 13),):
|
||
+
|
||
+ def _unpack_opargs(code):
|
||
+ buf = []
|
||
+ for i, start_offset, op, arg in dis._unpack_opargs(code):
|
||
+ buf.append((start_offset, op, arg))
|
||
+ for i, (start_offset, op, arg) in enumerate(buf):
|
||
+ if i + 1 < len(buf):
|
||
+ next_offset = buf[i + 1][0]
|
||
+ else:
|
||
+ next_offset = len(code)
|
||
+ yield (start_offset, op, arg, next_offset)
|
||
+
|
||
+else:
|
||
+ _unpack_opargs = _unpack_opargs_pre_3_13
|
||
+
|
||
+
|
||
def _patched_opargs(bc_stream):
|
||
"""Patch the bytecode stream.
|
||
|
||
@@ -298,7 +377,7 @@ class _ByteCode(object):
|
||
# Start with first bytecode's lineno
|
||
known = code.co_firstlineno
|
||
for inst in table.values():
|
||
- if inst.lineno >= 0:
|
||
+ if inst.lineno is not None and inst.lineno >= 0:
|
||
known = inst.lineno
|
||
else:
|
||
inst.lineno = known
|
||
@@ -363,7 +442,7 @@ class _ByteCode(object):
|
||
|
||
|
||
def _fix_LOAD_GLOBAL_arg(arg):
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
return arg >> 1
|
||
elif PYVERSION in ((3, 9), (3, 10)):
|
||
return arg
|
||
@@ -452,8 +531,15 @@ class ByteCodePy312(ByteCodePy311):
|
||
entirely along with the dead exceptions that it points to.
|
||
A pair of exception that sandwiches these exception will
|
||
also be merged into a single exception.
|
||
- """
|
||
|
||
+ Update for Python 3.13, the ending of the pattern has a extra
|
||
+ POP_TOP:
|
||
+
|
||
+ ...
|
||
+ END_FOR
|
||
+ POP_TOP
|
||
+ SWAP(2)
|
||
+ """
|
||
def pop_and_merge_exceptions(entries: list,
|
||
entry_to_remove: _ExceptionTableEntry):
|
||
lower_entry_idx = entries.index(entry_to_remove) - 1
|
||
@@ -505,17 +591,34 @@ class ByteCodePy312(ByteCodePy311):
|
||
if not next_inst.opname == "FOR_ITER":
|
||
continue
|
||
|
||
- # Check end of pattern, two instructions.
|
||
- # Check for the corresponding END_FOR, exception table end is
|
||
- # non-inclusive, so subtract one.
|
||
- index = self.ordered_offsets.index(entry.end)
|
||
- curr_inst = self.table[self.ordered_offsets[index - 1]]
|
||
- if not curr_inst.opname == "END_FOR":
|
||
- continue
|
||
- # END_FOR must be followed by SWAP(2)
|
||
- next_inst = self.table[self.ordered_offsets[index]]
|
||
- if not next_inst.opname == "SWAP" and next_inst.arg == 2:
|
||
- continue
|
||
+ if PYVERSION == (3, 13):
|
||
+ # Check end of pattern, two instructions.
|
||
+ # Check for the corresponding END_FOR, exception table end
|
||
+ # is non-inclusive, so subtract one.
|
||
+ index = self.ordered_offsets.index(entry.end)
|
||
+ curr_inst = self.table[self.ordered_offsets[index - 2]]
|
||
+ if not curr_inst.opname == "END_FOR":
|
||
+ continue
|
||
+ next_inst = self.table[self.ordered_offsets[index - 1]]
|
||
+ if not next_inst.opname == "POP_TOP":
|
||
+ continue
|
||
+ # END_FOR must be followed by SWAP(2)
|
||
+ next_inst = self.table[self.ordered_offsets[index]]
|
||
+ if not next_inst.opname == "SWAP" and next_inst.arg == 2:
|
||
+ continue
|
||
+ else:
|
||
+ assert PYVERSION < (3, 13)
|
||
+ # Check end of pattern, two instructions.
|
||
+ # Check for the corresponding END_FOR, exception table end
|
||
+ # is non-inclusive, so subtract one.
|
||
+ index = self.ordered_offsets.index(entry.end)
|
||
+ curr_inst = self.table[self.ordered_offsets[index - 1]]
|
||
+ if not curr_inst.opname == "END_FOR":
|
||
+ continue
|
||
+ # END_FOR must be followed by SWAP(2)
|
||
+ next_inst = self.table[self.ordered_offsets[index]]
|
||
+ if not next_inst.opname == "SWAP" and next_inst.arg == 2:
|
||
+ continue
|
||
# If all conditions are met that means this exception entry
|
||
# is for a list/dict/set comprehension and can be removed.
|
||
# Also if there exist exception entries above and below this
|
||
@@ -528,7 +631,7 @@ class ByteCodePy312(ByteCodePy311):
|
||
|
||
if PYVERSION == (3, 11):
|
||
ByteCode = ByteCodePy311
|
||
-elif PYVERSION == (3, 12):
|
||
+elif PYVERSION in ((3, 12), (3, 13),):
|
||
ByteCode = ByteCodePy312
|
||
elif PYVERSION < (3, 11):
|
||
ByteCode = _ByteCode
|
||
Index: numba-0.60.0/numba/core/byteflow.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/byteflow.py
|
||
+++ numba-0.60.0/numba/core/byteflow.py
|
||
@@ -10,7 +10,7 @@ from functools import total_ordering
|
||
from numba.core.utils import UniqueDict, PYVERSION, ALL_BINOPS_TO_OPERATORS
|
||
from numba.core.controlflow import NEW_BLOCKERS, CFGraph
|
||
from numba.core.ir import Loc
|
||
-from numba.core.errors import UnsupportedError
|
||
+from numba.core.errors import UnsupportedBytecodeError
|
||
|
||
|
||
_logger = logging.getLogger(__name__)
|
||
@@ -24,7 +24,7 @@ _NO_RAISE_OPS = frozenset({
|
||
'PRECALL',
|
||
})
|
||
|
||
-if PYVERSION in ((3, 12), ):
|
||
+if PYVERSION in ((3, 12), (3, 13)):
|
||
from enum import Enum
|
||
|
||
# Operands for CALL_INTRINSIC_1
|
||
@@ -149,7 +149,7 @@ class Flow(object):
|
||
self.block_infos[state.pc_initial] = si = adapt_state_infos(state)
|
||
_logger.debug("block_infos %s:\n%s", state, si)
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
def _run_handle_exception(self, runner, state):
|
||
if not state.in_with() and (
|
||
state.has_active_try() and
|
||
@@ -312,7 +312,7 @@ class Flow(object):
|
||
msg = ("The 'with (context manager) as "
|
||
"(variable):' construct is not "
|
||
"supported.")
|
||
- raise UnsupportedError(msg)
|
||
+ raise UnsupportedBytecodeError(msg)
|
||
|
||
|
||
def _is_null_temp_reg(reg):
|
||
@@ -331,7 +331,7 @@ class TraceRunner(object):
|
||
return Loc(self.debug_filename, lineno)
|
||
|
||
def dispatch(self, state):
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
if state._blockstack:
|
||
state: State
|
||
while state._blockstack:
|
||
@@ -354,7 +354,8 @@ class TraceRunner(object):
|
||
fn(state, inst)
|
||
else:
|
||
msg = "Use of unsupported opcode (%s) found" % inst.opname
|
||
- raise UnsupportedError(msg, loc=self.get_debug_loc(inst.lineno))
|
||
+ raise UnsupportedBytecodeError(msg,
|
||
+ loc=self.get_debug_loc(inst.lineno))
|
||
|
||
def _adjust_except_stack(self, state):
|
||
"""
|
||
@@ -405,6 +406,15 @@ class TraceRunner(object):
|
||
state.push(state.make_temp())
|
||
state.append(inst)
|
||
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ def op_FORMAT_SIMPLE(self, state, inst):
|
||
+ assert PYVERSION == (3, 13)
|
||
+ value = state.pop()
|
||
+ strvar = state.make_temp()
|
||
+ res = state.make_temp()
|
||
+ state.append(inst, value=value, res=res, strvar=strvar)
|
||
+ state.push(res)
|
||
+
|
||
def op_FORMAT_VALUE(self, state, inst):
|
||
"""
|
||
FORMAT_VALUE(flags): flags argument specifies format spec which is
|
||
@@ -415,7 +425,8 @@ class TraceRunner(object):
|
||
"""
|
||
if inst.arg != 0:
|
||
msg = "format spec in f-strings not supported yet"
|
||
- raise UnsupportedError(msg, loc=self.get_debug_loc(inst.lineno))
|
||
+ raise UnsupportedBytecodeError(msg,
|
||
+ loc=self.get_debug_loc(inst.lineno))
|
||
value = state.pop()
|
||
strvar = state.make_temp()
|
||
res = state.make_temp()
|
||
@@ -442,7 +453,27 @@ class TraceRunner(object):
|
||
def op_POP_TOP(self, state, inst):
|
||
state.pop()
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ def op_TO_BOOL(self, state, inst):
|
||
+ res = state.make_temp()
|
||
+ tos = state.pop()
|
||
+ state.append(inst, val=tos, res=res)
|
||
+ state.push(res)
|
||
+
|
||
+ elif PYVERSION < (3, 13):
|
||
+ pass
|
||
+
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ def op_LOAD_GLOBAL(self, state, inst):
|
||
+ # Ordering of the global value and NULL is swapped in Py3.13
|
||
+ res = state.make_temp()
|
||
+ idx = inst.arg >> 1
|
||
+ state.append(inst, idx=idx, res=res)
|
||
+ state.push(res)
|
||
+ # ignoring the NULL
|
||
+ if inst.arg & 1:
|
||
+ state.push(state.make_null())
|
||
+ elif PYVERSION in ((3, 11), (3, 12)):
|
||
def op_LOAD_GLOBAL(self, state, inst):
|
||
res = state.make_temp()
|
||
idx = inst.arg >> 1
|
||
@@ -471,30 +502,89 @@ class TraceRunner(object):
|
||
state.push(res)
|
||
|
||
def op_LOAD_CONST(self, state, inst):
|
||
- res = state.make_temp("const")
|
||
+ # append const index for interpreter to read the const value
|
||
+ res = state.make_temp("const") + f".{inst.arg}"
|
||
state.push(res)
|
||
state.append(inst, res=res)
|
||
|
||
def op_LOAD_ATTR(self, state, inst):
|
||
item = state.pop()
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ res = state.make_temp()
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ state.push(res) # the attr
|
||
+ if inst.arg & 1:
|
||
+ state.push(state.make_null())
|
||
+ elif PYVERSION in ((3, 12),):
|
||
if inst.arg & 1:
|
||
state.push(state.make_null())
|
||
+ state.push(res)
|
||
elif PYVERSION in ((3, 9), (3, 10), (3, 11)):
|
||
- pass
|
||
+ state.push(res)
|
||
else:
|
||
raise NotImplementedError(PYVERSION)
|
||
- res = state.make_temp()
|
||
state.append(inst, item=item, res=res)
|
||
- state.push(res)
|
||
|
||
def op_LOAD_FAST(self, state, inst):
|
||
- name = state.get_varname(inst)
|
||
+ assert PYVERSION <= (3, 13)
|
||
+ if PYVERSION in ((3, 13), ):
|
||
+ try:
|
||
+ name = state.get_varname(inst)
|
||
+ except IndexError: # oparg is out of range
|
||
+ # Handle this like a LOAD_DEREF
|
||
+ # Assume MAKE_CELL and COPY_FREE_VARS has correctly setup the
|
||
+ # states.
|
||
+ # According to https://github.com/python/cpython/blob/9ac606080a0074cdf7589d9b7c9413a73e0ddf37/Objects/codeobject.c#L730C9-L759 # noqa E501
|
||
+ # localsplus is locals + cells + freevars
|
||
+ bc = state._bytecode
|
||
+ num_varnames = len(bc.co_varnames)
|
||
+ num_freevars = len(bc.co_freevars)
|
||
+ num_cellvars = len(bc.co_cellvars)
|
||
+ max_fast_local = num_cellvars + num_freevars
|
||
+ assert 0 <= inst.arg - num_varnames < max_fast_local
|
||
+ res = state.make_temp()
|
||
+ state.append(inst, res=res, as_load_deref=True)
|
||
+ state.push(res)
|
||
+ return
|
||
+ else:
|
||
+ name = state.get_varname(inst)
|
||
res = state.make_temp(name)
|
||
state.append(inst, res=res)
|
||
state.push(res)
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ def op_LOAD_FAST_LOAD_FAST(self, state, inst):
|
||
+ oparg = inst.arg
|
||
+ oparg1 = oparg >> 4
|
||
+ oparg2 = oparg & 15
|
||
+ name1 = state.get_varname_by_arg(oparg1)
|
||
+ name2 = state.get_varname_by_arg(oparg2)
|
||
+ res1 = state.make_temp(name1)
|
||
+ res2 = state.make_temp(name2)
|
||
+ state.append(inst, res1=res1, res2=res2)
|
||
+ state.push(res1)
|
||
+ state.push(res2)
|
||
+
|
||
+ def op_STORE_FAST_LOAD_FAST(self, state, inst):
|
||
+ oparg = inst.arg
|
||
+ # oparg1 = oparg >> 4 # not needed
|
||
+ oparg2 = oparg & 15
|
||
+ store_value = state.pop()
|
||
+ load_name = state.get_varname_by_arg(oparg2)
|
||
+ load_res = state.make_temp(load_name)
|
||
+ state.append(inst, store_value=store_value, load_res=load_res)
|
||
+ state.push(load_res)
|
||
+
|
||
+ def op_STORE_FAST_STORE_FAST(self, state, inst):
|
||
+ value1 = state.pop()
|
||
+ value2 = state.pop()
|
||
+ state.append(inst, value1=value1, value2=value2)
|
||
+
|
||
+ elif PYVERSION in ((3, 10), (3, 11), (3, 12)):
|
||
+ pass
|
||
+ else:
|
||
+ raise NotImplementedError(PYVERSION)
|
||
+
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
op_LOAD_FAST_CHECK = op_LOAD_FAST
|
||
op_LOAD_FAST_AND_CLEAR = op_LOAD_FAST
|
||
elif PYVERSION in ((3, 9), (3, 10), (3, 11)):
|
||
@@ -753,7 +843,7 @@ class TraceRunner(object):
|
||
)
|
||
state.push(res)
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
def op_BINARY_SLICE(self, state, inst):
|
||
end = state.pop()
|
||
start = state.pop()
|
||
@@ -771,7 +861,7 @@ class TraceRunner(object):
|
||
else:
|
||
raise NotImplementedError(PYVERSION)
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
def op_STORE_SLICE(self, state, inst):
|
||
end = state.pop()
|
||
start = state.pop()
|
||
@@ -804,7 +894,7 @@ class TraceRunner(object):
|
||
op_POP_JUMP_IF_TRUE = _op_POP_JUMP_IF
|
||
op_POP_JUMP_IF_FALSE = _op_POP_JUMP_IF
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
op_POP_JUMP_IF_NONE = _op_POP_JUMP_IF
|
||
op_POP_JUMP_IF_NOT_NONE = _op_POP_JUMP_IF
|
||
elif PYVERSION in ((3, 9), (3, 10), (3, 11)):
|
||
@@ -853,6 +943,8 @@ class TraceRunner(object):
|
||
state.append(inst)
|
||
state.fork(pc=inst.get_jump_target())
|
||
|
||
+ op_JUMP_BACKWARD_NO_INTERRUPT = op_JUMP_BACKWARD
|
||
+
|
||
def op_JUMP_ABSOLUTE(self, state, inst):
|
||
state.append(inst)
|
||
state.fork(pc=inst.get_jump_target())
|
||
@@ -868,7 +960,7 @@ class TraceRunner(object):
|
||
state.append(inst, retval=state.pop(), castval=state.make_temp())
|
||
state.terminate()
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
def op_RETURN_CONST(self, state, inst):
|
||
res = state.make_temp("const")
|
||
state.append(inst, retval=res, castval=state.make_temp())
|
||
@@ -884,14 +976,14 @@ class TraceRunner(object):
|
||
state.append(inst, value=val, res=res)
|
||
state.push(res)
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
def op_RAISE_VARARGS(self, state, inst):
|
||
if inst.arg == 0:
|
||
exc = None
|
||
# No re-raising within a try-except block.
|
||
# But we allow bare reraise.
|
||
if state.has_active_try():
|
||
- raise UnsupportedError(
|
||
+ raise UnsupportedBytecodeError(
|
||
"The re-raising of an exception is not yet supported.",
|
||
loc=self.get_debug_loc(inst.lineno),
|
||
)
|
||
@@ -915,7 +1007,7 @@ class TraceRunner(object):
|
||
if inst.arg == 0:
|
||
exc = None
|
||
if in_exc_block:
|
||
- raise UnsupportedError(
|
||
+ raise UnsupportedBytecodeError(
|
||
"The re-raising of an exception is not yet supported.",
|
||
loc=self.get_debug_loc(inst.lineno),
|
||
)
|
||
@@ -940,7 +1032,10 @@ class TraceRunner(object):
|
||
blk = state.pop_block()
|
||
state.reset_stack(blk['entry_stack'])
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ def op_END_FOR(self, state, inst):
|
||
+ state.pop()
|
||
+ elif PYVERSION in ((3, 12),):
|
||
def op_END_FOR(self, state, inst):
|
||
state.pop()
|
||
state.pop()
|
||
@@ -954,7 +1049,8 @@ class TraceRunner(object):
|
||
if inst.arg != 0:
|
||
msg = ('Unsupported use of a bytecode related to try..finally'
|
||
' or a with-context')
|
||
- raise UnsupportedError(msg, loc=self.get_debug_loc(inst.lineno))
|
||
+ raise UnsupportedBytecodeError(msg,
|
||
+ loc=self.get_debug_loc(inst.lineno))
|
||
|
||
def op_CALL_FINALLY(self, state, inst):
|
||
pass
|
||
@@ -1068,7 +1164,7 @@ class TraceRunner(object):
|
||
'FINALLY', state, next=inst.next, end=inst.get_jump_target(),
|
||
)
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
def op_POP_EXCEPT(self, state, inst):
|
||
state.pop()
|
||
|
||
@@ -1076,7 +1172,7 @@ class TraceRunner(object):
|
||
def op_POP_EXCEPT(self, state, inst):
|
||
blk = state.pop_block()
|
||
if blk['kind'] not in {BlockKind('EXCEPT'), BlockKind('FINALLY')}:
|
||
- raise UnsupportedError(
|
||
+ raise UnsupportedBytecodeError(
|
||
f"POP_EXCEPT got an unexpected block: {blk['kind']}",
|
||
loc=self.get_debug_loc(inst.lineno),
|
||
)
|
||
@@ -1117,16 +1213,24 @@ class TraceRunner(object):
|
||
def op_CALL(self, state, inst):
|
||
narg = inst.arg
|
||
args = list(reversed([state.pop() for _ in range(narg)]))
|
||
- callable_or_firstarg = state.pop()
|
||
- null_or_callable = state.pop()
|
||
- if _is_null_temp_reg(null_or_callable):
|
||
- callable = callable_or_firstarg
|
||
- else:
|
||
- callable = null_or_callable
|
||
- args = [callable_or_firstarg, *args]
|
||
+ if PYVERSION == (3, 13):
|
||
+ null_or_self = state.pop()
|
||
+ # position of the callable is fixed
|
||
+ callable = state.pop()
|
||
+ if not _is_null_temp_reg(null_or_self):
|
||
+ args = [null_or_self, *args]
|
||
+ kw_names = None
|
||
+ elif PYVERSION < (3, 13):
|
||
+ callable_or_firstarg = state.pop()
|
||
+ null_or_callable = state.pop()
|
||
+ if _is_null_temp_reg(null_or_callable):
|
||
+ callable = callable_or_firstarg
|
||
+ else:
|
||
+ callable = null_or_callable
|
||
+ args = [callable_or_firstarg, *args]
|
||
+ kw_names = state.pop_kw_names()
|
||
res = state.make_temp()
|
||
|
||
- kw_names = state.pop_kw_names()
|
||
state.append(inst, func=callable, args=args, kw_names=kw_names, res=res)
|
||
state.push(res)
|
||
|
||
@@ -1152,28 +1256,67 @@ class TraceRunner(object):
|
||
state.append(inst, func=func, args=args, names=names, res=res)
|
||
state.push(res)
|
||
|
||
- def op_CALL_FUNCTION_EX(self, state, inst):
|
||
- if inst.arg & 1 and PYVERSION < (3, 10):
|
||
- errmsg = "CALL_FUNCTION_EX with **kwargs not supported"
|
||
- raise UnsupportedError(errmsg)
|
||
- if inst.arg & 1:
|
||
- varkwarg = state.pop()
|
||
- else:
|
||
- varkwarg = None
|
||
- vararg = state.pop()
|
||
- func = state.pop()
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ def op_CALL_KW(self, state, inst):
|
||
+ narg = inst.arg
|
||
+ kw_names = state.pop()
|
||
+ args = list(reversed([state.pop() for _ in range(narg)]))
|
||
+ null_or_firstarg = state.pop()
|
||
+ callable = state.pop()
|
||
+ if not _is_null_temp_reg(null_or_firstarg):
|
||
+ args = [null_or_firstarg, *args]
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
- if _is_null_temp_reg(state.peek(1)):
|
||
- state.pop() # pop NULL, it's not used
|
||
- elif PYVERSION in ((3, 9), (3, 10)):
|
||
- pass
|
||
- else:
|
||
- raise NotImplementedError(PYVERSION)
|
||
+ res = state.make_temp()
|
||
+ state.append(inst, func=callable, args=args, kw_names=kw_names,
|
||
+ res=res)
|
||
+ state.push(res)
|
||
|
||
- res = state.make_temp()
|
||
- state.append(inst, func=func, vararg=vararg, varkwarg=varkwarg, res=res)
|
||
- state.push(res)
|
||
+ elif PYVERSION in ((3, 10), (3, 11), (3, 12)):
|
||
+ pass
|
||
+ else:
|
||
+ raise NotImplementedError(PYVERSION)
|
||
+
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ def op_CALL_FUNCTION_EX(self, state, inst):
|
||
+ # (func, unused, callargs, kwargs if (oparg & 1) -- result))
|
||
+ if inst.arg & 1:
|
||
+ varkwarg = state.pop()
|
||
+ else:
|
||
+ varkwarg = None
|
||
+
|
||
+ vararg = state.pop()
|
||
+ state.pop() # unused
|
||
+ func = state.pop()
|
||
+
|
||
+ res = state.make_temp()
|
||
+ state.append(inst, func=func, vararg=vararg, varkwarg=varkwarg,
|
||
+ res=res)
|
||
+ state.push(res)
|
||
+
|
||
+ elif PYVERSION in ((3, 10), (3, 11), (3, 12)):
|
||
+
|
||
+ def op_CALL_FUNCTION_EX(self, state, inst):
|
||
+ if inst.arg & 1:
|
||
+ varkwarg = state.pop()
|
||
+ else:
|
||
+ varkwarg = None
|
||
+ vararg = state.pop()
|
||
+ func = state.pop()
|
||
+
|
||
+ if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if _is_null_temp_reg(state.peek(1)):
|
||
+ state.pop() # pop NULL, it's not used
|
||
+ elif PYVERSION in ((3, 9), (3, 10)):
|
||
+ pass
|
||
+ else:
|
||
+ raise NotImplementedError(PYVERSION)
|
||
+
|
||
+ res = state.make_temp()
|
||
+ state.append(inst, func=func, vararg=vararg, varkwarg=varkwarg,
|
||
+ res=res)
|
||
+ state.push(res)
|
||
+ else:
|
||
+ raise NotImplementedError(PYVERSION)
|
||
|
||
def _dup_topx(self, state, inst, count):
|
||
orig = [state.pop() for _ in range(count)]
|
||
@@ -1187,7 +1330,7 @@ class TraceRunner(object):
|
||
for val in duped:
|
||
state.push(val)
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
def op_CALL_INTRINSIC_1(self, state, inst):
|
||
# See https://github.com/python/cpython/blob/v3.12.0rc2/Include/
|
||
# internal/pycore_intrinsics.h#L3-L17C36
|
||
@@ -1404,7 +1547,7 @@ class TraceRunner(object):
|
||
pred=pred)
|
||
state.push(indval)
|
||
end = inst.get_jump_target()
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
# Changed in version 3.12: Up until 3.11 the iterator was
|
||
# popped when it was exhausted. Now this is handled using END_FOR
|
||
# op code.
|
||
@@ -1490,7 +1633,7 @@ class TraceRunner(object):
|
||
op_BINARY_XOR = _binaryop
|
||
|
||
def op_MAKE_FUNCTION(self, state, inst, MAKE_CLOSURE=False):
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
# https://github.com/python/cpython/commit/2f180ce
|
||
# name set via co_qualname
|
||
name = None
|
||
@@ -1500,14 +1643,19 @@ class TraceRunner(object):
|
||
raise NotImplementedError(PYVERSION)
|
||
code = state.pop()
|
||
closure = annotations = kwdefaults = defaults = None
|
||
- if inst.arg & 0x8:
|
||
- closure = state.pop()
|
||
- if inst.arg & 0x4:
|
||
- annotations = state.pop()
|
||
- if inst.arg & 0x2:
|
||
- kwdefaults = state.pop()
|
||
- if inst.arg & 0x1:
|
||
- defaults = state.pop()
|
||
+ if PYVERSION in ((3, 13), ):
|
||
+ assert inst.arg is None
|
||
+ # SET_FUNCTION_ATTRIBUTE is responsible for setting
|
||
+ # closure, annotations, kwdefaults and defaults.
|
||
+ else:
|
||
+ if inst.arg & 0x8:
|
||
+ closure = state.pop()
|
||
+ if inst.arg & 0x4:
|
||
+ annotations = state.pop()
|
||
+ if inst.arg & 0x2:
|
||
+ kwdefaults = state.pop()
|
||
+ if inst.arg & 0x1:
|
||
+ defaults = state.pop()
|
||
res = state.make_temp()
|
||
state.append(
|
||
inst,
|
||
@@ -1521,6 +1669,27 @@ class TraceRunner(object):
|
||
)
|
||
state.push(res)
|
||
|
||
+ def op_SET_FUNCTION_ATTRIBUTE(self, state, inst):
|
||
+ assert PYVERSION in ((3, 13), )
|
||
+ make_func_stack = state.pop()
|
||
+ data = state.pop()
|
||
+ if inst.arg == 0x1:
|
||
+ # 0x01 a tuple of default values for positional-only and
|
||
+ # positional-or-keyword parameters in positional order
|
||
+ state.set_function_attribute(make_func_stack, defaults=data)
|
||
+ elif inst.arg & 0x2:
|
||
+ # 0x02 a tuple of strings containing parameters’ annotations
|
||
+ state.set_function_attribute(make_func_stack, kwdefaults=data)
|
||
+ elif inst.arg & 0x4:
|
||
+ # 0x04 a tuple of strings containing parameters’ annotations
|
||
+ state.set_function_attribute(make_func_stack, annotations=data)
|
||
+ elif inst.arg == 0x8:
|
||
+ # 0x08 a tuple containing cells for free variables, making a closure
|
||
+ state.set_function_attribute(make_func_stack, closure=data)
|
||
+ else:
|
||
+ raise AssertionError("unreachable")
|
||
+ state.push(make_func_stack)
|
||
+
|
||
def op_MAKE_CLOSURE(self, state, inst):
|
||
self.op_MAKE_FUNCTION(state, inst, MAKE_CLOSURE=True)
|
||
|
||
@@ -1551,7 +1720,7 @@ class TraceRunner(object):
|
||
state.fork(pc=inst.next)
|
||
state.fork(pc=inst.get_jump_target())
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
def op_RERAISE(self, state, inst):
|
||
# This isn't handled, but the state is set up anyway
|
||
exc = state.pop()
|
||
@@ -1576,7 +1745,7 @@ class TraceRunner(object):
|
||
# NOTE: Please see notes in `interpreter.py` surrounding the implementation
|
||
# of LOAD_METHOD and CALL_METHOD.
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
# LOAD_METHOD has become a pseudo-instruction in 3.12
|
||
pass
|
||
elif PYVERSION in ((3, 11), ):
|
||
@@ -1828,9 +1997,14 @@ class _State(object):
|
||
return self.get_top_block('TRY') is not None
|
||
|
||
def get_varname(self, inst):
|
||
+ """Get referenced variable name from the instruction's oparg
|
||
+ """
|
||
+ return self.get_varname_by_arg(inst.arg)
|
||
+
|
||
+ def get_varname_by_arg(self, oparg: int):
|
||
"""Get referenced variable name from the oparg
|
||
"""
|
||
- return self._bytecode.co_varnames[inst.arg]
|
||
+ return self._bytecode.co_varnames[oparg]
|
||
|
||
def terminate(self):
|
||
"""Mark block as terminated
|
||
@@ -1852,7 +2026,7 @@ class _State(object):
|
||
stack.append(self.make_temp())
|
||
# Handle changes on the blockstack
|
||
blockstack = list(self._blockstack)
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
# pop expired block in destination pc
|
||
while blockstack:
|
||
top = blockstack[-1]
|
||
@@ -1940,7 +2114,21 @@ class StatePy311(_State):
|
||
return self.make_temp(prefix="null$")
|
||
|
||
|
||
-if PYVERSION >= (3, 11):
|
||
+class StatePy313(StatePy311):
|
||
+ def __init__(self, *args, **kwargs):
|
||
+ super().__init__(*args, **kwargs)
|
||
+ self._make_func_attrs = defaultdict(dict)
|
||
+
|
||
+ def set_function_attribute(self, make_func_res, **kwargs):
|
||
+ self._make_func_attrs[make_func_res].update(kwargs)
|
||
+
|
||
+ def get_function_attributes(self, make_func_res):
|
||
+ return self._make_func_attrs[make_func_res]
|
||
+
|
||
+
|
||
+if PYVERSION in ((3, 13), ):
|
||
+ State = StatePy313
|
||
+elif PYVERSION in ((3, 11), (3, 12)):
|
||
State = StatePy311
|
||
elif PYVERSION < (3, 11):
|
||
State = _State
|
||
@@ -1970,8 +2158,20 @@ AdaptBlockInfo = namedtuple(
|
||
|
||
|
||
def adapt_state_infos(state):
|
||
+ def process_function_attributes(inst_pair):
|
||
+ offset, data = inst_pair
|
||
+ inst = state._bytecode[offset]
|
||
+ if inst.opname == "MAKE_FUNCTION":
|
||
+ data.update(state.get_function_attributes(data['res']))
|
||
+ return offset, data
|
||
+ if PYVERSION in ((3, 13), ):
|
||
+ insts = tuple(map(process_function_attributes, state.instructions))
|
||
+ elif PYVERSION in ((3, 10), (3, 11), (3, 12)):
|
||
+ insts = tuple(state.instructions)
|
||
+ else:
|
||
+ raise NotImplementedError(PYVERSION)
|
||
return AdaptBlockInfo(
|
||
- insts=tuple(state.instructions),
|
||
+ insts=insts,
|
||
outgoing_phis=state.outgoing_phis,
|
||
blockstack=state.blockstack_initial,
|
||
active_try_block=state.find_initial_try_block(),
|
||
Index: numba-0.60.0/numba/core/controlflow.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/controlflow.py
|
||
+++ numba-0.60.0/numba/core/controlflow.py
|
||
@@ -954,7 +954,7 @@ class ControlFlowAnalysis(object):
|
||
self._curblock.terminating = True
|
||
self._force_new_block = True
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
def op_RETURN_CONST(self, inst):
|
||
self._curblock.terminating = True
|
||
self._force_new_block = True
|
||
Index: numba-0.60.0/numba/core/interpreter.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/interpreter.py
|
||
+++ numba-0.60.0/numba/core/interpreter.py
|
||
@@ -6,7 +6,11 @@ import logging
|
||
import textwrap
|
||
|
||
from numba.core import errors, ir, config
|
||
-from numba.core.errors import NotDefinedError, UnsupportedError, error_extras
|
||
+from numba.core.errors import (
|
||
+ NotDefinedError,
|
||
+ UnsupportedBytecodeError,
|
||
+ error_extras,
|
||
+)
|
||
from numba.core.ir_utils import get_definition, guard
|
||
from numba.core.utils import (PYVERSION, BINOPS_TO_OPERATORS,
|
||
INPLACE_BINOPS_TO_OPERATORS,)
|
||
@@ -15,7 +19,7 @@ from numba.core.unsafe import eh
|
||
from numba.cpython.unsafe.tuple import unpack_single_tuple
|
||
|
||
|
||
-if PYVERSION in ((3, 12), ):
|
||
+if PYVERSION in ((3, 12), (3, 13)):
|
||
# Operands for CALL_INTRINSIC_1
|
||
from numba.core.byteflow import CALL_INTRINSIC_1_Operand as ci1op
|
||
elif PYVERSION in ((3, 9), (3, 10), (3, 11)):
|
||
@@ -108,7 +112,7 @@ def _remove_assignment_definition(old_bo
|
||
func_ir._definitions[lhs].remove(rhs)
|
||
already_deleted_defs[lhs].add(rhs)
|
||
elif rhs not in already_deleted_defs[lhs]:
|
||
- raise UnsupportedError(
|
||
+ raise UnsupportedBytecodeError(
|
||
"Inconsistency found in the definitions while executing"
|
||
" a peephole optimization. This suggests an internal"
|
||
" error or inconsistency elsewhere in the compiler."
|
||
@@ -211,7 +215,7 @@ def _call_function_ex_replace_kws_large(
|
||
):
|
||
# We cannot handle this format so raise the
|
||
# original error message.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
key_var_name = const_stmt.target.name
|
||
key_val = const_stmt.value.value
|
||
search_start += 1
|
||
@@ -257,7 +261,7 @@ def _call_function_ex_replace_kws_large(
|
||
):
|
||
# We cannot handle this format so raise the
|
||
# original error message.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
setitem_stmt = old_body[search_start + 1]
|
||
if not (
|
||
isinstance(setitem_stmt, ir.Assign)
|
||
@@ -277,7 +281,7 @@ def _call_function_ex_replace_kws_large(
|
||
# getattr. If for some reason this doesn't match the code
|
||
# format, we raise the original error message. This check
|
||
# is meant as a precaution.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
arg_var = setitem_stmt.value.args[1]
|
||
# Append the (key, value) pair.
|
||
kws.append((key_val, arg_var))
|
||
@@ -421,7 +425,7 @@ def _call_function_ex_replace_args_large
|
||
and concat_stmt.value.fn == operator.add
|
||
):
|
||
# We cannot handle this format.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
lhs_name = concat_stmt.value.lhs.name
|
||
rhs_name = concat_stmt.value.rhs.name
|
||
# The previous statement should be a
|
||
@@ -439,7 +443,7 @@ def _call_function_ex_replace_args_large
|
||
and len(arg_tuple_stmt.value.items) == 1
|
||
):
|
||
# We cannot handle this format.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
if arg_tuple_stmt.target.name == lhs_name:
|
||
# The tuple should always be generated on the RHS.
|
||
raise AssertionError("unreachable")
|
||
@@ -447,7 +451,7 @@ def _call_function_ex_replace_args_large
|
||
target_name = lhs_name
|
||
else:
|
||
# We cannot handle this format.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
total_args.append(
|
||
arg_tuple_stmt.value.items[0]
|
||
)
|
||
@@ -497,7 +501,7 @@ def _call_function_ex_replace_args_large
|
||
# If we reached the start we never found the build_tuple.
|
||
# We cannot handle this format so raise the
|
||
# original error message.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
# Reverse the arguments so we get the correct order.
|
||
return total_args[::-1]
|
||
|
||
@@ -586,7 +590,7 @@ def peep_hole_call_function_ex_to_call_f
|
||
# If we couldn't find where the kwargs are created
|
||
# then it should be a normal **kwargs call
|
||
# so we produce an unsupported message.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
# Determine the kws
|
||
if keyword_def.value.items:
|
||
# n_kws <= 15 case.
|
||
@@ -638,7 +642,7 @@ def peep_hole_call_function_ex_to_call_f
|
||
if args:
|
||
# If we have vararg then args is expected to
|
||
# be an empty list.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
vararg_loc = start_search
|
||
args_def = None
|
||
found = False
|
||
@@ -654,7 +658,7 @@ def peep_hole_call_function_ex_to_call_f
|
||
if not found:
|
||
# If we couldn't find where the args are created
|
||
# then we can't handle this format.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
if (
|
||
isinstance(args_def.value, ir.Expr)
|
||
and args_def.value.op == "build_tuple"
|
||
@@ -683,7 +687,7 @@ def peep_hole_call_function_ex_to_call_f
|
||
# If there is a call with vararg we need to check
|
||
# if the list -> tuple conversion failed and if so
|
||
# throw an error.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
else:
|
||
# Here the IR is an initial empty build_tuple.
|
||
# Then for each arg, a new tuple with a single
|
||
@@ -747,7 +751,7 @@ def peep_hole_call_function_ex_to_call_f
|
||
# exception.
|
||
expr = func_ir._definitions[vararg_name][0]
|
||
if isinstance(expr, ir.Expr) and expr.op == "list_to_tuple":
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
|
||
new_body.append(stmt)
|
||
# Replace the block body if we changed the IR
|
||
@@ -1197,7 +1201,7 @@ def peep_hole_fuse_dict_add_updates(func
|
||
else:
|
||
# If we cannot remove _update_from_bytecode
|
||
# Then raise an error for the user.
|
||
- raise UnsupportedError(errmsg)
|
||
+ raise UnsupportedBytecodeError(errmsg)
|
||
|
||
# Check if we need to drop any maps from being tracked.
|
||
# Skip the setitem/_update_from_bytecode getattr that
|
||
@@ -1385,7 +1389,7 @@ class Interpreter(object):
|
||
max(inst_blocks.body))
|
||
self.last_active_offset = last_active_offset
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
self.active_exception_entries = tuple(
|
||
[entry for entry in self.bytecode.exception_entries
|
||
if entry.start < self.last_active_offset])
|
||
@@ -1401,7 +1405,7 @@ class Interpreter(object):
|
||
# Interpret loop
|
||
for inst, kws in self._iter_inst():
|
||
self._dispatch(inst, kws)
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
# Insert end of try markers
|
||
self._end_try_blocks()
|
||
elif PYVERSION in ((3, 9), (3, 10)):
|
||
@@ -1418,12 +1422,12 @@ class Interpreter(object):
|
||
# post process the IR to rewrite opcodes/byte sequences that are too
|
||
# involved to risk handling as part of direct interpretation
|
||
peepholes = []
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
peepholes.append(peep_hole_split_at_pop_block)
|
||
- if PYVERSION in ((3, 9), (3, 10), (3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 9), (3, 10), (3, 11), (3, 12), (3, 13)):
|
||
peepholes.append(peep_hole_list_to_tuple)
|
||
peepholes.append(peep_hole_delete_with_exit)
|
||
- if PYVERSION in ((3, 10), (3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)):
|
||
# peep_hole_call_function_ex_to_call_function_kw
|
||
# depends on peep_hole_list_to_tuple converting
|
||
# any large number of arguments from a list to a
|
||
@@ -1456,7 +1460,7 @@ class Interpreter(object):
|
||
|
||
See also: _insert_try_block_end
|
||
"""
|
||
- assert PYVERSION in ((3, 11), (3, 12))
|
||
+ assert PYVERSION in ((3, 11), (3, 12), (3, 13))
|
||
graph = self.cfa.graph
|
||
for offset, block in self.blocks.items():
|
||
# Get current blockstack
|
||
@@ -1507,7 +1511,7 @@ class Interpreter(object):
|
||
first = uservar[0]
|
||
loc = self.current_scope.get(first).loc
|
||
msg = "Exception object cannot be stored into variable ({})."
|
||
- raise errors.UnsupportedError(msg.format(first), loc=loc)
|
||
+ raise errors.UnsupportedBytecodeError(msg.format(first), loc=loc)
|
||
|
||
def init_first_block(self):
|
||
# Define variables receiving the function arguments
|
||
@@ -1564,7 +1568,7 @@ class Interpreter(object):
|
||
self.dfainfo = self.dfa.infos[self.current_block_offset]
|
||
self.assigner = Assigner()
|
||
# Check out-of-scope syntactic-block
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
# This is recreating pre-3.11 code structure
|
||
while self.syntax_blocks:
|
||
if offset >= self.syntax_blocks[-1].exit:
|
||
@@ -1735,7 +1739,7 @@ class Interpreter(object):
|
||
val = self.get(varname)
|
||
except ir.NotDefinedError:
|
||
# Hack to make sure exception variables are defined
|
||
- assert PYVERSION in ((3, 11), (3, 12)), \
|
||
+ assert PYVERSION in ((3, 11), (3, 12), (3, 13)), \
|
||
"unexpected missing definition"
|
||
val = ir.Const(value=None, loc=self.loc)
|
||
stmt = ir.Assign(value=val, target=target,
|
||
@@ -1795,7 +1799,7 @@ class Interpreter(object):
|
||
if self._DEBUG_PRINT:
|
||
print(inst)
|
||
assert self.current_block is not None
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
if self.syntax_blocks:
|
||
top = self.syntax_blocks[-1]
|
||
if isinstance(top, ir.With) :
|
||
@@ -1825,6 +1829,9 @@ class Interpreter(object):
|
||
if not config.FULL_TRACEBACKS:
|
||
raise err from None
|
||
else:
|
||
+ m = f"handling op: {inst} | offset: {inst.offset}"
|
||
+ err.add_context(m)
|
||
+ err.add_context(self.bytecode.dump())
|
||
raise err
|
||
|
||
# --- Scope operations ---
|
||
@@ -1921,6 +1928,10 @@ class Interpreter(object):
|
||
loc=self.loc)
|
||
self.store(expr, st)
|
||
|
||
+ def op_FORMAT_SIMPLE(self, inst, value, res, strvar):
|
||
+ # Same as FORMAT_VALUE
|
||
+ return self.op_FORMAT_VALUE(inst, value, res, strvar)
|
||
+
|
||
def op_FORMAT_VALUE(self, inst, value, res, strvar):
|
||
"""
|
||
FORMAT_VALUE(flags): flags argument specifies format spec which is not
|
||
@@ -1971,7 +1982,7 @@ class Interpreter(object):
|
||
(), loc=self.loc)
|
||
self.store(value=sliceinst, name=res)
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
def op_BINARY_SLICE(self, inst, start, end, container, res, slicevar,
|
||
temp_res):
|
||
start = self.get(start)
|
||
@@ -1990,7 +2001,7 @@ class Interpreter(object):
|
||
else:
|
||
raise NotImplementedError(PYVERSION)
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
def op_STORE_SLICE(self, inst, start, end, container, value, res,
|
||
slicevar):
|
||
start = self.get(start)
|
||
@@ -2218,11 +2229,58 @@ class Interpreter(object):
|
||
stmt = ir.DelItem(base, self.get(indexvar), loc=self.loc)
|
||
self.current_block.append(stmt)
|
||
|
||
- def op_LOAD_FAST(self, inst, res):
|
||
+ def _op_LOAD_FAST(self, inst, res):
|
||
srcname = self.code_locals[inst.arg]
|
||
self.store(value=self.get(srcname), name=res)
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 13), ):
|
||
+ def op_LOAD_FAST(self, inst, res, as_load_deref=False):
|
||
+ if as_load_deref:
|
||
+ self.op_LOAD_DEREF(inst, res)
|
||
+ else:
|
||
+ self._op_LOAD_FAST(inst, res)
|
||
+
|
||
+ else:
|
||
+ op_LOAD_FAST = _op_LOAD_FAST
|
||
+
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ def op_LOAD_FAST_LOAD_FAST(self, inst, res1, res2):
|
||
+ oparg = inst.arg
|
||
+ oparg1 = oparg >> 4
|
||
+ oparg2 = oparg & 15
|
||
+ src1 = self.get(self.code_locals[oparg1])
|
||
+ src2 = self.get(self.code_locals[oparg2])
|
||
+ self.store(value=src1, name=res1)
|
||
+ self.store(value=src2, name=res2)
|
||
+
|
||
+ def op_STORE_FAST_LOAD_FAST(self, inst, store_value, load_res):
|
||
+ oparg = inst.arg
|
||
+ oparg1 = oparg >> 4
|
||
+ oparg2 = oparg & 15
|
||
+
|
||
+ dstname = self.code_locals[oparg1]
|
||
+ dst_value = self.get(store_value)
|
||
+ self.store(value=dst_value, name=dstname)
|
||
+
|
||
+ src_value = self.get(self.code_locals[oparg2])
|
||
+ self.store(value=src_value, name=load_res)
|
||
+
|
||
+ def op_STORE_FAST_STORE_FAST(self, inst, value1, value2):
|
||
+ oparg = inst.arg
|
||
+ oparg1 = oparg >> 4
|
||
+ oparg2 = oparg & 15
|
||
+
|
||
+ dstname = self.code_locals[oparg1]
|
||
+ self.store(value=self.get(value1), name=dstname)
|
||
+ dstname = self.code_locals[oparg2]
|
||
+ self.store(value=self.get(value2), name=dstname)
|
||
+
|
||
+ elif PYVERSION in ((3, 10), (3, 11), (3, 12)):
|
||
+ pass
|
||
+ else:
|
||
+ raise NotImplementedError(PYVERSION)
|
||
+
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
op_LOAD_FAST_CHECK = op_LOAD_FAST
|
||
|
||
def op_LOAD_FAST_AND_CLEAR(self, inst, res):
|
||
@@ -2269,7 +2327,7 @@ class Interpreter(object):
|
||
|
||
def op_LOAD_ATTR(self, inst, item, res):
|
||
item = self.get(item)
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
attr = self.code_names[inst.arg >> 1]
|
||
elif PYVERSION in ((3, 9), (3, 10), (3, 11)):
|
||
attr = self.code_names[inst.arg]
|
||
@@ -2300,7 +2358,7 @@ class Interpreter(object):
|
||
const = ir.Const(value, loc=self.loc)
|
||
self.store(const, res)
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
def op_LOAD_GLOBAL(self, inst, idx, res):
|
||
name = self.code_names[idx]
|
||
value = self.get_global_value(name)
|
||
@@ -2318,11 +2376,15 @@ class Interpreter(object):
|
||
def op_COPY_FREE_VARS(self, inst):
|
||
pass
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
def op_LOAD_DEREF(self, inst, res):
|
||
name = self.func_id.func.__code__._varname_from_oparg(inst.arg)
|
||
if name in self.code_cellvars:
|
||
- gl = self.get(name)
|
||
+ try:
|
||
+ gl = self.get(name)
|
||
+ except NotDefinedError:
|
||
+ msg = "Unsupported use of cell variable encountered"
|
||
+ raise NotImplementedError(msg)
|
||
elif name in self.code_freevars:
|
||
idx = self.code_freevars.index(name)
|
||
value = self.get_closure_value(idx)
|
||
@@ -2343,11 +2405,11 @@ class Interpreter(object):
|
||
else:
|
||
raise NotImplementedError(PYVERSION)
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
def op_MAKE_CELL(self, inst):
|
||
pass # ignored bytecode
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
def op_STORE_DEREF(self, inst, value):
|
||
name = self.func_id.func.__code__._varname_from_oparg(inst.arg)
|
||
value = self.get(value)
|
||
@@ -2387,7 +2449,7 @@ class Interpreter(object):
|
||
|
||
def op_BEFORE_WITH(self, inst, contextmanager, exitfn, end):
|
||
assert self.blocks[inst.offset] is self.current_block
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
# Python 3.12 hack for handling nested with blocks
|
||
if end > self.last_active_offset:
|
||
# Use exception entries to figure out end of syntax block
|
||
@@ -2437,6 +2499,7 @@ class Interpreter(object):
|
||
func = self.get(func)
|
||
args = [self.get(x) for x in args]
|
||
if kw_names is not None:
|
||
+ assert PYVERSION < (3, 13)
|
||
names = self.code_consts[kw_names]
|
||
kwargs = list(zip(names, args[-len(names):]))
|
||
args = args[:-len(names)]
|
||
@@ -2445,6 +2508,19 @@ class Interpreter(object):
|
||
expr = ir.Expr.call(func, args, kwargs, loc=self.loc)
|
||
self.store(expr, res)
|
||
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ def op_CALL_KW(self, inst, func, args, kw_names, res):
|
||
+ func = self.get(func)
|
||
+ args = [self.get(x) for x in args]
|
||
+ consti = int(kw_names.rsplit('.', 2)[-1])
|
||
+ names = self.code_consts[consti]
|
||
+ kwargs = list(zip(names, args[-len(names):]))
|
||
+ args = args[:-len(names)]
|
||
+ expr = ir.Expr.call(func, args, kwargs, loc=self.loc)
|
||
+ self.store(expr, res)
|
||
+ else:
|
||
+ assert PYVERSION < (3, 13)
|
||
+
|
||
def op_CALL_FUNCTION(self, inst, func, args, res):
|
||
func = self.get(func)
|
||
args = [self.get(x) for x in args]
|
||
@@ -2878,6 +2954,8 @@ class Interpreter(object):
|
||
jmp = ir.Jump(inst.get_jump_target(), loc=self.loc)
|
||
self.current_block.append(jmp)
|
||
|
||
+ op_JUMP_BACKWARD_NO_INTERRUPT = op_JUMP_BACKWARD
|
||
+
|
||
def op_POP_BLOCK(self, inst, kind=None):
|
||
if kind is None:
|
||
self.syntax_blocks.pop()
|
||
@@ -2892,7 +2970,7 @@ class Interpreter(object):
|
||
ret = ir.Return(self.get(castval), loc=self.loc)
|
||
self.current_block.append(ret)
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
def op_RETURN_CONST(self, inst, retval, castval):
|
||
value = self.code_consts[inst.arg]
|
||
const = ir.Const(value, loc=self.loc)
|
||
@@ -2905,8 +2983,20 @@ class Interpreter(object):
|
||
else:
|
||
raise NotImplementedError(PYVERSION)
|
||
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ def op_TO_BOOL(self, inst, val, res):
|
||
+ self.store(self.get(val), res) # TODO: just a lazy hack
|
||
+
|
||
+ elif PYVERSION in ((3, 10), (3, 11), (3, 12)):
|
||
+ pass
|
||
+ else:
|
||
+ raise NotImplementedError(PYVERSION)
|
||
+
|
||
def op_COMPARE_OP(self, inst, lhs, rhs, res):
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ op = dis.cmp_op[inst.arg >> 5]
|
||
+ # TODO: fifth lowest bit now indicates a forced version to bool.
|
||
+ elif PYVERSION in ((3, 12),):
|
||
op = dis.cmp_op[inst.arg >> 4]
|
||
elif PYVERSION in ((3, 9), (3, 10), (3, 11)):
|
||
op = dis.cmp_op[inst.arg]
|
||
@@ -3024,7 +3114,7 @@ class Interpreter(object):
|
||
def op_POP_JUMP_FORWARD_IF_NOT_NONE(self, inst, pred):
|
||
self._jump_if_none(inst, pred, False)
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
def op_POP_JUMP_IF_NONE(self, inst, pred):
|
||
self._jump_if_none(inst, pred, True)
|
||
|
||
@@ -3152,7 +3242,7 @@ class Interpreter(object):
|
||
"Probably caused by complex control-flow constructs; "
|
||
"e.g. try-except"
|
||
)
|
||
- raise errors.UnsupportedError(msg, loc=self.loc)
|
||
+ raise errors.UnsupportedBytecodeError(msg, loc=self.loc)
|
||
fcode = assume_code_const.value
|
||
if name:
|
||
name = self.get(name)
|
||
@@ -3166,14 +3256,14 @@ class Interpreter(object):
|
||
self.op_MAKE_FUNCTION(inst, name, code, closure, annotations,
|
||
kwdefaults, defaults, res)
|
||
|
||
- if PYVERSION in ((3, 11), (3, 12)):
|
||
+ if PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
def op_LOAD_CLOSURE(self, inst, res):
|
||
name = self.func_id.func.__code__._varname_from_oparg(inst.arg)
|
||
if name in self.code_cellvars:
|
||
try:
|
||
gl = self.get(name)
|
||
except NotDefinedError:
|
||
- msg = "Unsupported use of op_LOAD_CLOSURE encountered"
|
||
+ msg = "Unsupported use of cell variable encountered"
|
||
raise NotImplementedError(msg)
|
||
elif name in self.code_freevars:
|
||
idx = self.code_freevars.index(name)
|
||
@@ -3191,7 +3281,7 @@ class Interpreter(object):
|
||
try:
|
||
gl = self.get(name)
|
||
except NotDefinedError:
|
||
- msg = "Unsupported use of op_LOAD_CLOSURE encountered"
|
||
+ msg = "Unsupported use of cell variable encountered"
|
||
raise NotImplementedError(msg)
|
||
else:
|
||
idx = inst.arg - n_cellvars
|
||
@@ -3228,7 +3318,7 @@ class Interpreter(object):
|
||
"op_LIST_EXTEND at the start of a block.\n\nThis could be "
|
||
"due to the use of a branch in a tuple unpacking statement.")
|
||
if not self.current_block.body:
|
||
- raise errors.UnsupportedError(msg)
|
||
+ raise errors.UnsupportedBytecodeError(msg)
|
||
|
||
# is last emitted statement a build_tuple?
|
||
stmt = self.current_block.body[-1]
|
||
@@ -3258,7 +3348,7 @@ class Interpreter(object):
|
||
ok = False
|
||
break
|
||
if ok and build_empty_list is None:
|
||
- raise errors.UnsupportedError(msg)
|
||
+ raise errors.UnsupportedBytecodeError(msg)
|
||
if ok:
|
||
stmts = self.current_block.body
|
||
build_tuple_asgn = self.current_block.body[-1]
|
||
@@ -3304,7 +3394,7 @@ class Interpreter(object):
|
||
def op_CALL_METHOD(self, *args, **kws):
|
||
self.op_CALL_FUNCTION(*args, **kws)
|
||
|
||
- if PYVERSION in ((3, 12), ):
|
||
+ if PYVERSION in ((3, 12), (3, 13)):
|
||
def op_CALL_INTRINSIC_1(self, inst, operand, **kwargs):
|
||
if operand == ci1op.INTRINSIC_STOPITERATION_ERROR:
|
||
stmt = ir.StaticRaise(INTRINSIC_STOPITERATION_ERROR, (),
|
||
@@ -3325,7 +3415,7 @@ class Interpreter(object):
|
||
raise NotImplementedError(PYVERSION)
|
||
|
||
|
||
-if PYVERSION in ((3, 12), ):
|
||
+if PYVERSION in ((3, 12), (3, 13)):
|
||
class INTRINSIC_STOPITERATION_ERROR(AssertionError):
|
||
pass
|
||
elif PYVERSION in ((3, 9), (3, 10), (3, 11)):
|
||
Index: numba-0.60.0/numba/cpython/unicode.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/cpython/unicode.py
|
||
+++ numba-0.60.0/numba/cpython/unicode.py
|
||
@@ -349,7 +349,7 @@ def _set_code_point(a, i, ch):
|
||
"Unexpected unicode representation in _set_code_point")
|
||
|
||
|
||
-if PYVERSION in ((3, 12),):
|
||
+if PYVERSION in ((3, 12), (3, 13)):
|
||
@register_jitable
|
||
def _pick_kind(kind1, kind2):
|
||
if kind1 == PY_UNICODE_1BYTE_KIND:
|
||
@@ -393,7 +393,7 @@ def _pick_ascii(is_ascii1, is_ascii2):
|
||
return types.uint32(0)
|
||
|
||
|
||
-if PYVERSION in ((3, 12),):
|
||
+if PYVERSION in ((3, 12), (3, 13)):
|
||
@register_jitable
|
||
def _kind_to_byte_width(kind):
|
||
if kind == PY_UNICODE_1BYTE_KIND:
|
||
@@ -2047,7 +2047,7 @@ def _is_upper(is_lower, is_upper, is_tit
|
||
def impl(a):
|
||
l = len(a)
|
||
if l == 1:
|
||
- return is_upper(_get_code_point(a, 0))
|
||
+ return is_upper(_get_code_point(a, 0)) != 0
|
||
if l == 0:
|
||
return False
|
||
cased = False
|
||
Index: numba-0.60.0/numba/experimental/jitclass/base.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/experimental/jitclass/base.py
|
||
+++ numba-0.60.0/numba/experimental/jitclass/base.py
|
||
@@ -282,6 +282,9 @@ def _drop_ignored_attrs(dct):
|
||
drop = set(['__weakref__',
|
||
'__module__',
|
||
'__dict__'])
|
||
+ if utils.PYVERSION == (3, 13):
|
||
+ # new in python 3.13
|
||
+ drop |= set(['__firstlineno__', '__static_attributes__'])
|
||
|
||
if '__annotations__' in dct:
|
||
drop.add('__annotations__')
|
||
@@ -300,7 +303,7 @@ def _drop_ignored_attrs(dct):
|
||
drop.add('__hash__')
|
||
|
||
for k in drop:
|
||
- del dct[k]
|
||
+ dct.pop(k)
|
||
|
||
|
||
class ClassBuilder(object):
|
||
Index: numba-0.60.0/numba/core/compiler.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/compiler.py
|
||
+++ numba-0.60.0/numba/core/compiler.py
|
||
@@ -476,10 +476,7 @@ class CompilerBase(object):
|
||
res = e.result
|
||
break
|
||
except Exception as e:
|
||
- if (utils.use_new_style_errors() and not
|
||
- isinstance(e, errors.NumbaError)):
|
||
- raise e
|
||
-
|
||
+ utils.handle_new_style_errors(e)
|
||
self.state.status.fail_reason = e
|
||
if is_final_pipeline:
|
||
raise e
|
||
Index: numba-0.60.0/numba/core/compiler_machinery.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/compiler_machinery.py
|
||
+++ numba-0.60.0/numba/core/compiler_machinery.py
|
||
@@ -304,7 +304,8 @@ class PassManager(object):
|
||
args=str(internal_state.args),
|
||
return_type=str(internal_state.return_type),
|
||
)
|
||
- with ev.trigger_event("numba:run_pass", data=ev_details):
|
||
+ errctx = errors.new_error_context(f"Pass {pss.name()}")
|
||
+ with ev.trigger_event("numba:run_pass", data=ev_details), errctx:
|
||
with SimpleTimer() as init_time:
|
||
mutated |= check(pss.run_initialization, internal_state)
|
||
with SimpleTimer() as pass_time:
|
||
@@ -359,9 +360,7 @@ class PassManager(object):
|
||
except _EarlyPipelineCompletion as e:
|
||
raise e
|
||
except Exception as e:
|
||
- if (utils.use_new_style_errors() and not
|
||
- isinstance(e, errors.NumbaError)):
|
||
- raise e
|
||
+ utils.handle_new_style_errors(e)
|
||
msg = "Failed in %s mode pipeline (step: %s)" % \
|
||
(self.pipeline_name, pass_desc)
|
||
patched_exception = self._patch_error(msg, e)
|
||
Index: numba-0.60.0/numba/core/errors.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/errors.py
|
||
+++ numba-0.60.0/numba/core/errors.py
|
||
@@ -532,7 +532,6 @@ class WarningsFixer(object):
|
||
|
||
|
||
class NumbaError(Exception):
|
||
-
|
||
def __init__(self, msg, loc=None, highlighting=True):
|
||
self.msg = msg
|
||
self.loc = loc
|
||
@@ -578,7 +577,13 @@ class UnsupportedError(NumbaError):
|
||
"""
|
||
Numba does not have an implementation for this functionality.
|
||
"""
|
||
- pass
|
||
+
|
||
+
|
||
+class UnsupportedBytecodeError(Exception):
|
||
+ """Unsupported bytecode is non-recoverable
|
||
+ """
|
||
+ def __init__(self, msg, loc=None):
|
||
+ super().__init__(f"{msg}. Raised from {loc}")
|
||
|
||
|
||
class UnsupportedRewriteError(UnsupportedError):
|
||
Index: numba-0.60.0/numba/core/types/functions.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/types/functions.py
|
||
+++ numba-0.60.0/numba/core/types/functions.py
|
||
@@ -307,12 +307,9 @@ class BaseFunction(Callable):
|
||
for k, v in kws.items()}
|
||
sig = temp.apply(nolitargs, nolitkws)
|
||
except Exception as e:
|
||
- if (utils.use_new_style_errors() and not
|
||
- isinstance(e, errors.NumbaError)):
|
||
- raise e
|
||
- else:
|
||
- sig = None
|
||
- failures.add_error(temp, False, e, uselit)
|
||
+ utils.handle_new_style_errors(e)
|
||
+ sig = None
|
||
+ failures.add_error(temp, False, e, uselit)
|
||
else:
|
||
if sig is not None:
|
||
self._impl_keys[sig.args] = temp.get_impl_key(sig)
|
||
Index: numba-0.60.0/numba/core/utils.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/utils.py
|
||
+++ numba-0.60.0/numba/core/utils.py
|
||
@@ -230,6 +230,17 @@ def use_old_style_errors():
|
||
return res
|
||
|
||
|
||
+def handle_new_style_errors(e):
|
||
+ """Handle new_style error by raising the exception immediately if they are
|
||
+ non-recoverable.
|
||
+ """
|
||
+ from numba.core import errors
|
||
+
|
||
+ if use_new_style_errors():
|
||
+ if not isinstance(e, errors.NumbaError):
|
||
+ raise e
|
||
+
|
||
+
|
||
class ThreadLocalStack:
|
||
"""A TLS stack container.
|
||
|
||
Index: numba-0.60.0/numba/stencils/stencil.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/stencils/stencil.py
|
||
+++ numba-0.60.0/numba/stencils/stencil.py
|
||
@@ -402,8 +402,9 @@ class StencilFunc(object):
|
||
sig = signature(real_ret, *argtys_extra)
|
||
dummy_text = ("def __numba_dummy_stencil({}{}):\n pass\n".format(
|
||
",".join(self.kernel_ir.arg_names), sig_extra))
|
||
- exec(dummy_text) in globals(), locals()
|
||
- dummy_func = eval("__numba_dummy_stencil")
|
||
+ dct = {}
|
||
+ exec(dummy_text, dct)
|
||
+ dummy_func = dct["__numba_dummy_stencil"]
|
||
sig = sig.replace(pysig=utils.pysignature(dummy_func))
|
||
self._targetctx.insert_func_defn([(self._lower_me, self, argtys_extra)])
|
||
self._type_cache[argtys_extra] = (sig, result, typemap, calltypes)
|
||
@@ -659,8 +660,10 @@ class StencilFunc(object):
|
||
print(func_text)
|
||
|
||
# Force the new stencil function into existence.
|
||
- exec(func_text) in globals(), locals()
|
||
- stencil_func = eval(stencil_func_name)
|
||
+ dct = {}
|
||
+ dct.update(globals())
|
||
+ exec(func_text, dct)
|
||
+ stencil_func = dct[stencil_func_name]
|
||
if sigret is not None:
|
||
pysig = utils.pysignature(stencil_func)
|
||
sigret.pysig = pysig
|
||
Index: numba-0.60.0/numba/tests/test_debug.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_debug.py
|
||
+++ numba-0.60.0/numba/tests/test_debug.py
|
||
@@ -73,7 +73,7 @@ class DebugTestBase(TestCase):
|
||
self.assert_fails(check_meth, out)
|
||
|
||
def _check_dump_bytecode(self, out):
|
||
- if utils.PYVERSION in ((3, 11), (3, 12)):
|
||
+ if utils.PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
self.assertIn('BINARY_OP', out)
|
||
elif utils.PYVERSION in ((3, 9), (3, 10)):
|
||
self.assertIn('BINARY_ADD', out)
|
||
Index: numba-0.60.0/numba/tests/test_ir_inlining.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_ir_inlining.py
|
||
+++ numba-0.60.0/numba/tests/test_ir_inlining.py
|
||
@@ -444,7 +444,7 @@ class TestFunctionInlining(MemoryLeakMix
|
||
return bar(z + 2)
|
||
|
||
# block count changes with Python version due to bytecode differences.
|
||
- if utils.PYVERSION in ((3, 12), ):
|
||
+ if utils.PYVERSION in ((3, 12), (3, 13)):
|
||
bc = 39
|
||
elif utils.PYVERSION in ((3, 10), (3, 11)):
|
||
bc = 35
|
||
Index: numba-0.60.0/numba/tests/test_closure.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_closure.py
|
||
+++ numba-0.60.0/numba/tests/test_closure.py
|
||
@@ -400,13 +400,13 @@ class TestInlinedClosure(TestCase):
|
||
with self.assertRaises(NotImplementedError) as raises:
|
||
cfunc = jit(nopython=True)(outer3)
|
||
cfunc(var)
|
||
- msg = "Unsupported use of op_LOAD_CLOSURE encountered"
|
||
+ msg = "Unsupported use of cell variable encountered"
|
||
self.assertIn(msg, str(raises.exception))
|
||
|
||
with self.assertRaises(NotImplementedError) as raises:
|
||
cfunc = jit(nopython=True)(outer4)
|
||
cfunc(var)
|
||
- msg = "Unsupported use of op_LOAD_CLOSURE encountered"
|
||
+ msg = "Unsupported use of cell variable encountered"
|
||
self.assertIn(msg, str(raises.exception))
|
||
|
||
with self.assertRaises(TypingError) as raises:
|
||
Index: numba-0.60.0/numba/core/inline_closurecall.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/inline_closurecall.py
|
||
+++ numba-0.60.0/numba/core/inline_closurecall.py
|
||
@@ -95,7 +95,7 @@ class InlineClosureCallPass(object):
|
||
modified = False
|
||
work_list = list(self.func_ir.blocks.items())
|
||
debug_print = _make_debug_print("InlineClosureCallPass")
|
||
- debug_print("START")
|
||
+ debug_print(f"START {self.func_ir.func_id.func_qualname}")
|
||
while work_list:
|
||
_label, block = work_list.pop()
|
||
for i, instr in enumerate(block.body):
|
||
Index: numba-0.60.0/numba/pycc/modulemixin.c
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/pycc/modulemixin.c
|
||
+++ numba-0.60.0/numba/pycc/modulemixin.c
|
||
@@ -23,6 +23,12 @@
|
||
#include "../core/runtime/nrt.h"
|
||
#endif
|
||
|
||
+#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION >= 12)
|
||
+ #define Py_BUILD_CORE 1
|
||
+ #include "internal/pycore_pyhash.h"
|
||
+ #undef Py_BUILD_CORE
|
||
+#endif
|
||
+
|
||
/* Defines hashsecret variables (see issue #6386) */
|
||
int64_t _numba_hashsecret_siphash_k0;
|
||
int64_t _numba_hashsecret_siphash_k1;
|
||
Index: numba-0.60.0/numba/tests/test_operators.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_operators.py
|
||
+++ numba-0.60.0/numba/tests/test_operators.py
|
||
@@ -768,7 +768,7 @@ class TestOperators(TestCase):
|
||
# error message depends on Python version.
|
||
if utils.PYVERSION in ((3, 9),):
|
||
msg = "can't mod complex numbers"
|
||
- elif utils.PYVERSION in ((3, 10), (3, 11), (3, 12)):
|
||
+ elif utils.PYVERSION in ((3, 10), (3, 11), (3, 12), (3, 13)):
|
||
msg = "unsupported operand type(s) for %"
|
||
else:
|
||
raise NotImplementedError(utils.PYVERSION)
|
||
Index: numba-0.60.0/numba/tests/test_parfors.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_parfors.py
|
||
+++ numba-0.60.0/numba/tests/test_parfors.py
|
||
@@ -3550,7 +3550,7 @@ class TestPrangeBase(TestParforsBase):
|
||
prange_names.append('prange')
|
||
prange_names = tuple(prange_names)
|
||
prange_idx = len(prange_names) - 1
|
||
- if utils.PYVERSION in ((3, 11), (3, 12)):
|
||
+ if utils.PYVERSION in ((3, 11), (3, 12), (3, 13)):
|
||
# this is the inverse of _fix_LOAD_GLOBAL_arg
|
||
prange_idx = 1 + (prange_idx << 1)
|
||
elif utils.PYVERSION in ((3, 9), (3, 10)):
|
||
Index: numba-0.60.0/numba/tests/support.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/support.py
|
||
+++ numba-0.60.0/numba/tests/support.py
|
||
@@ -128,6 +128,12 @@ def expected_failure_np2(fn):
|
||
else:
|
||
return fn
|
||
|
||
+def expected_failure_py313(fn):
|
||
+ if utils.PYVERSION == (3, 13):
|
||
+ return unittest.expectedFailure(fn)
|
||
+ else:
|
||
+ return fn
|
||
+
|
||
_msg = "SciPy needed for test"
|
||
skip_unless_scipy = unittest.skipIf(scipy is None, _msg)
|
||
|
||
Index: numba-0.60.0/numba/tests/test_np_functions.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_np_functions.py
|
||
+++ numba-0.60.0/numba/tests/test_np_functions.py
|
||
@@ -6192,8 +6192,9 @@ def foo():
|
||
tystr = ty.__name__
|
||
basestr = basefunc.__name__
|
||
funcstr = self.template % (tystr, basestr)
|
||
- eval(compile(funcstr, '<string>', 'exec'))
|
||
- return locals()['foo']
|
||
+ dct = {}
|
||
+ exec(compile(funcstr, '<string>', 'exec'), globals(), dct)
|
||
+ return dct['foo']
|
||
|
||
@unittest.skipIf(numpy_version >= (1, 24), "NumPy < 1.24 required")
|
||
def test_MachAr(self):
|
||
Index: numba-0.60.0/numba/tests/test_unicode.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_unicode.py
|
||
+++ numba-0.60.0/numba/tests/test_unicode.py
|
||
@@ -6,10 +6,12 @@ from numba import njit, typeof
|
||
from numba.core import types
|
||
import unittest
|
||
from numba.tests.support import (TestCase, no_pyobj_flags, MemoryLeakMixin)
|
||
-from numba.core.errors import TypingError, UnsupportedError
|
||
+from numba.core.errors import (TypingError, UnsupportedError,
|
||
+ UnsupportedBytecodeError)
|
||
from numba.cpython.unicode import _MAX_UNICODE
|
||
from numba.core.types.functions import _header_lead
|
||
from numba.extending import overload
|
||
+from numba.core.utils import PYVERSION
|
||
|
||
|
||
def isascii(s):
|
||
@@ -2697,10 +2699,17 @@ class TestUnicodeAuxillary(BaseTest):
|
||
self.assertEqual(got, expected)
|
||
|
||
# check error when format spec provided
|
||
- with self.assertRaises(UnsupportedError) as raises:
|
||
+ unsupported_errors = (UnsupportedError, UnsupportedBytecodeError)
|
||
+ with self.assertRaises(unsupported_errors) as raises:
|
||
njit(impl4)(["A", "B"])
|
||
- msg = "format spec in f-strings not supported yet"
|
||
- self.assertIn(msg, str(raises.exception))
|
||
+ if PYVERSION in ((3, 13),):
|
||
+ msg = "Use of unsupported opcode (FORMAT_WITH_SPEC)"
|
||
+ self.assertIn(msg, str(raises.exception))
|
||
+ elif PYVERSION in ((3, 10), (3, 11), (3, 12)):
|
||
+ msg = "format spec in f-strings not supported yet"
|
||
+ self.assertIn(msg, str(raises.exception))
|
||
+ else:
|
||
+ raise NotImplementedError(PYVERSION)
|
||
self.assertEqual(impl5(), njit(impl5)())
|
||
|
||
|
||
Index: numba-0.60.0/numba/core/ir.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/ir.py
|
||
+++ numba-0.60.0/numba/core/ir.py
|
||
@@ -90,9 +90,12 @@ class Loc(object):
|
||
|
||
def get_lines(self):
|
||
if self.lines is None:
|
||
-
|
||
- self.lines = linecache.getlines(self._get_path())
|
||
-
|
||
+ path = self._get_path()
|
||
+ # Avoid reading from dynamic string. They are most likely
|
||
+ # overridden. Problem started with Python 3.13. "<string>" seems
|
||
+ # to be something from multiprocessing.
|
||
+ lns = [] if path == "<string>" else linecache.getlines(path)
|
||
+ self.lines = lns
|
||
return self.lines
|
||
|
||
def _get_path(self):
|
||
@@ -1496,7 +1499,7 @@ class FunctionIR(object):
|
||
self.block_entry_vars = {}
|
||
|
||
def derive(self, blocks, arg_count=None, arg_names=None,
|
||
- force_non_generator=False):
|
||
+ force_non_generator=False, loc=None):
|
||
"""
|
||
Derive a new function IR from this one, using the given blocks,
|
||
and possibly modifying the argument count and generator flag.
|
||
@@ -1507,7 +1510,7 @@ class FunctionIR(object):
|
||
|
||
new_ir = copy.copy(self)
|
||
new_ir.blocks = blocks
|
||
- new_ir.loc = firstblock.loc
|
||
+ new_ir.loc = firstblock.loc if loc is None else loc
|
||
if force_non_generator:
|
||
new_ir.is_generator = False
|
||
if arg_count is not None:
|
||
Index: numba-0.60.0/numba/core/transforms.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/transforms.py
|
||
+++ numba-0.60.0/numba/core/transforms.py
|
||
@@ -191,12 +191,20 @@ def _loop_lift_modify_blocks(func_ir, lo
|
||
loopblocks = dict((k, blocks[k].copy()) for k in loopblockkeys)
|
||
# Modify the loop blocks
|
||
_loop_lift_prepare_loop_func(loopinfo, loopblocks)
|
||
-
|
||
+ # Since Python 3.13, [END_FOR, POP_TOP] sequence becomes the start of the
|
||
+ # block causing the block to have line number of the start of previous loop.
|
||
+ # Fix this using the loc of the first getiter.
|
||
+ getiter_exprs = []
|
||
+ for blk in loopblocks.values():
|
||
+ getiter_exprs.extend(blk.find_exprs(op="getiter"))
|
||
+ first_getiter = min(getiter_exprs, key=lambda x: x.loc.line)
|
||
+ loop_loc = first_getiter.loc
|
||
# Create a new IR for the lifted loop
|
||
lifted_ir = func_ir.derive(blocks=loopblocks,
|
||
arg_names=tuple(loopinfo.inputs),
|
||
arg_count=len(loopinfo.inputs),
|
||
- force_non_generator=True)
|
||
+ force_non_generator=True,
|
||
+ loc=loop_loc)
|
||
liftedloop = LiftedLoop(lifted_ir,
|
||
typingctx, targetctx, flags, locals)
|
||
|
||
Index: numba-0.60.0/numba/tests/test_exceptions.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_exceptions.py
|
||
+++ numba-0.60.0/numba/tests/test_exceptions.py
|
||
@@ -6,6 +6,7 @@ from numba import jit, njit
|
||
from numba.core import types, errors, utils
|
||
from numba.tests.support import (TestCase, expected_failure_py311,
|
||
expected_failure_py312,
|
||
+ expected_failure_py313,
|
||
)
|
||
import unittest
|
||
|
||
@@ -440,6 +441,7 @@ class TestRaising(TestCase):
|
||
|
||
@expected_failure_py311
|
||
@expected_failure_py312
|
||
+ @expected_failure_py313
|
||
def test_dynamic_raise(self):
|
||
|
||
@njit
|
||
Index: numba-0.60.0/numba/tests/test_try_except.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_try_except.py
|
||
+++ numba-0.60.0/numba/tests/test_try_except.py
|
||
@@ -8,12 +8,13 @@ from numba import njit, typed, objmode,
|
||
from numba.core.utils import PYVERSION
|
||
from numba.core import ir_utils, ir
|
||
from numba.core.errors import (
|
||
- UnsupportedError, CompilerError, NumbaPerformanceWarning, TypingError,
|
||
+ CompilerError, NumbaPerformanceWarning, TypingError,
|
||
+ UnsupportedBytecodeError,
|
||
)
|
||
from numba.tests.support import (
|
||
TestCase, unittest, captured_stdout, MemoryLeakMixin,
|
||
skip_parfors_unsupported, skip_unless_scipy, expected_failure_py311,
|
||
- expected_failure_py312
|
||
+ expected_failure_py312, expected_failure_py313,
|
||
)
|
||
|
||
|
||
@@ -372,7 +373,7 @@ class TestTryBareExcept(TestCase):
|
||
except: # noqa: E722
|
||
raise
|
||
|
||
- with self.assertRaises(UnsupportedError) as raises:
|
||
+ with self.assertRaises(UnsupportedBytecodeError) as raises:
|
||
udt()
|
||
self.assertIn(
|
||
"The re-raising of an exception is not yet supported.",
|
||
@@ -459,7 +460,7 @@ class TestTryExceptCaught(TestCase):
|
||
return r
|
||
return r
|
||
|
||
- with self.assertRaises(UnsupportedError) as raises:
|
||
+ with self.assertRaises(UnsupportedBytecodeError) as raises:
|
||
udt(True)
|
||
self.assertIn(
|
||
"Exception object cannot be stored into variable (e)",
|
||
@@ -474,7 +475,7 @@ class TestTryExceptCaught(TestCase):
|
||
except Exception:
|
||
raise
|
||
|
||
- with self.assertRaises(UnsupportedError) as raises:
|
||
+ with self.assertRaises(UnsupportedBytecodeError) as raises:
|
||
udt()
|
||
self.assertIn(
|
||
"The re-raising of an exception is not yet supported.",
|
||
@@ -492,7 +493,7 @@ class TestTryExceptCaught(TestCase):
|
||
except Exception:
|
||
raise
|
||
|
||
- with self.assertRaises(UnsupportedError) as raises:
|
||
+ with self.assertRaises(UnsupportedBytecodeError) as raises:
|
||
udt()
|
||
self.assertIn(
|
||
"The re-raising of an exception is not yet supported.",
|
||
@@ -692,6 +693,7 @@ class TestTryExceptOtherControlFlow(Test
|
||
|
||
@expected_failure_py311
|
||
@expected_failure_py312
|
||
+ @expected_failure_py313
|
||
def test_objmode(self):
|
||
@njit
|
||
def udt():
|
||
@@ -712,6 +714,7 @@ class TestTryExceptOtherControlFlow(Test
|
||
|
||
@expected_failure_py311
|
||
@expected_failure_py312
|
||
+ @expected_failure_py313
|
||
def test_objmode_output_type(self):
|
||
def bar(x):
|
||
return np.asarray(list(reversed(x.tolist())))
|
||
Index: numba-0.60.0/numba/tests/test_withlifting.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_withlifting.py
|
||
+++ numba-0.60.0/numba/tests/test_withlifting.py
|
||
@@ -16,7 +16,8 @@ from numba.tests.support import (MemoryL
|
||
skip_unless_scipy, linux_only,
|
||
strace_supported, strace,
|
||
expected_failure_py311,
|
||
- expected_failure_py312)
|
||
+ expected_failure_py312,
|
||
+ expected_failure_py313)
|
||
from numba.core.utils import PYVERSION
|
||
from numba.experimental import jitclass
|
||
import unittest
|
||
@@ -280,6 +281,7 @@ class TestLiftCall(BaseTestWithLifting):
|
||
|
||
@expected_failure_py311
|
||
@expected_failure_py312
|
||
+ @expected_failure_py313
|
||
def test_liftcall5(self):
|
||
self.check_extracted_with(liftcall5, expect_count=1,
|
||
expected_stdout="0\n1\n2\n3\n4\n5\nA\n")
|
||
@@ -719,6 +721,7 @@ class TestLiftObj(MemoryLeak, TestCase):
|
||
|
||
@expected_failure_py311
|
||
@expected_failure_py312
|
||
+ @expected_failure_py313
|
||
def test_case19_recursion(self):
|
||
def foo(x):
|
||
with objmode_context():
|
||
@@ -1169,7 +1172,7 @@ class TestBogusContext(BaseTestWithLifti
|
||
with open('') as f:
|
||
pass
|
||
|
||
- with self.assertRaises(errors.UnsupportedError) as raises:
|
||
+ with self.assertRaises(errors.UnsupportedBytecodeError) as raises:
|
||
foo()
|
||
|
||
excstr = str(raises.exception)
|
||
Index: numba-0.60.0/numba/tests/test_sys_monitoring.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_sys_monitoring.py
|
||
+++ numba-0.60.0/numba/tests/test_sys_monitoring.py
|
||
@@ -4,7 +4,7 @@ import sys
|
||
import threading
|
||
import unittest
|
||
from unittest.mock import Mock, call
|
||
-from numba.tests.support import TestCase, skip_unless_py312
|
||
+from numba.tests.support import TestCase
|
||
from numba import jit, objmode
|
||
from numba.core.utils import PYVERSION
|
||
from numba.core.serialize import _numba_unpickle
|
||
@@ -21,7 +21,7 @@ def generate_usecase():
|
||
return foo, call_foo
|
||
|
||
|
||
-if PYVERSION == (3, 12):
|
||
+if PYVERSION in ((3, 12), (3, 13)):
|
||
PY_START = sys.monitoring.events.PY_START
|
||
PY_RETURN = sys.monitoring.events.PY_RETURN
|
||
RAISE = sys.monitoring.events.RAISE
|
||
@@ -36,7 +36,7 @@ TOOL2MONITORTYPE = {0 : "Debugger",
|
||
5 : "Optimizer"}
|
||
|
||
|
||
-@skip_unless_py312
|
||
+@unittest.skipUnless(PYVERSION >= (3, 12), "needs Python 3.12+")
|
||
class TestMonitoring(TestCase):
|
||
# Tests the interaction of the Numba dispatcher with `sys.monitoring`.
|
||
#
|
||
@@ -724,7 +724,7 @@ class TestMonitoring(TestCase):
|
||
self.assertFalse(q2.qsize())
|
||
|
||
|
||
-@skip_unless_py312
|
||
+@unittest.skipUnless(PYVERSION >= (3, 12), "needs Python 3.12+")
|
||
class TestMonitoringSelfTest(TestCase):
|
||
|
||
def test_skipping_of_tests_if_monitoring_in_use(self):
|
||
Index: numba-0.60.0/numba/_random.c
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/_random.c
|
||
+++ numba-0.60.0/numba/_random.c
|
||
@@ -195,7 +195,7 @@ rnd_implicit_init(rnd_state_t *state)
|
||
Py_buffer buf;
|
||
PyGILState_STATE gilstate = PyGILState_Ensure();
|
||
|
||
- module = PyImport_ImportModuleNoBlock("os");
|
||
+ module = PyImport_ImportModule("os");
|
||
if (module == NULL)
|
||
goto error;
|
||
/* Read as many bytes as necessary to get the full entropy
|
||
Index: numba-0.60.0/numba/core/pythonapi.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/pythonapi.py
|
||
+++ numba-0.60.0/numba/core/pythonapi.py
|
||
@@ -919,9 +919,9 @@ class PythonAPI(object):
|
||
# Other APIs (organize them better!)
|
||
#
|
||
|
||
- def import_module_noblock(self, modname):
|
||
+ def import_module(self, modname):
|
||
fnty = ir.FunctionType(self.pyobj, [self.cstring])
|
||
- fn = self._get_function(fnty, name="PyImport_ImportModuleNoBlock")
|
||
+ fn = self._get_function(fnty, name="PyImport_ImportModule")
|
||
return self.builder.call(fn, [modname])
|
||
|
||
def call_function_objargs(self, callee, objargs):
|
||
Index: numba-0.60.0/numba/experimental/function_type.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/experimental/function_type.py
|
||
+++ numba-0.60.0/numba/experimental/function_type.py
|
||
@@ -181,7 +181,7 @@ def lower_get_wrapper_address(context, b
|
||
# caller.
|
||
|
||
modname = context.insert_const_string(builder.module, __name__)
|
||
- numba_mod = pyapi.import_module_noblock(modname)
|
||
+ numba_mod = pyapi.import_module(modname)
|
||
numba_func = pyapi.object_getattr_string(
|
||
numba_mod, '_get_wrapper_address')
|
||
pyapi.decref(numba_mod)
|
||
@@ -263,3 +263,4 @@ def lower_cast_dispatcher_to_function_ty
|
||
llty = context.get_value_type(types.voidptr)
|
||
sfunc.pyaddr = builder.ptrtoint(val, llty)
|
||
return sfunc._getvalue()
|
||
+
|
||
Index: numba-0.60.0/numba/typed/typeddict.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/typed/typeddict.py
|
||
+++ numba-0.60.0/numba/typed/typeddict.py
|
||
@@ -266,7 +266,7 @@ def box_dicttype(typ, val, c):
|
||
modname = c.context.insert_const_string(
|
||
c.builder.module, 'numba.typed.typeddict',
|
||
)
|
||
- typeddict_mod = c.pyapi.import_module_noblock(modname)
|
||
+ typeddict_mod = c.pyapi.import_module(modname)
|
||
fmp_fn = c.pyapi.object_getattr_string(typeddict_mod, '_from_meminfo_ptr')
|
||
|
||
dicttype_obj = c.pyapi.unserialize(c.pyapi.serialize_object(typ))
|
||
Index: numba-0.60.0/numba/typed/typedlist.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/typed/typedlist.py
|
||
+++ numba-0.60.0/numba/typed/typedlist.py
|
||
@@ -471,7 +471,7 @@ def box_lsttype(typ, val, c):
|
||
modname = c.context.insert_const_string(
|
||
c.builder.module, 'numba.typed.typedlist',
|
||
)
|
||
- typedlist_mod = c.pyapi.import_module_noblock(modname)
|
||
+ typedlist_mod = c.pyapi.import_module(modname)
|
||
fmp_fn = c.pyapi.object_getattr_string(typedlist_mod, '_from_meminfo_ptr')
|
||
|
||
lsttype_obj = c.pyapi.unserialize(c.pyapi.serialize_object(typ))
|
||
Index: numba-0.60.0/numba/tests/test_interpreter.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_interpreter.py
|
||
+++ numba-0.60.0/numba/tests/test_interpreter.py
|
||
@@ -5,7 +5,7 @@ import unittest
|
||
from numba import jit, njit, objmode, typeof, literally
|
||
from numba.extending import overload
|
||
from numba.core import types
|
||
-from numba.core.errors import UnsupportedError
|
||
+from numba.core.errors import UnsupportedBytecodeError
|
||
from numba.tests.support import (
|
||
TestCase,
|
||
MemoryLeakMixin,
|
||
@@ -388,7 +388,7 @@ class TestCallFunctionExPeepHole(MemoryL
|
||
arg41=1,
|
||
)
|
||
|
||
- with self.assertRaises(UnsupportedError) as raises:
|
||
+ with self.assertRaises(UnsupportedBytecodeError) as raises:
|
||
njit()(inline_func)(False)
|
||
self.assertIn(
|
||
'You can resolve this issue by moving the control flow out',
|
||
@@ -498,7 +498,7 @@ class TestCallFunctionExPeepHole(MemoryL
|
||
1,
|
||
)
|
||
|
||
- with self.assertRaises(UnsupportedError) as raises:
|
||
+ with self.assertRaises(UnsupportedBytecodeError) as raises:
|
||
njit()(inline_func)(False)
|
||
self.assertIn(
|
||
'You can resolve this issue by moving the control flow out',
|
||
@@ -585,7 +585,7 @@ class TestCallFunctionExPeepHole(MemoryL
|
||
arg15=1 if flag else 2,
|
||
)
|
||
|
||
- with self.assertRaises(UnsupportedError) as raises:
|
||
+ with self.assertRaises(UnsupportedBytecodeError) as raises:
|
||
njit()(inline_func)(False)
|
||
self.assertIn(
|
||
'You can resolve this issue by moving the control flow out',
|
||
@@ -973,7 +973,7 @@ class TestLargeConstDict(TestCase, Memor
|
||
}
|
||
return d["S"]
|
||
|
||
- with self.assertRaises(UnsupportedError) as raises:
|
||
+ with self.assertRaises(UnsupportedBytecodeError) as raises:
|
||
njit()(inline_func)("a_string", False)
|
||
self.assertIn(
|
||
'You can resolve this issue by moving the control flow out',
|
||
Index: numba-0.60.0/numba/tests/test_tuples.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/tests/test_tuples.py
|
||
+++ numba-0.60.0/numba/tests/test_tuples.py
|
||
@@ -731,7 +731,7 @@ class TestTupleBuild(TestCase):
|
||
b = (3,2, 4)
|
||
return (*(b if a[0] else (5, 6)),)
|
||
|
||
- with self.assertRaises(errors.UnsupportedError) as raises:
|
||
+ with self.assertRaises(errors.UnsupportedBytecodeError) as raises:
|
||
foo()
|
||
msg = "op_LIST_EXTEND at the start of a block"
|
||
self.assertIn(msg, str(raises.exception))
|
||
Index: numba-0.60.0/setup.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/setup.py
|
||
+++ numba-0.60.0/setup.py
|
||
@@ -20,7 +20,7 @@ except ImportError:
|
||
|
||
|
||
min_python_version = "3.9"
|
||
-max_python_version = "3.13" # exclusive
|
||
+max_python_version = "3.14" # exclusive
|
||
min_numpy_build_version = "2.0.0rc1"
|
||
min_numpy_run_version = "1.22"
|
||
max_numpy_run_version = "2.1"
|
||
Index: numba-0.60.0/numba/core/boxing.py
|
||
===================================================================
|
||
--- numba-0.60.0.orig/numba/core/boxing.py
|
||
+++ numba-0.60.0/numba/core/boxing.py
|
||
@@ -655,7 +655,7 @@ class _NumbaTypeHelper(object):
|
||
def __enter__(self):
|
||
c = self.c
|
||
numba_name = c.context.insert_const_string(c.builder.module, 'numba')
|
||
- numba_mod = c.pyapi.import_module_noblock(numba_name)
|
||
+ numba_mod = c.pyapi.import_module(numba_name)
|
||
typeof_fn = c.pyapi.object_getattr_string(numba_mod, 'typeof')
|
||
self.typeof_fn = typeof_fn
|
||
c.pyapi.decref(numba_mod)
|
||
@@ -1213,7 +1213,7 @@ def unbox_numpy_random_bitgenerator(typ,
|
||
# store the results.
|
||
# First find ctypes.cast, and ctypes.c_void_p
|
||
ctypes_name = c.context.insert_const_string(c.builder.module, 'ctypes')
|
||
- ctypes_module = c.pyapi.import_module_noblock(ctypes_name)
|
||
+ ctypes_module = c.pyapi.import_module(ctypes_name)
|
||
extra_refs.append(ctypes_module)
|
||
with cgutils.early_exit_if_null(c.builder, stack, ctypes_module):
|
||
handle_failure()
|
||
Index: numba-0.60.0/numba/pythoncapi_compat.h
|
||
===================================================================
|
||
--- /dev/null
|
||
+++ numba-0.60.0/numba/pythoncapi_compat.h
|
||
@@ -0,0 +1,1696 @@
|
||
+// Header file providing new C API functions to old Python versions.
|
||
+//
|
||
+// File distributed under the Zero Clause BSD (0BSD) license.
|
||
+// Copyright Contributors to the pythoncapi_compat project.
|
||
+//
|
||
+// Homepage:
|
||
+// https://github.com/python/pythoncapi_compat
|
||
+//
|
||
+// Latest version:
|
||
+// https://raw.githubusercontent.com/python/pythoncapi-compat/0041177c4f348c8952b4c8980b2c90856e61c7c7/pythoncapi_compat.h
|
||
+//
|
||
+// SPDX-License-Identifier: 0BSD
|
||
+
|
||
+#ifndef PYTHONCAPI_COMPAT
|
||
+#define PYTHONCAPI_COMPAT
|
||
+
|
||
+#ifdef __cplusplus
|
||
+extern "C" {
|
||
+#endif
|
||
+
|
||
+#include <Python.h>
|
||
+
|
||
+// Python 3.11.0b4 added PyFrame_Back() to Python.h
|
||
+#if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION)
|
||
+# include "frameobject.h" // PyFrameObject, PyFrame_GetBack()
|
||
+#endif
|
||
+
|
||
+
|
||
+#ifndef _Py_CAST
|
||
+# define _Py_CAST(type, expr) ((type)(expr))
|
||
+#endif
|
||
+
|
||
+// Static inline functions should use _Py_NULL rather than using directly NULL
|
||
+// to prevent C++ compiler warnings. On C23 and newer and on C++11 and newer,
|
||
+// _Py_NULL is defined as nullptr.
|
||
+#if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L) \
|
||
+ || (defined(__cplusplus) && __cplusplus >= 201103)
|
||
+# define _Py_NULL nullptr
|
||
+#else
|
||
+# define _Py_NULL NULL
|
||
+#endif
|
||
+
|
||
+// Cast argument to PyObject* type.
|
||
+#ifndef _PyObject_CAST
|
||
+# define _PyObject_CAST(op) _Py_CAST(PyObject*, op)
|
||
+#endif
|
||
+
|
||
+#ifndef Py_BUILD_ASSERT
|
||
+# define Py_BUILD_ASSERT(cond) \
|
||
+ do { \
|
||
+ (void)sizeof(char [1 - 2 * !(cond)]); \
|
||
+ } while(0)
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-42262 added Py_NewRef() to Python 3.10.0a3
|
||
+#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef)
|
||
+static inline PyObject* _Py_NewRef(PyObject *obj)
|
||
+{
|
||
+ Py_INCREF(obj);
|
||
+ return obj;
|
||
+}
|
||
+#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-42262 added Py_XNewRef() to Python 3.10.0a3
|
||
+#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef)
|
||
+static inline PyObject* _Py_XNewRef(PyObject *obj)
|
||
+{
|
||
+ Py_XINCREF(obj);
|
||
+ return obj;
|
||
+}
|
||
+#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4
|
||
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT)
|
||
+static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt)
|
||
+{
|
||
+ ob->ob_refcnt = refcnt;
|
||
+}
|
||
+#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt)
|
||
+#endif
|
||
+
|
||
+
|
||
+// Py_SETREF() and Py_XSETREF() were added to Python 3.5.2.
|
||
+// It is excluded from the limited C API.
|
||
+#if (PY_VERSION_HEX < 0x03050200 && !defined(Py_SETREF)) && !defined(Py_LIMITED_API)
|
||
+#define Py_SETREF(dst, src) \
|
||
+ do { \
|
||
+ PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
|
||
+ PyObject *_tmp_dst = (*_tmp_dst_ptr); \
|
||
+ *_tmp_dst_ptr = _PyObject_CAST(src); \
|
||
+ Py_DECREF(_tmp_dst); \
|
||
+ } while (0)
|
||
+
|
||
+#define Py_XSETREF(dst, src) \
|
||
+ do { \
|
||
+ PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
|
||
+ PyObject *_tmp_dst = (*_tmp_dst_ptr); \
|
||
+ *_tmp_dst_ptr = _PyObject_CAST(src); \
|
||
+ Py_XDECREF(_tmp_dst); \
|
||
+ } while (0)
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-43753 added Py_Is(), Py_IsNone(), Py_IsTrue() and Py_IsFalse()
|
||
+// to Python 3.10.0b1.
|
||
+#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_Is)
|
||
+# define Py_Is(x, y) ((x) == (y))
|
||
+#endif
|
||
+#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsNone)
|
||
+# define Py_IsNone(x) Py_Is(x, Py_None)
|
||
+#endif
|
||
+#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsTrue)
|
||
+# define Py_IsTrue(x) Py_Is(x, Py_True)
|
||
+#endif
|
||
+#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsFalse)
|
||
+# define Py_IsFalse(x) Py_Is(x, Py_False)
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4
|
||
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
|
||
+static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type)
|
||
+{
|
||
+ ob->ob_type = type;
|
||
+}
|
||
+#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type)
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4
|
||
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
|
||
+static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size)
|
||
+{
|
||
+ ob->ob_size = size;
|
||
+}
|
||
+#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size)
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
|
||
+#if PY_VERSION_HEX < 0x030900B1 || defined(PYPY_VERSION)
|
||
+static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)
|
||
+{
|
||
+ assert(frame != _Py_NULL);
|
||
+ assert(frame->f_code != _Py_NULL);
|
||
+ return _Py_CAST(PyCodeObject*, Py_NewRef(frame->f_code));
|
||
+}
|
||
+#endif
|
||
+
|
||
+static inline PyCodeObject* _PyFrame_GetCodeBorrow(PyFrameObject *frame)
|
||
+{
|
||
+ PyCodeObject *code = PyFrame_GetCode(frame);
|
||
+ Py_DECREF(code);
|
||
+ return code;
|
||
+}
|
||
+
|
||
+
|
||
+// bpo-40421 added PyFrame_GetBack() to Python 3.9.0b1
|
||
+#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
|
||
+static inline PyFrameObject* PyFrame_GetBack(PyFrameObject *frame)
|
||
+{
|
||
+ assert(frame != _Py_NULL);
|
||
+ return _Py_CAST(PyFrameObject*, Py_XNewRef(frame->f_back));
|
||
+}
|
||
+#endif
|
||
+
|
||
+#if !defined(PYPY_VERSION)
|
||
+static inline PyFrameObject* _PyFrame_GetBackBorrow(PyFrameObject *frame)
|
||
+{
|
||
+ PyFrameObject *back = PyFrame_GetBack(frame);
|
||
+ Py_XDECREF(back);
|
||
+ return back;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-40421 added PyFrame_GetLocals() to Python 3.11.0a7
|
||
+#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
|
||
+static inline PyObject* PyFrame_GetLocals(PyFrameObject *frame)
|
||
+{
|
||
+#if PY_VERSION_HEX >= 0x030400B1
|
||
+ if (PyFrame_FastToLocalsWithError(frame) < 0) {
|
||
+ return NULL;
|
||
+ }
|
||
+#else
|
||
+ PyFrame_FastToLocals(frame);
|
||
+#endif
|
||
+ return Py_NewRef(frame->f_locals);
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-40421 added PyFrame_GetGlobals() to Python 3.11.0a7
|
||
+#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
|
||
+static inline PyObject* PyFrame_GetGlobals(PyFrameObject *frame)
|
||
+{
|
||
+ return Py_NewRef(frame->f_globals);
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-40421 added PyFrame_GetBuiltins() to Python 3.11.0a7
|
||
+#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
|
||
+static inline PyObject* PyFrame_GetBuiltins(PyFrameObject *frame)
|
||
+{
|
||
+ return Py_NewRef(frame->f_builtins);
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1
|
||
+#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
|
||
+static inline int PyFrame_GetLasti(PyFrameObject *frame)
|
||
+{
|
||
+#if PY_VERSION_HEX >= 0x030A00A7
|
||
+ // bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset,
|
||
+ // not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes)
|
||
+ // instructions.
|
||
+ if (frame->f_lasti < 0) {
|
||
+ return -1;
|
||
+ }
|
||
+ return frame->f_lasti * 2;
|
||
+#else
|
||
+ return frame->f_lasti;
|
||
+#endif
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-91248 added PyFrame_GetVar() to Python 3.12.0a2
|
||
+#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION)
|
||
+static inline PyObject* PyFrame_GetVar(PyFrameObject *frame, PyObject *name)
|
||
+{
|
||
+ PyObject *locals, *value;
|
||
+
|
||
+ locals = PyFrame_GetLocals(frame);
|
||
+ if (locals == NULL) {
|
||
+ return NULL;
|
||
+ }
|
||
+#if PY_VERSION_HEX >= 0x03000000
|
||
+ value = PyDict_GetItemWithError(locals, name);
|
||
+#else
|
||
+ value = _PyDict_GetItemWithError(locals, name);
|
||
+#endif
|
||
+ Py_DECREF(locals);
|
||
+
|
||
+ if (value == NULL) {
|
||
+ if (PyErr_Occurred()) {
|
||
+ return NULL;
|
||
+ }
|
||
+#if PY_VERSION_HEX >= 0x03000000
|
||
+ PyErr_Format(PyExc_NameError, "variable %R does not exist", name);
|
||
+#else
|
||
+ PyErr_SetString(PyExc_NameError, "variable does not exist");
|
||
+#endif
|
||
+ return NULL;
|
||
+ }
|
||
+ return Py_NewRef(value);
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-91248 added PyFrame_GetVarString() to Python 3.12.0a2
|
||
+#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION)
|
||
+static inline PyObject*
|
||
+PyFrame_GetVarString(PyFrameObject *frame, const char *name)
|
||
+{
|
||
+ PyObject *name_obj, *value;
|
||
+#if PY_VERSION_HEX >= 0x03000000
|
||
+ name_obj = PyUnicode_FromString(name);
|
||
+#else
|
||
+ name_obj = PyString_FromString(name);
|
||
+#endif
|
||
+ if (name_obj == NULL) {
|
||
+ return NULL;
|
||
+ }
|
||
+ value = PyFrame_GetVar(frame, name_obj);
|
||
+ Py_DECREF(name_obj);
|
||
+ return value;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5
|
||
+#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
|
||
+static inline PyInterpreterState *
|
||
+PyThreadState_GetInterpreter(PyThreadState *tstate)
|
||
+{
|
||
+ assert(tstate != _Py_NULL);
|
||
+ return tstate->interp;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1
|
||
+#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
|
||
+static inline PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
|
||
+{
|
||
+ assert(tstate != _Py_NULL);
|
||
+ return _Py_CAST(PyFrameObject *, Py_XNewRef(tstate->frame));
|
||
+}
|
||
+#endif
|
||
+
|
||
+#if !defined(PYPY_VERSION)
|
||
+static inline PyFrameObject*
|
||
+_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
|
||
+{
|
||
+ PyFrameObject *frame = PyThreadState_GetFrame(tstate);
|
||
+ Py_XDECREF(frame);
|
||
+ return frame;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5
|
||
+#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
|
||
+static inline PyInterpreterState* PyInterpreterState_Get(void)
|
||
+{
|
||
+ PyThreadState *tstate;
|
||
+ PyInterpreterState *interp;
|
||
+
|
||
+ tstate = PyThreadState_GET();
|
||
+ if (tstate == _Py_NULL) {
|
||
+ Py_FatalError("GIL released (tstate is NULL)");
|
||
+ }
|
||
+ interp = tstate->interp;
|
||
+ if (interp == _Py_NULL) {
|
||
+ Py_FatalError("no current interpreter");
|
||
+ }
|
||
+ return interp;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6
|
||
+#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
|
||
+static inline uint64_t PyThreadState_GetID(PyThreadState *tstate)
|
||
+{
|
||
+ assert(tstate != _Py_NULL);
|
||
+ return tstate->id;
|
||
+}
|
||
+#endif
|
||
+
|
||
+// bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2
|
||
+#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
|
||
+static inline void PyThreadState_EnterTracing(PyThreadState *tstate)
|
||
+{
|
||
+ tstate->tracing++;
|
||
+#if PY_VERSION_HEX >= 0x030A00A1
|
||
+ tstate->cframe->use_tracing = 0;
|
||
+#else
|
||
+ tstate->use_tracing = 0;
|
||
+#endif
|
||
+}
|
||
+#endif
|
||
+
|
||
+// bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2
|
||
+#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
|
||
+static inline void PyThreadState_LeaveTracing(PyThreadState *tstate)
|
||
+{
|
||
+ int use_tracing = (tstate->c_tracefunc != _Py_NULL
|
||
+ || tstate->c_profilefunc != _Py_NULL);
|
||
+ tstate->tracing--;
|
||
+#if PY_VERSION_HEX >= 0x030A00A1
|
||
+ tstate->cframe->use_tracing = use_tracing;
|
||
+#else
|
||
+ tstate->use_tracing = use_tracing;
|
||
+#endif
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1
|
||
+// PyObject_CallNoArgs() added to PyPy 3.9.16-v7.3.11
|
||
+#if !defined(PyObject_CallNoArgs) && PY_VERSION_HEX < 0x030900A1
|
||
+static inline PyObject* PyObject_CallNoArgs(PyObject *func)
|
||
+{
|
||
+ return PyObject_CallFunctionObjArgs(func, NULL);
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-39245 made PyObject_CallOneArg() public (previously called
|
||
+// _PyObject_CallOneArg) in Python 3.9.0a4
|
||
+// PyObject_CallOneArg() added to PyPy 3.9.16-v7.3.11
|
||
+#if !defined(PyObject_CallOneArg) && PY_VERSION_HEX < 0x030900A4
|
||
+static inline PyObject* PyObject_CallOneArg(PyObject *func, PyObject *arg)
|
||
+{
|
||
+ return PyObject_CallFunctionObjArgs(func, arg, NULL);
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3
|
||
+#if PY_VERSION_HEX < 0x030A00A3
|
||
+static inline int
|
||
+PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value)
|
||
+{
|
||
+ int res;
|
||
+
|
||
+ if (!value && !PyErr_Occurred()) {
|
||
+ // PyModule_AddObject() raises TypeError in this case
|
||
+ PyErr_SetString(PyExc_SystemError,
|
||
+ "PyModule_AddObjectRef() must be called "
|
||
+ "with an exception raised if value is NULL");
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ Py_XINCREF(value);
|
||
+ res = PyModule_AddObject(module, name, value);
|
||
+ if (res < 0) {
|
||
+ Py_XDECREF(value);
|
||
+ }
|
||
+ return res;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-40024 added PyModule_AddType() to Python 3.9.0a5
|
||
+#if PY_VERSION_HEX < 0x030900A5
|
||
+static inline int PyModule_AddType(PyObject *module, PyTypeObject *type)
|
||
+{
|
||
+ const char *name, *dot;
|
||
+
|
||
+ if (PyType_Ready(type) < 0) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ // inline _PyType_Name()
|
||
+ name = type->tp_name;
|
||
+ assert(name != _Py_NULL);
|
||
+ dot = strrchr(name, '.');
|
||
+ if (dot != _Py_NULL) {
|
||
+ name = dot + 1;
|
||
+ }
|
||
+
|
||
+ return PyModule_AddObjectRef(module, name, _PyObject_CAST(type));
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6.
|
||
+// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2.
|
||
+#if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
|
||
+static inline int PyObject_GC_IsTracked(PyObject* obj)
|
||
+{
|
||
+ return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj));
|
||
+}
|
||
+#endif
|
||
+
|
||
+// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6.
|
||
+// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final.
|
||
+#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION)
|
||
+static inline int PyObject_GC_IsFinalized(PyObject *obj)
|
||
+{
|
||
+ PyGC_Head *gc = _Py_CAST(PyGC_Head*, obj) - 1;
|
||
+ return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc));
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4
|
||
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE)
|
||
+static inline int _Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
|
||
+ return Py_TYPE(ob) == type;
|
||
+}
|
||
+#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type)
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-46906 added PyFloat_Pack2() and PyFloat_Unpack2() to Python 3.11a7.
|
||
+// bpo-11734 added _PyFloat_Pack2() and _PyFloat_Unpack2() to Python 3.6.0b1.
|
||
+// Python 3.11a2 moved _PyFloat_Pack2() and _PyFloat_Unpack2() to the internal
|
||
+// C API: Python 3.11a2-3.11a6 versions are not supported.
|
||
+#if 0x030600B1 <= PY_VERSION_HEX && PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION)
|
||
+static inline int PyFloat_Pack2(double x, char *p, int le)
|
||
+{ return _PyFloat_Pack2(x, (unsigned char*)p, le); }
|
||
+
|
||
+static inline double PyFloat_Unpack2(const char *p, int le)
|
||
+{ return _PyFloat_Unpack2((const unsigned char *)p, le); }
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-46906 added PyFloat_Pack4(), PyFloat_Pack8(), PyFloat_Unpack4() and
|
||
+// PyFloat_Unpack8() to Python 3.11a7.
|
||
+// Python 3.11a2 moved _PyFloat_Pack4(), _PyFloat_Pack8(), _PyFloat_Unpack4()
|
||
+// and _PyFloat_Unpack8() to the internal C API: Python 3.11a2-3.11a6 versions
|
||
+// are not supported.
|
||
+#if PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION)
|
||
+static inline int PyFloat_Pack4(double x, char *p, int le)
|
||
+{ return _PyFloat_Pack4(x, (unsigned char*)p, le); }
|
||
+
|
||
+static inline int PyFloat_Pack8(double x, char *p, int le)
|
||
+{ return _PyFloat_Pack8(x, (unsigned char*)p, le); }
|
||
+
|
||
+static inline double PyFloat_Unpack4(const char *p, int le)
|
||
+{ return _PyFloat_Unpack4((const unsigned char *)p, le); }
|
||
+
|
||
+static inline double PyFloat_Unpack8(const char *p, int le)
|
||
+{ return _PyFloat_Unpack8((const unsigned char *)p, le); }
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-92154 added PyCode_GetCode() to Python 3.11.0b1
|
||
+#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
|
||
+static inline PyObject* PyCode_GetCode(PyCodeObject *code)
|
||
+{
|
||
+ return Py_NewRef(code->co_code);
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-95008 added PyCode_GetVarnames() to Python 3.11.0rc1
|
||
+#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
|
||
+static inline PyObject* PyCode_GetVarnames(PyCodeObject *code)
|
||
+{
|
||
+ return Py_NewRef(code->co_varnames);
|
||
+}
|
||
+#endif
|
||
+
|
||
+// gh-95008 added PyCode_GetFreevars() to Python 3.11.0rc1
|
||
+#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
|
||
+static inline PyObject* PyCode_GetFreevars(PyCodeObject *code)
|
||
+{
|
||
+ return Py_NewRef(code->co_freevars);
|
||
+}
|
||
+#endif
|
||
+
|
||
+// gh-95008 added PyCode_GetCellvars() to Python 3.11.0rc1
|
||
+#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
|
||
+static inline PyObject* PyCode_GetCellvars(PyCodeObject *code)
|
||
+{
|
||
+ return Py_NewRef(code->co_cellvars);
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// Py_UNUSED() was added to Python 3.4.0b2.
|
||
+#if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED)
|
||
+# if defined(__GNUC__) || defined(__clang__)
|
||
+# define Py_UNUSED(name) _unused_ ## name __attribute__((unused))
|
||
+# else
|
||
+# define Py_UNUSED(name) _unused_ ## name
|
||
+# endif
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-105922 added PyImport_AddModuleRef() to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A0
|
||
+static inline PyObject* PyImport_AddModuleRef(const char *name)
|
||
+{
|
||
+ return Py_XNewRef(PyImport_AddModule(name));
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-105927 added PyWeakref_GetRef() to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D0000
|
||
+static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj)
|
||
+{
|
||
+ PyObject *obj;
|
||
+ if (ref != NULL && !PyWeakref_Check(ref)) {
|
||
+ *pobj = NULL;
|
||
+ PyErr_SetString(PyExc_TypeError, "expected a weakref");
|
||
+ return -1;
|
||
+ }
|
||
+ obj = PyWeakref_GetObject(ref);
|
||
+ if (obj == NULL) {
|
||
+ // SystemError if ref is NULL
|
||
+ *pobj = NULL;
|
||
+ return -1;
|
||
+ }
|
||
+ if (obj == Py_None) {
|
||
+ *pobj = NULL;
|
||
+ return 0;
|
||
+ }
|
||
+ *pobj = Py_NewRef(obj);
|
||
+ return (*pobj != NULL);
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// bpo-36974 added PY_VECTORCALL_ARGUMENTS_OFFSET to Python 3.8b1
|
||
+#ifndef PY_VECTORCALL_ARGUMENTS_OFFSET
|
||
+# define PY_VECTORCALL_ARGUMENTS_OFFSET (_Py_CAST(size_t, 1) << (8 * sizeof(size_t) - 1))
|
||
+#endif
|
||
+
|
||
+// bpo-36974 added PyVectorcall_NARGS() to Python 3.8b1
|
||
+#if PY_VERSION_HEX < 0x030800B1
|
||
+static inline Py_ssize_t PyVectorcall_NARGS(size_t n)
|
||
+{
|
||
+ return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-105922 added PyObject_Vectorcall() to Python 3.9.0a4
|
||
+#if PY_VERSION_HEX < 0x030900A4
|
||
+static inline PyObject*
|
||
+PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
|
||
+ size_t nargsf, PyObject *kwnames)
|
||
+{
|
||
+#if PY_VERSION_HEX >= 0x030800B1 && !defined(PYPY_VERSION)
|
||
+ // bpo-36974 added _PyObject_Vectorcall() to Python 3.8.0b1
|
||
+ return _PyObject_Vectorcall(callable, args, nargsf, kwnames);
|
||
+#else
|
||
+ PyObject *posargs = NULL, *kwargs = NULL;
|
||
+ PyObject *res;
|
||
+ Py_ssize_t nposargs, nkwargs, i;
|
||
+
|
||
+ if (nargsf != 0 && args == NULL) {
|
||
+ PyErr_BadInternalCall();
|
||
+ goto error;
|
||
+ }
|
||
+ if (kwnames != NULL && !PyTuple_Check(kwnames)) {
|
||
+ PyErr_BadInternalCall();
|
||
+ goto error;
|
||
+ }
|
||
+
|
||
+ nposargs = (Py_ssize_t)PyVectorcall_NARGS(nargsf);
|
||
+ if (kwnames) {
|
||
+ nkwargs = PyTuple_GET_SIZE(kwnames);
|
||
+ }
|
||
+ else {
|
||
+ nkwargs = 0;
|
||
+ }
|
||
+
|
||
+ posargs = PyTuple_New(nposargs);
|
||
+ if (posargs == NULL) {
|
||
+ goto error;
|
||
+ }
|
||
+ if (nposargs) {
|
||
+ for (i=0; i < nposargs; i++) {
|
||
+ PyTuple_SET_ITEM(posargs, i, Py_NewRef(*args));
|
||
+ args++;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (nkwargs) {
|
||
+ kwargs = PyDict_New();
|
||
+ if (kwargs == NULL) {
|
||
+ goto error;
|
||
+ }
|
||
+
|
||
+ for (i = 0; i < nkwargs; i++) {
|
||
+ PyObject *key = PyTuple_GET_ITEM(kwnames, i);
|
||
+ PyObject *value = *args;
|
||
+ args++;
|
||
+ if (PyDict_SetItem(kwargs, key, value) < 0) {
|
||
+ goto error;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ else {
|
||
+ kwargs = NULL;
|
||
+ }
|
||
+
|
||
+ res = PyObject_Call(callable, posargs, kwargs);
|
||
+ Py_DECREF(posargs);
|
||
+ Py_XDECREF(kwargs);
|
||
+ return res;
|
||
+
|
||
+error:
|
||
+ Py_DECREF(posargs);
|
||
+ Py_XDECREF(kwargs);
|
||
+ return NULL;
|
||
+#endif
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-106521 added PyObject_GetOptionalAttr() and
|
||
+// PyObject_GetOptionalAttrString() to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A1
|
||
+static inline int
|
||
+PyObject_GetOptionalAttr(PyObject *obj, PyObject *attr_name, PyObject **result)
|
||
+{
|
||
+ // bpo-32571 added _PyObject_LookupAttr() to Python 3.7.0b1
|
||
+#if PY_VERSION_HEX >= 0x030700B1 && !defined(PYPY_VERSION)
|
||
+ return _PyObject_LookupAttr(obj, attr_name, result);
|
||
+#else
|
||
+ *result = PyObject_GetAttr(obj, attr_name);
|
||
+ if (*result != NULL) {
|
||
+ return 1;
|
||
+ }
|
||
+ if (!PyErr_Occurred()) {
|
||
+ return 0;
|
||
+ }
|
||
+ if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||
+ PyErr_Clear();
|
||
+ return 0;
|
||
+ }
|
||
+ return -1;
|
||
+#endif
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result)
|
||
+{
|
||
+ PyObject *name_obj;
|
||
+ int rc;
|
||
+#if PY_VERSION_HEX >= 0x03000000
|
||
+ name_obj = PyUnicode_FromString(attr_name);
|
||
+#else
|
||
+ name_obj = PyString_FromString(attr_name);
|
||
+#endif
|
||
+ if (name_obj == NULL) {
|
||
+ *result = NULL;
|
||
+ return -1;
|
||
+ }
|
||
+ rc = PyObject_GetOptionalAttr(obj, name_obj, result);
|
||
+ Py_DECREF(name_obj);
|
||
+ return rc;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-106307 added PyObject_GetOptionalAttr() and
|
||
+// PyMapping_GetOptionalItemString() to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A1
|
||
+static inline int
|
||
+PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result)
|
||
+{
|
||
+ *result = PyObject_GetItem(obj, key);
|
||
+ if (*result) {
|
||
+ return 1;
|
||
+ }
|
||
+ if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
|
||
+ return -1;
|
||
+ }
|
||
+ PyErr_Clear();
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result)
|
||
+{
|
||
+ PyObject *key_obj;
|
||
+ int rc;
|
||
+#if PY_VERSION_HEX >= 0x03000000
|
||
+ key_obj = PyUnicode_FromString(key);
|
||
+#else
|
||
+ key_obj = PyString_FromString(key);
|
||
+#endif
|
||
+ if (key_obj == NULL) {
|
||
+ *result = NULL;
|
||
+ return -1;
|
||
+ }
|
||
+ rc = PyMapping_GetOptionalItem(obj, key_obj, result);
|
||
+ Py_DECREF(key_obj);
|
||
+ return rc;
|
||
+}
|
||
+#endif
|
||
+
|
||
+// gh-108511 added PyMapping_HasKeyWithError() and
|
||
+// PyMapping_HasKeyStringWithError() to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A1
|
||
+static inline int
|
||
+PyMapping_HasKeyWithError(PyObject *obj, PyObject *key)
|
||
+{
|
||
+ PyObject *res;
|
||
+ int rc = PyMapping_GetOptionalItem(obj, key, &res);
|
||
+ Py_XDECREF(res);
|
||
+ return rc;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyMapping_HasKeyStringWithError(PyObject *obj, const char *key)
|
||
+{
|
||
+ PyObject *res;
|
||
+ int rc = PyMapping_GetOptionalItemString(obj, key, &res);
|
||
+ Py_XDECREF(res);
|
||
+ return rc;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-108511 added PyObject_HasAttrWithError() and
|
||
+// PyObject_HasAttrStringWithError() to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A1
|
||
+static inline int
|
||
+PyObject_HasAttrWithError(PyObject *obj, PyObject *attr)
|
||
+{
|
||
+ PyObject *res;
|
||
+ int rc = PyObject_GetOptionalAttr(obj, attr, &res);
|
||
+ Py_XDECREF(res);
|
||
+ return rc;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyObject_HasAttrStringWithError(PyObject *obj, const char *attr)
|
||
+{
|
||
+ PyObject *res;
|
||
+ int rc = PyObject_GetOptionalAttrString(obj, attr, &res);
|
||
+ Py_XDECREF(res);
|
||
+ return rc;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-106004 added PyDict_GetItemRef() and PyDict_GetItemStringRef()
|
||
+// to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A1
|
||
+static inline int
|
||
+PyDict_GetItemRef(PyObject *mp, PyObject *key, PyObject **result)
|
||
+{
|
||
+#if PY_VERSION_HEX >= 0x03000000
|
||
+ PyObject *item = PyDict_GetItemWithError(mp, key);
|
||
+#else
|
||
+ PyObject *item = _PyDict_GetItemWithError(mp, key);
|
||
+#endif
|
||
+ if (item != NULL) {
|
||
+ *result = Py_NewRef(item);
|
||
+ return 1; // found
|
||
+ }
|
||
+ if (!PyErr_Occurred()) {
|
||
+ *result = NULL;
|
||
+ return 0; // not found
|
||
+ }
|
||
+ *result = NULL;
|
||
+ return -1;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyDict_GetItemStringRef(PyObject *mp, const char *key, PyObject **result)
|
||
+{
|
||
+ int res;
|
||
+#if PY_VERSION_HEX >= 0x03000000
|
||
+ PyObject *key_obj = PyUnicode_FromString(key);
|
||
+#else
|
||
+ PyObject *key_obj = PyString_FromString(key);
|
||
+#endif
|
||
+ if (key_obj == NULL) {
|
||
+ *result = NULL;
|
||
+ return -1;
|
||
+ }
|
||
+ res = PyDict_GetItemRef(mp, key_obj, result);
|
||
+ Py_DECREF(key_obj);
|
||
+ return res;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-106307 added PyModule_Add() to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A1
|
||
+static inline int
|
||
+PyModule_Add(PyObject *mod, const char *name, PyObject *value)
|
||
+{
|
||
+ int res = PyModule_AddObjectRef(mod, name, value);
|
||
+ Py_XDECREF(value);
|
||
+ return res;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-108014 added Py_IsFinalizing() to Python 3.13.0a1
|
||
+// bpo-1856 added _Py_Finalizing to Python 3.2.1b1.
|
||
+// _Py_IsFinalizing() was added to PyPy 7.3.0.
|
||
+#if (0x030201B1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030D00A1) \
|
||
+ && (!defined(PYPY_VERSION_NUM) || PYPY_VERSION_NUM >= 0x7030000)
|
||
+static inline int Py_IsFinalizing(void)
|
||
+{
|
||
+#if PY_VERSION_HEX >= 0x030700A1
|
||
+ // _Py_IsFinalizing() was added to Python 3.7.0a1.
|
||
+ return _Py_IsFinalizing();
|
||
+#else
|
||
+ return (_Py_Finalizing != NULL);
|
||
+#endif
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-108323 added PyDict_ContainsString() to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A1
|
||
+static inline int PyDict_ContainsString(PyObject *op, const char *key)
|
||
+{
|
||
+ PyObject *key_obj = PyUnicode_FromString(key);
|
||
+ if (key_obj == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+ int res = PyDict_Contains(op, key_obj);
|
||
+ Py_DECREF(key_obj);
|
||
+ return res;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-108445 added PyLong_AsInt() to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A1
|
||
+static inline int PyLong_AsInt(PyObject *obj)
|
||
+{
|
||
+#ifdef PYPY_VERSION
|
||
+ long value = PyLong_AsLong(obj);
|
||
+ if (value == -1 && PyErr_Occurred()) {
|
||
+ return -1;
|
||
+ }
|
||
+ if (value < (long)INT_MIN || (long)INT_MAX < value) {
|
||
+ PyErr_SetString(PyExc_OverflowError,
|
||
+ "Python int too large to convert to C int");
|
||
+ return -1;
|
||
+ }
|
||
+ return (int)value;
|
||
+#else
|
||
+ return _PyLong_AsInt(obj);
|
||
+#endif
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-107073 added PyObject_VisitManagedDict() to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A1
|
||
+static inline int
|
||
+PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg)
|
||
+{
|
||
+ PyObject **dict = _PyObject_GetDictPtr(obj);
|
||
+ if (*dict == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+ Py_VISIT(*dict);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static inline void
|
||
+PyObject_ClearManagedDict(PyObject *obj)
|
||
+{
|
||
+ PyObject **dict = _PyObject_GetDictPtr(obj);
|
||
+ if (*dict == NULL) {
|
||
+ return;
|
||
+ }
|
||
+ Py_CLEAR(*dict);
|
||
+}
|
||
+#endif
|
||
+
|
||
+// gh-108867 added PyThreadState_GetUnchecked() to Python 3.13.0a1
|
||
+// Python 3.5.2 added _PyThreadState_UncheckedGet().
|
||
+#if PY_VERSION_HEX >= 0x03050200 && PY_VERSION_HEX < 0x030D00A1
|
||
+static inline PyThreadState*
|
||
+PyThreadState_GetUnchecked(void)
|
||
+{
|
||
+ return _PyThreadState_UncheckedGet();
|
||
+}
|
||
+#endif
|
||
+
|
||
+// gh-110289 added PyUnicode_EqualToUTF8() and PyUnicode_EqualToUTF8AndSize()
|
||
+// to Python 3.13.0a1
|
||
+#if PY_VERSION_HEX < 0x030D00A1
|
||
+static inline int
|
||
+PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t str_len)
|
||
+{
|
||
+ Py_ssize_t len;
|
||
+ const void *utf8;
|
||
+ PyObject *exc_type, *exc_value, *exc_tb;
|
||
+ int res;
|
||
+
|
||
+ // API cannot report errors so save/restore the exception
|
||
+ PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
|
||
+
|
||
+ // Python 3.3.0a1 added PyUnicode_AsUTF8AndSize()
|
||
+#if PY_VERSION_HEX >= 0x030300A1
|
||
+ if (PyUnicode_IS_ASCII(unicode)) {
|
||
+ utf8 = PyUnicode_DATA(unicode);
|
||
+ len = PyUnicode_GET_LENGTH(unicode);
|
||
+ }
|
||
+ else {
|
||
+ utf8 = PyUnicode_AsUTF8AndSize(unicode, &len);
|
||
+ if (utf8 == NULL) {
|
||
+ // Memory allocation failure. The API cannot report error,
|
||
+ // so ignore the exception and return 0.
|
||
+ res = 0;
|
||
+ goto done;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (len != str_len) {
|
||
+ res = 0;
|
||
+ goto done;
|
||
+ }
|
||
+ res = (memcmp(utf8, str, (size_t)len) == 0);
|
||
+#else
|
||
+ PyObject *bytes = PyUnicode_AsUTF8String(unicode);
|
||
+ if (bytes == NULL) {
|
||
+ // Memory allocation failure. The API cannot report error,
|
||
+ // so ignore the exception and return 0.
|
||
+ res = 0;
|
||
+ goto done;
|
||
+ }
|
||
+
|
||
+#if PY_VERSION_HEX >= 0x03000000
|
||
+ len = PyBytes_GET_SIZE(bytes);
|
||
+ utf8 = PyBytes_AS_STRING(bytes);
|
||
+#else
|
||
+ len = PyString_GET_SIZE(bytes);
|
||
+ utf8 = PyString_AS_STRING(bytes);
|
||
+#endif
|
||
+ if (len != str_len) {
|
||
+ Py_DECREF(bytes);
|
||
+ res = 0;
|
||
+ goto done;
|
||
+ }
|
||
+
|
||
+ res = (memcmp(utf8, str, (size_t)len) == 0);
|
||
+ Py_DECREF(bytes);
|
||
+#endif
|
||
+
|
||
+done:
|
||
+ PyErr_Restore(exc_type, exc_value, exc_tb);
|
||
+ return res;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyUnicode_EqualToUTF8(PyObject *unicode, const char *str)
|
||
+{
|
||
+ return PyUnicode_EqualToUTF8AndSize(unicode, str, (Py_ssize_t)strlen(str));
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-111138 added PyList_Extend() and PyList_Clear() to Python 3.13.0a2
|
||
+#if PY_VERSION_HEX < 0x030D00A2
|
||
+static inline int
|
||
+PyList_Extend(PyObject *list, PyObject *iterable)
|
||
+{
|
||
+ return PyList_SetSlice(list, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, iterable);
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyList_Clear(PyObject *list)
|
||
+{
|
||
+ return PyList_SetSlice(list, 0, PY_SSIZE_T_MAX, NULL);
|
||
+}
|
||
+#endif
|
||
+
|
||
+// gh-111262 added PyDict_Pop() and PyDict_PopString() to Python 3.13.0a2
|
||
+#if PY_VERSION_HEX < 0x030D00A2
|
||
+static inline int
|
||
+PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result)
|
||
+{
|
||
+ PyObject *value;
|
||
+
|
||
+ if (!PyDict_Check(dict)) {
|
||
+ PyErr_BadInternalCall();
|
||
+ if (result) {
|
||
+ *result = NULL;
|
||
+ }
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ // bpo-16991 added _PyDict_Pop() to Python 3.5.0b2.
|
||
+ // Python 3.6.0b3 changed _PyDict_Pop() first argument type to PyObject*.
|
||
+ // Python 3.13.0a1 removed _PyDict_Pop().
|
||
+#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030500b2 || PY_VERSION_HEX >= 0x030D0000
|
||
+ value = PyObject_CallMethod(dict, "pop", "O", key);
|
||
+#elif PY_VERSION_HEX < 0x030600b3
|
||
+ value = _PyDict_Pop(_Py_CAST(PyDictObject*, dict), key, NULL);
|
||
+#else
|
||
+ value = _PyDict_Pop(dict, key, NULL);
|
||
+#endif
|
||
+ if (value == NULL) {
|
||
+ if (result) {
|
||
+ *result = NULL;
|
||
+ }
|
||
+ if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_KeyError)) {
|
||
+ return -1;
|
||
+ }
|
||
+ PyErr_Clear();
|
||
+ return 0;
|
||
+ }
|
||
+ if (result) {
|
||
+ *result = value;
|
||
+ }
|
||
+ else {
|
||
+ Py_DECREF(value);
|
||
+ }
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyDict_PopString(PyObject *dict, const char *key, PyObject **result)
|
||
+{
|
||
+ PyObject *key_obj = PyUnicode_FromString(key);
|
||
+ if (key_obj == NULL) {
|
||
+ if (result != NULL) {
|
||
+ *result = NULL;
|
||
+ }
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ int res = PyDict_Pop(dict, key_obj, result);
|
||
+ Py_DECREF(key_obj);
|
||
+ return res;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+#if PY_VERSION_HEX < 0x030200A4
|
||
+// Python 3.2.0a4 added Py_hash_t type
|
||
+typedef Py_ssize_t Py_hash_t;
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-111545 added Py_HashPointer() to Python 3.13.0a3
|
||
+#if PY_VERSION_HEX < 0x030D00A3
|
||
+static inline Py_hash_t Py_HashPointer(const void *ptr)
|
||
+{
|
||
+#if PY_VERSION_HEX >= 0x030900A4 && !defined(PYPY_VERSION)
|
||
+ return _Py_HashPointer(ptr);
|
||
+#else
|
||
+ return _Py_HashPointer(_Py_CAST(void*, ptr));
|
||
+#endif
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// Python 3.13a4 added a PyTime API.
|
||
+// Use the private API added to Python 3.5.
|
||
+#if PY_VERSION_HEX < 0x030D00A4 && PY_VERSION_HEX >= 0x03050000
|
||
+typedef _PyTime_t PyTime_t;
|
||
+#define PyTime_MIN _PyTime_MIN
|
||
+#define PyTime_MAX _PyTime_MAX
|
||
+
|
||
+static inline double PyTime_AsSecondsDouble(PyTime_t t)
|
||
+{ return _PyTime_AsSecondsDouble(t); }
|
||
+
|
||
+static inline int PyTime_Monotonic(PyTime_t *result)
|
||
+{ return _PyTime_GetMonotonicClockWithInfo(result, NULL); }
|
||
+
|
||
+static inline int PyTime_Time(PyTime_t *result)
|
||
+{ return _PyTime_GetSystemClockWithInfo(result, NULL); }
|
||
+
|
||
+static inline int PyTime_PerfCounter(PyTime_t *result)
|
||
+{
|
||
+#if PY_VERSION_HEX >= 0x03070000 && !defined(PYPY_VERSION)
|
||
+ return _PyTime_GetPerfCounterWithInfo(result, NULL);
|
||
+#elif PY_VERSION_HEX >= 0x03070000
|
||
+ // Call time.perf_counter_ns() and convert Python int object to PyTime_t.
|
||
+ // Cache time.perf_counter_ns() function for best performance.
|
||
+ static PyObject *func = NULL;
|
||
+ if (func == NULL) {
|
||
+ PyObject *mod = PyImport_ImportModule("time");
|
||
+ if (mod == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ func = PyObject_GetAttrString(mod, "perf_counter_ns");
|
||
+ Py_DECREF(mod);
|
||
+ if (func == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ PyObject *res = PyObject_CallNoArgs(func);
|
||
+ if (res == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+ long long value = PyLong_AsLongLong(res);
|
||
+ Py_DECREF(res);
|
||
+
|
||
+ if (value == -1 && PyErr_Occurred()) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ Py_BUILD_ASSERT(sizeof(value) >= sizeof(PyTime_t));
|
||
+ *result = (PyTime_t)value;
|
||
+ return 0;
|
||
+#else
|
||
+ // Call time.perf_counter() and convert C double to PyTime_t.
|
||
+ // Cache time.perf_counter() function for best performance.
|
||
+ static PyObject *func = NULL;
|
||
+ if (func == NULL) {
|
||
+ PyObject *mod = PyImport_ImportModule("time");
|
||
+ if (mod == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ func = PyObject_GetAttrString(mod, "perf_counter");
|
||
+ Py_DECREF(mod);
|
||
+ if (func == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ PyObject *res = PyObject_CallNoArgs(func);
|
||
+ if (res == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+ double d = PyFloat_AsDouble(res);
|
||
+ Py_DECREF(res);
|
||
+
|
||
+ if (d == -1.0 && PyErr_Occurred()) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ // Avoid floor() to avoid having to link to libm
|
||
+ *result = (PyTime_t)(d * 1e9);
|
||
+ return 0;
|
||
+#endif
|
||
+}
|
||
+
|
||
+#endif
|
||
+
|
||
+// gh-111389 added hash constants to Python 3.13.0a5. These constants were
|
||
+// added first as private macros to Python 3.4.0b1 and PyPy 7.3.9.
|
||
+#if (!defined(PyHASH_BITS) \
|
||
+ && ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \
|
||
+ || (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \
|
||
+ && PYPY_VERSION_NUM >= 0x07090000)))
|
||
+# define PyHASH_BITS _PyHASH_BITS
|
||
+# define PyHASH_MODULUS _PyHASH_MODULUS
|
||
+# define PyHASH_INF _PyHASH_INF
|
||
+# define PyHASH_IMAG _PyHASH_IMAG
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-111545 added Py_GetConstant() and Py_GetConstantBorrowed()
|
||
+// to Python 3.13.0a6
|
||
+#if PY_VERSION_HEX < 0x030D00A6 && !defined(Py_CONSTANT_NONE)
|
||
+
|
||
+#define Py_CONSTANT_NONE 0
|
||
+#define Py_CONSTANT_FALSE 1
|
||
+#define Py_CONSTANT_TRUE 2
|
||
+#define Py_CONSTANT_ELLIPSIS 3
|
||
+#define Py_CONSTANT_NOT_IMPLEMENTED 4
|
||
+#define Py_CONSTANT_ZERO 5
|
||
+#define Py_CONSTANT_ONE 6
|
||
+#define Py_CONSTANT_EMPTY_STR 7
|
||
+#define Py_CONSTANT_EMPTY_BYTES 8
|
||
+#define Py_CONSTANT_EMPTY_TUPLE 9
|
||
+
|
||
+static inline PyObject* Py_GetConstant(unsigned int constant_id)
|
||
+{
|
||
+ static PyObject* constants[Py_CONSTANT_EMPTY_TUPLE + 1] = {NULL};
|
||
+
|
||
+ if (constants[Py_CONSTANT_NONE] == NULL) {
|
||
+ constants[Py_CONSTANT_NONE] = Py_None;
|
||
+ constants[Py_CONSTANT_FALSE] = Py_False;
|
||
+ constants[Py_CONSTANT_TRUE] = Py_True;
|
||
+ constants[Py_CONSTANT_ELLIPSIS] = Py_Ellipsis;
|
||
+ constants[Py_CONSTANT_NOT_IMPLEMENTED] = Py_NotImplemented;
|
||
+
|
||
+ constants[Py_CONSTANT_ZERO] = PyLong_FromLong(0);
|
||
+ if (constants[Py_CONSTANT_ZERO] == NULL) {
|
||
+ goto fatal_error;
|
||
+ }
|
||
+
|
||
+ constants[Py_CONSTANT_ONE] = PyLong_FromLong(1);
|
||
+ if (constants[Py_CONSTANT_ONE] == NULL) {
|
||
+ goto fatal_error;
|
||
+ }
|
||
+
|
||
+ constants[Py_CONSTANT_EMPTY_STR] = PyUnicode_FromStringAndSize("", 0);
|
||
+ if (constants[Py_CONSTANT_EMPTY_STR] == NULL) {
|
||
+ goto fatal_error;
|
||
+ }
|
||
+
|
||
+ constants[Py_CONSTANT_EMPTY_BYTES] = PyBytes_FromStringAndSize("", 0);
|
||
+ if (constants[Py_CONSTANT_EMPTY_BYTES] == NULL) {
|
||
+ goto fatal_error;
|
||
+ }
|
||
+
|
||
+ constants[Py_CONSTANT_EMPTY_TUPLE] = PyTuple_New(0);
|
||
+ if (constants[Py_CONSTANT_EMPTY_TUPLE] == NULL) {
|
||
+ goto fatal_error;
|
||
+ }
|
||
+ // goto dance to avoid compiler warnings about Py_FatalError()
|
||
+ goto init_done;
|
||
+
|
||
+fatal_error:
|
||
+ // This case should never happen
|
||
+ Py_FatalError("Py_GetConstant() failed to get constants");
|
||
+ }
|
||
+
|
||
+init_done:
|
||
+ if (constant_id <= Py_CONSTANT_EMPTY_TUPLE) {
|
||
+ return Py_NewRef(constants[constant_id]);
|
||
+ }
|
||
+ else {
|
||
+ PyErr_BadInternalCall();
|
||
+ return NULL;
|
||
+ }
|
||
+}
|
||
+
|
||
+static inline PyObject* Py_GetConstantBorrowed(unsigned int constant_id)
|
||
+{
|
||
+ PyObject *obj = Py_GetConstant(constant_id);
|
||
+ Py_XDECREF(obj);
|
||
+ return obj;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-114329 added PyList_GetItemRef() to Python 3.13.0a4
|
||
+#if PY_VERSION_HEX < 0x030D00A4
|
||
+static inline PyObject *
|
||
+PyList_GetItemRef(PyObject *op, Py_ssize_t index)
|
||
+{
|
||
+ PyObject *item = PyList_GetItem(op, index);
|
||
+ Py_XINCREF(item);
|
||
+ return item;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-114329 added PyList_GetItemRef() to Python 3.13.0a4
|
||
+#if PY_VERSION_HEX < 0x030D00A4
|
||
+static inline int
|
||
+PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value,
|
||
+ PyObject **result)
|
||
+{
|
||
+ PyObject *value;
|
||
+ if (PyDict_GetItemRef(d, key, &value) < 0) {
|
||
+ // get error
|
||
+ if (result) {
|
||
+ *result = NULL;
|
||
+ }
|
||
+ return -1;
|
||
+ }
|
||
+ if (value != NULL) {
|
||
+ // present
|
||
+ if (result) {
|
||
+ *result = value;
|
||
+ }
|
||
+ else {
|
||
+ Py_DECREF(value);
|
||
+ }
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ // missing: set the item
|
||
+ if (PyDict_SetItem(d, key, default_value) < 0) {
|
||
+ // set error
|
||
+ if (result) {
|
||
+ *result = NULL;
|
||
+ }
|
||
+ return -1;
|
||
+ }
|
||
+ if (result) {
|
||
+ *result = Py_NewRef(default_value);
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+#endif
|
||
+
|
||
+#if PY_VERSION_HEX < 0x030D00B3
|
||
+# define Py_BEGIN_CRITICAL_SECTION(op) {
|
||
+# define Py_END_CRITICAL_SECTION() }
|
||
+# define Py_BEGIN_CRITICAL_SECTION2(a, b) {
|
||
+# define Py_END_CRITICAL_SECTION2() }
|
||
+#endif
|
||
+
|
||
+#if PY_VERSION_HEX < 0x030E0000 && PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION)
|
||
+typedef struct PyUnicodeWriter PyUnicodeWriter;
|
||
+
|
||
+static inline void PyUnicodeWriter_Discard(PyUnicodeWriter *writer)
|
||
+{
|
||
+ _PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer);
|
||
+ PyMem_Free(writer);
|
||
+}
|
||
+
|
||
+static inline PyUnicodeWriter* PyUnicodeWriter_Create(Py_ssize_t length)
|
||
+{
|
||
+ if (length < 0) {
|
||
+ PyErr_SetString(PyExc_ValueError,
|
||
+ "length must be positive");
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ const size_t size = sizeof(_PyUnicodeWriter);
|
||
+ PyUnicodeWriter *pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size);
|
||
+ if (pub_writer == _Py_NULL) {
|
||
+ PyErr_NoMemory();
|
||
+ return _Py_NULL;
|
||
+ }
|
||
+ _PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer;
|
||
+
|
||
+ _PyUnicodeWriter_Init(writer);
|
||
+ if (_PyUnicodeWriter_Prepare(writer, length, 127) < 0) {
|
||
+ PyUnicodeWriter_Discard(pub_writer);
|
||
+ return NULL;
|
||
+ }
|
||
+ writer->overallocate = 1;
|
||
+ return pub_writer;
|
||
+}
|
||
+
|
||
+static inline PyObject* PyUnicodeWriter_Finish(PyUnicodeWriter *writer)
|
||
+{
|
||
+ PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer);
|
||
+ assert(((_PyUnicodeWriter*)writer)->buffer == NULL);
|
||
+ PyMem_Free(writer);
|
||
+ return str;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch)
|
||
+{
|
||
+ if (ch > 0x10ffff) {
|
||
+ PyErr_SetString(PyExc_ValueError,
|
||
+ "character must be in range(0x110000)");
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch);
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj)
|
||
+{
|
||
+ PyObject *str = PyObject_Str(obj);
|
||
+ if (str == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
|
||
+ Py_DECREF(str);
|
||
+ return res;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj)
|
||
+{
|
||
+ PyObject *str = PyObject_Repr(obj);
|
||
+ if (str == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
|
||
+ Py_DECREF(str);
|
||
+ return res;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer,
|
||
+ const char *str, Py_ssize_t size)
|
||
+{
|
||
+ if (size < 0) {
|
||
+ size = (Py_ssize_t)strlen(str);
|
||
+ }
|
||
+
|
||
+ PyObject *str_obj = PyUnicode_FromStringAndSize(str, size);
|
||
+ if (str_obj == _Py_NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj);
|
||
+ Py_DECREF(str_obj);
|
||
+ return res;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer,
|
||
+ const wchar_t *str, Py_ssize_t size)
|
||
+{
|
||
+ if (size < 0) {
|
||
+ size = (Py_ssize_t)wcslen(str);
|
||
+ }
|
||
+
|
||
+ PyObject *str_obj = PyUnicode_FromWideChar(str, size);
|
||
+ if (str_obj == _Py_NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj);
|
||
+ Py_DECREF(str_obj);
|
||
+ return res;
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str,
|
||
+ Py_ssize_t start, Py_ssize_t end)
|
||
+{
|
||
+ if (!PyUnicode_Check(str)) {
|
||
+ PyErr_Format(PyExc_TypeError, "expect str, not %T", str);
|
||
+ return -1;
|
||
+ }
|
||
+ if (start < 0 || start > end) {
|
||
+ PyErr_Format(PyExc_ValueError, "invalid start argument");
|
||
+ return -1;
|
||
+ }
|
||
+ if (end > PyUnicode_GET_LENGTH(str)) {
|
||
+ PyErr_Format(PyExc_ValueError, "invalid end argument");
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str,
|
||
+ start, end);
|
||
+}
|
||
+
|
||
+static inline int
|
||
+PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...)
|
||
+{
|
||
+ va_list vargs;
|
||
+ va_start(vargs, format);
|
||
+ PyObject *str = PyUnicode_FromFormatV(format, vargs);
|
||
+ va_end(vargs);
|
||
+ if (str == _Py_NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
|
||
+ Py_DECREF(str);
|
||
+ return res;
|
||
+}
|
||
+#endif // PY_VERSION_HEX < 0x030E0000
|
||
+
|
||
+// gh-116560 added PyLong_GetSign() to Python 3.14.0a0
|
||
+#if PY_VERSION_HEX < 0x030E00A0
|
||
+static inline int PyLong_GetSign(PyObject *obj, int *sign)
|
||
+{
|
||
+ if (!PyLong_Check(obj)) {
|
||
+ PyErr_Format(PyExc_TypeError, "expect int, got %s", Py_TYPE(obj)->tp_name);
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ *sign = _PyLong_Sign(obj);
|
||
+ return 0;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-124502 added PyUnicode_Equal() to Python 3.14.0a0
|
||
+#if PY_VERSION_HEX < 0x030E00A0
|
||
+static inline int PyUnicode_Equal(PyObject *str1, PyObject *str2)
|
||
+{
|
||
+ if (!PyUnicode_Check(str1)) {
|
||
+ PyErr_Format(PyExc_TypeError, "first argument must be str, not %s",
|
||
+ Py_TYPE(str1)->tp_name);
|
||
+ return -1;
|
||
+ }
|
||
+ if (!PyUnicode_Check(str2)) {
|
||
+ PyErr_Format(PyExc_TypeError, "second argument must be str, not %s",
|
||
+ Py_TYPE(str2)->tp_name);
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+#if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION)
|
||
+ PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *str1, PyObject *str2);
|
||
+
|
||
+ return _PyUnicode_Equal(str1, str2);
|
||
+#elif PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION)
|
||
+ return _PyUnicode_EQ(str1, str2);
|
||
+#elif PY_VERSION_HEX >= 0x03090000 && defined(PYPY_VERSION)
|
||
+ return _PyUnicode_EQ(str1, str2);
|
||
+#else
|
||
+ return (PyUnicode_Compare(str1, str2) == 0);
|
||
+#endif
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+// gh-121645 added PyBytes_Join() to Python 3.14.0a0
|
||
+#if PY_VERSION_HEX < 0x030E00A0
|
||
+static inline PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable)
|
||
+{
|
||
+ return _PyBytes_Join(sep, iterable);
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+#if PY_VERSION_HEX < 0x030E00A0
|
||
+static inline Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len)
|
||
+{
|
||
+#if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
|
||
+ PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void *src, Py_ssize_t len);
|
||
+
|
||
+ return _Py_HashBytes(ptr, len);
|
||
+#else
|
||
+ Py_hash_t hash;
|
||
+ PyObject *bytes = PyBytes_FromStringAndSize((const char*)ptr, len);
|
||
+ if (bytes == NULL) {
|
||
+ return -1;
|
||
+ }
|
||
+ hash = PyObject_Hash(bytes);
|
||
+ Py_DECREF(bytes);
|
||
+ return hash;
|
||
+#endif
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+#if PY_VERSION_HEX < 0x030E00A0
|
||
+static inline int PyIter_NextItem(PyObject *iter, PyObject **item)
|
||
+{
|
||
+ iternextfunc tp_iternext;
|
||
+
|
||
+ assert(iter != NULL);
|
||
+ assert(item != NULL);
|
||
+
|
||
+ tp_iternext = Py_TYPE(iter)->tp_iternext;
|
||
+ if (tp_iternext == NULL) {
|
||
+ *item = NULL;
|
||
+ PyErr_Format(PyExc_TypeError, "expected an iterator, got '%s'",
|
||
+ Py_TYPE(iter)->tp_name);
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ if ((*item = tp_iternext(iter))) {
|
||
+ return 1;
|
||
+ }
|
||
+ if (!PyErr_Occurred()) {
|
||
+ return 0;
|
||
+ }
|
||
+ if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
|
||
+ PyErr_Clear();
|
||
+ return 0;
|
||
+ }
|
||
+ return -1;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+#if PY_VERSION_HEX < 0x030E00A0
|
||
+static inline PyObject* PyLong_FromInt32(int32_t value)
|
||
+{
|
||
+ Py_BUILD_ASSERT(sizeof(long) >= 4);
|
||
+ return PyLong_FromLong(value);
|
||
+}
|
||
+
|
||
+static inline PyObject* PyLong_FromInt64(int64_t value)
|
||
+{
|
||
+ Py_BUILD_ASSERT(sizeof(long long) >= 8);
|
||
+ return PyLong_FromLongLong(value);
|
||
+}
|
||
+
|
||
+static inline PyObject* PyLong_FromUInt32(uint32_t value)
|
||
+{
|
||
+ Py_BUILD_ASSERT(sizeof(unsigned long) >= 4);
|
||
+ return PyLong_FromUnsignedLong(value);
|
||
+}
|
||
+
|
||
+static inline PyObject* PyLong_FromUInt64(uint64_t value)
|
||
+{
|
||
+ Py_BUILD_ASSERT(sizeof(unsigned long long) >= 8);
|
||
+ return PyLong_FromUnsignedLongLong(value);
|
||
+}
|
||
+
|
||
+static inline int PyLong_AsInt32(PyObject *obj, int32_t *pvalue)
|
||
+{
|
||
+ Py_BUILD_ASSERT(sizeof(int) == 4);
|
||
+ int value = PyLong_AsInt(obj);
|
||
+ if (value == -1 && PyErr_Occurred()) {
|
||
+ return -1;
|
||
+ }
|
||
+ *pvalue = (int32_t)value;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static inline int PyLong_AsInt64(PyObject *obj, int64_t *pvalue)
|
||
+{
|
||
+ Py_BUILD_ASSERT(sizeof(long long) == 8);
|
||
+ long long value = PyLong_AsLongLong(obj);
|
||
+ if (value == -1 && PyErr_Occurred()) {
|
||
+ return -1;
|
||
+ }
|
||
+ *pvalue = (int64_t)value;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static inline int PyLong_AsUInt32(PyObject *obj, uint32_t *pvalue)
|
||
+{
|
||
+ Py_BUILD_ASSERT(sizeof(long) >= 4);
|
||
+ unsigned long value = PyLong_AsUnsignedLong(obj);
|
||
+ if (value == (unsigned long)-1 && PyErr_Occurred()) {
|
||
+ return -1;
|
||
+ }
|
||
+#if SIZEOF_LONG > 4
|
||
+ if ((unsigned long)UINT32_MAX < value) {
|
||
+ PyErr_SetString(PyExc_OverflowError,
|
||
+ "Python int too large to convert to C uint32_t");
|
||
+ return -1;
|
||
+ }
|
||
+#endif
|
||
+ *pvalue = (uint32_t)value;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static inline int PyLong_AsUInt64(PyObject *obj, uint64_t *pvalue)
|
||
+{
|
||
+ Py_BUILD_ASSERT(sizeof(long long) == 8);
|
||
+ unsigned long long value = PyLong_AsUnsignedLongLong(obj);
|
||
+ if (value == (unsigned long long)-1 && PyErr_Occurred()) {
|
||
+ return -1;
|
||
+ }
|
||
+ *pvalue = (uint64_t)value;
|
||
+ return 0;
|
||
+}
|
||
+#endif
|
||
+
|
||
+
|
||
+#ifdef __cplusplus
|
||
+}
|
||
+#endif
|
||
+#endif // PYTHONCAPI_COMPAT
|