From 4bd456a334bcf9679fe0f4e762d9c3a86915727d Mon Sep 17 00:00:00 2001
From: Joris Vink <joris@sanctorum.se>
Date: Fri, 8 Nov 2024 20:08:19 +0100
Subject: [PATCH] Support Python 3.13.

Since we're using some cpython internals that change from time to time
we have to adjust for the 3.13 release accordingly.
---
 src/python.c | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/python.c b/src/python.c
index 48506620..01c094e7 100644
--- a/src/python.c
+++ b/src/python.c
@@ -55,10 +55,33 @@
 
 #include <frameobject.h>
 
+/*
+ * Python 3.13.x requires that Py_BUILD_CORE is defined before we pull
+ * in the pycore_frame header file, and it loves using unnamed unions
+ * so we have to turn off pendatic mode before including it.
+ *
+ * The f_code member was removed from _PyInterpreterFrame and is replaced
+ * with a PyObject called f_executable. There is an _PyFrame_GetCode()
+ * helper function now.
+ */
+#if PY_VERSION_HEX >= 0x030d0000
+#define Py_BUILD_CORE			1
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored		"-Wpedantic"
+#endif
+
+#if PY_VERSION_HEX < 0x030d0000
+#define _PyFrame_GetCode(frame)		(frame->f_code)
+#endif
+
 #if PY_VERSION_HEX >= 0x030b0000
 #include <internal/pycore_frame.h>
 #endif
 
+#if PY_VERSION_HEX >= 0x030d0000
+#pragma GCC diagnostic pop
+#endif
+
 #if PY_VERSION_HEX < 0x030A0000
 typedef enum {
 	PYGEN_RETURN = 0,
@@ -1201,7 +1224,7 @@ python_resolve_frame_line(void *ptr)
 
 	frame = ptr;
 	addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
-	line = PyCode_Addr2Line(frame->f_code, addr);
+	line = PyCode_Addr2Line(_PyFrame_GetCode(frame), addr);
 #else
 	line = PyFrame_GetLineNumber(ptr);
 #endif
@@ -1232,8 +1255,8 @@ python_coro_trace(const char *label, struct python_coro *coro)
 #else
 	frame = obj->cr_frame;
 #endif
-	if (frame != NULL && frame->f_code != NULL) {
-		code = frame->f_code;
+	if (frame != NULL && _PyFrame_GetCode(frame) != NULL) {
+		code = _PyFrame_GetCode(frame);
 		func = PyUnicode_AsUTF8AndSize(code->co_name, NULL);
 		file = PyUnicode_AsUTF8AndSize(code->co_filename, NULL);
 
