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 c0041fb..8018c8e 100644
--- a/python-numba.spec
+++ b/python-numba.spec
@@ -56,7 +56,6 @@ ExclusiveArch: donotbuild
ExcludeArch: s390x ppc64 %ix86 %arm
%endif
%endif
-
Name: python-numba%{?psuffix}
Version: 0.60.0
Release: 0
@@ -69,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}