From 2abad7d325180aa379eb4e08fcde9bf5712430547df6b83e8417b265f36bd35c Mon Sep 17 00:00:00 2001 From: Matej Cepl Date: Fri, 22 Nov 2024 11:22:11 +0000 Subject: [PATCH] - Add upstream py313.patch to support Python 3.13 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:numeric/python-numba?expand=0&rev=98 --- _multibuild | 1 + py313.patch | 4127 ++++++++++++++++++++++++++++++++++++++++++ python-numba.changes | 5 + python-numba.spec | 4 +- 4 files changed, 4135 insertions(+), 2 deletions(-) create mode 100644 py313.patch diff --git a/_multibuild b/_multibuild index 6d8cafe..cd365a1 100644 --- a/_multibuild +++ b/_multibuild @@ -2,4 +2,5 @@ test-py310 test-py311 test-py312 + test-py313 diff --git a/py313.patch b/py313.patch new file mode 100644 index 0000000..8ea9ce7 --- /dev/null +++ b/py313.patch @@ -0,0 +1,4127 @@ +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 + ++ ++// 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 + #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, '', 'exec')) +- return locals()['foo'] ++ dct = {} ++ exec(compile(funcstr, '', '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. "" seems ++ # to be something from multiprocessing. ++ lns = [] if path == "" 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 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 diff --git a/python-numba.changes b/python-numba.changes index 9395517..eadcd3f 100644 --- a/python-numba.changes +++ b/python-numba.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Nov 22 09:42:21 UTC 2024 - Markéta Machová + +- Add upstream py313.patch to support Python 3.13 + ------------------------------------------------------------------- Tue Oct 29 20:01:54 UTC 2024 - Dirk Müller diff --git a/python-numba.spec b/python-numba.spec index 36a3f7f..8018c8e 100644 --- a/python-numba.spec +++ b/python-numba.spec @@ -56,8 +56,6 @@ ExclusiveArch: donotbuild ExcludeArch: s390x ppc64 %ix86 %arm %endif %endif -# not supported with 0.60.0 -%global skip_python313 1 Name: python-numba%{?psuffix} Version: 0.60.0 Release: 0 @@ -70,6 +68,8 @@ Source: https://files.pythonhosted.org/packages/source/n/numba/numba-%{v Patch3: skip-failing-tests.patch # PATCH-FIX-UPSTREAM https://github.com/numba/numba/pull/9741 Add Support for NumPy 2.1 Patch4: numpy21.patch +# PATCH-FIX-UPSTREAM https://github.com/numba/numba/pull/9682 Python 3.13 support +Patch5: py313.patch BuildRequires: %{python_module devel >= 3.9} BuildRequires: %{python_module numpy-devel >= %{min_numpy_ver} with %python-numpy-devel < %{max_numpy_ver}} BuildRequires: %{python_module pip}