File py313.patch of Package python-numba

From 3e89582a41fc2712a0ce86528be98cf3dd768a23 Mon Sep 17 00:00:00 2001
From: Siu Kwan Lam <1929845+sklam@users.noreply.github.com>
Date: Tue, 16 Jan 2024 14:31:01 -0600
Subject: [PATCH 01/61] Minimal changes to get compiling

Added pythoncapi_compat.h from https://github.com/python/pythoncapi-compat
---
 numba/_devicearray.cpp             |    2 +-
 numba/_dispatcher.cpp              |    8 +-
 numba/_dynfunc.c                   |   12 +-
 numba/_helperlib.c                 |    4 +-
 numba/_pymodule.h                  |    4 +
 numba/_typeof.cpp                  |    8 +
 numba/core/runtime/_nrt_python.c   |    2 +-
 numba/experimental/jitclass/_box.c |    2 +-
 numba/mviewbuf.c                   |    2 +-
 numba/np/ufunc/_internal.c         |    4 +-
 numba/pythoncapi_compat.h          | 1114 ++++++++++++++++++++++++++++
 setup.py                           |    2 +-
 12 files changed, 1148 insertions(+), 16 deletions(-)
 create mode 100644 numba/pythoncapi_compat.h

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