Skip to content

Commit

Permalink
Python3.12: Added support for "sys._getframemodulename"
Browse files Browse the repository at this point in the history
* We need to monkey patch it though, or else compiled frames are rejected.
  • Loading branch information
kayhayen committed May 15, 2024
1 parent 3cd5478 commit 139d9d6
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 23 deletions.
12 changes: 11 additions & 1 deletion nuitka/build/include/nuitka/compiled_frame.h
Expand Up @@ -90,11 +90,21 @@ NUITKA_MAY_BE_UNUSED static inline bool isFakeCodeObject(PyCodeObject *code) {

extern PyTypeObject Nuitka_Frame_Type;

static inline bool Nuitka_Frame_Check(PyObject *object) {
static inline bool Nuitka_Frame_CheckExact(PyObject *object) {
CHECK_OBJECT(object);
return Py_TYPE(object) == &Nuitka_Frame_Type;
}

static inline bool Nuitka_Frame_Check(PyObject *object) {
CHECK_OBJECT(object);

if (Nuitka_Frame_CheckExact(object)) {
return true;
}

return strcmp(Py_TYPE(object)->tp_name, "compiled_frame") == 0;
}

struct Nuitka_FrameObject {
PyFrameObject m_frame;

Expand Down
50 changes: 28 additions & 22 deletions nuitka/build/static_src/CompiledFrameType.c
Expand Up @@ -37,7 +37,7 @@ static PyMemberDef Nuitka_Frame_memberlist[] = {
#if PYTHON_VERSION < 0x300

static PyObject *Nuitka_Frame_get_exc_traceback(struct Nuitka_FrameObject *frame) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -52,7 +52,7 @@ static PyObject *Nuitka_Frame_get_exc_traceback(struct Nuitka_FrameObject *frame
}

static int Nuitka_Frame_set_exc_traceback(struct Nuitka_FrameObject *frame, PyObject *traceback) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -69,7 +69,7 @@ static int Nuitka_Frame_set_exc_traceback(struct Nuitka_FrameObject *frame, PyOb
}

static PyObject *Nuitka_Frame_get_exc_type(struct Nuitka_FrameObject *frame) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -86,7 +86,7 @@ static PyObject *Nuitka_Frame_get_exc_type(struct Nuitka_FrameObject *frame) {
}

static int Nuitka_Frame_set_exc_type(struct Nuitka_FrameObject *frame, PyObject *exception_type) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -105,7 +105,7 @@ static int Nuitka_Frame_set_exc_type(struct Nuitka_FrameObject *frame, PyObject
}

static PyObject *Nuitka_Frame_get_exc_value(struct Nuitka_FrameObject *frame) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -122,7 +122,7 @@ static PyObject *Nuitka_Frame_get_exc_value(struct Nuitka_FrameObject *frame) {
}

static int Nuitka_Frame_set_exc_value(struct Nuitka_FrameObject *frame, PyObject *exception_value) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -140,7 +140,7 @@ static int Nuitka_Frame_set_exc_value(struct Nuitka_FrameObject *frame, PyObject
}

static PyObject *Nuitka_Frame_get_restricted(struct Nuitka_FrameObject *frame, void *closure) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -151,7 +151,7 @@ static PyObject *Nuitka_Frame_get_restricted(struct Nuitka_FrameObject *frame, v
#endif

static PyObject *Nuitka_Frame_getlocals(struct Nuitka_FrameObject *nuitka_frame, void *closure) {
assert(Nuitka_Frame_Check((PyObject *)nuitka_frame));
assert(Nuitka_Frame_CheckExact((PyObject *)nuitka_frame));
CHECK_OBJECT((PyObject *)nuitka_frame);
assert(_PyObject_GC_IS_TRACKED(nuitka_frame));

Expand Down Expand Up @@ -236,15 +236,15 @@ static PyObject *Nuitka_Frame_getlocals(struct Nuitka_FrameObject *nuitka_frame,
}

static PyObject *Nuitka_Frame_getlineno(struct Nuitka_FrameObject *frame, void *closure) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

return PyInt_FromLong(frame->m_frame.f_lineno);
}

static PyObject *Nuitka_Frame_gettrace(struct Nuitka_FrameObject *frame, void *closure) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -254,7 +254,7 @@ static PyObject *Nuitka_Frame_gettrace(struct Nuitka_FrameObject *frame, void *c
}

static int Nuitka_Frame_settrace(struct Nuitka_FrameObject *frame, PyObject *v, void *closure) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -266,7 +266,7 @@ static int Nuitka_Frame_settrace(struct Nuitka_FrameObject *frame, PyObject *v,

#if PYTHON_VERSION >= 0x370
static PyObject *Nuitka_Frame_gettracelines(struct Nuitka_FrameObject *frame, void *closure) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -276,7 +276,7 @@ static PyObject *Nuitka_Frame_gettracelines(struct Nuitka_FrameObject *frame, vo
}

static int Nuitka_Frame_settracelines(struct Nuitka_FrameObject *frame, PyObject *v, void *closure) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -287,7 +287,7 @@ static int Nuitka_Frame_settracelines(struct Nuitka_FrameObject *frame, PyObject
}

static PyObject *Nuitka_Frame_gettraceopcodes(struct Nuitka_FrameObject *frame, void *closure) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -297,7 +297,7 @@ static PyObject *Nuitka_Frame_gettraceopcodes(struct Nuitka_FrameObject *frame,
}

static int Nuitka_Frame_settraceopcodes(struct Nuitka_FrameObject *frame, PyObject *v, void *closure) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -310,7 +310,7 @@ static int Nuitka_Frame_settraceopcodes(struct Nuitka_FrameObject *frame, PyObje

#if PYTHON_VERSION >= 0x3b0
static PyObject *Nuitka_Frame_getback(struct Nuitka_FrameObject *frame, void *closure) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand Down Expand Up @@ -339,7 +339,7 @@ static PyGetSetDef Nuitka_Frame_getsetlist[] = {

// tp_repr slot, decide how a function shall be output
static PyObject *Nuitka_Frame_tp_repr(struct Nuitka_FrameObject *nuitka_frame) {
assert(Nuitka_Frame_Check((PyObject *)nuitka_frame));
assert(Nuitka_Frame_CheckExact((PyObject *)nuitka_frame));
CHECK_OBJECT((PyObject *)nuitka_frame);
assert(_PyObject_GC_IS_TRACKED(nuitka_frame));

Expand Down Expand Up @@ -471,7 +471,7 @@ static void Nuitka_Frame_tp_dealloc(struct Nuitka_FrameObject *nuitka_frame) {
}

static int Nuitka_Frame_tp_traverse(struct Nuitka_FrameObject *frame, visitproc visit, void *arg) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand Down Expand Up @@ -541,7 +541,7 @@ static int Nuitka_Frame_tp_traverse(struct Nuitka_FrameObject *frame, visitproc
#if PYTHON_VERSION >= 0x340

static PyObject *Nuitka_Frame_clear(struct Nuitka_FrameObject *frame) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand Down Expand Up @@ -623,7 +623,7 @@ static PyObject *Nuitka_Frame_clear(struct Nuitka_FrameObject *frame) {
#endif

static inline Py_ssize_t Nuitka_Frame_GetSize(struct Nuitka_FrameObject *frame) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand All @@ -635,7 +635,7 @@ static inline Py_ssize_t Nuitka_Frame_GetSize(struct Nuitka_FrameObject *frame)
}

static PyObject *Nuitka_Frame_sizeof(struct Nuitka_FrameObject *frame) {
assert(Nuitka_Frame_Check((PyObject *)frame));
assert(Nuitka_Frame_CheckExact((PyObject *)frame));
CHECK_OBJECT((PyObject *)frame);
assert(_PyObject_GC_IS_TRACKED(frame));

Expand Down Expand Up @@ -800,7 +800,13 @@ static struct Nuitka_FrameObject *_MAKE_COMPILED_FRAME(PyCodeObject *code, PyObj
result->m_interpreter_frame.frame_obj = &result->m_frame;
result->m_interpreter_frame.owner = 0;
result->m_interpreter_frame.prev_instr = _PyCode_CODE(code);
#if PYTHON_VERSION >= 0x3c0
result->m_interpreter_frame.f_funcobj = NULL;
#else
result->m_interpreter_frame.f_func = NULL;
#endif
result->m_frame.f_frame = &result->m_interpreter_frame;

#endif

Nuitka_GC_Track(result);
Expand Down Expand Up @@ -980,7 +986,7 @@ PyCodeObject *makeCodeObject(PyObject *filename, int line, int flags, PyObject *
}

void Nuitka_Frame_AttachLocals(struct Nuitka_FrameObject *frame_object, char const *type_description, ...) {
assert(Nuitka_Frame_Check((PyObject *)frame_object));
assert(Nuitka_Frame_CheckExact((PyObject *)frame_object));
CHECK_OBJECT((PyObject *)frame_object);
assert(_PyObject_GC_IS_TRACKED(frame_object));
assertFrameObject(frame_object);
Expand Down
74 changes: 74 additions & 0 deletions nuitka/build/static_src/InspectPatcher.c
Expand Up @@ -112,6 +112,70 @@ static PyMethodDef _method_def_types_coroutine_replacement = {"coroutine", (PyCF

#endif

#if PYTHON_VERSION >= 0x3c0

static char *kw_list_depth[] = {(char *)"depth", NULL};

static bool Nuitka_FrameIsCompiled(_PyInterpreterFrame *frame) {
return ((frame->frame_obj != NULL) && (Py_REFCNT(frame->frame_obj) > 0) &&
Nuitka_Frame_Check((PyObject *)frame->frame_obj));
}

static bool Nuitka_FrameIsIncomplete(_PyInterpreterFrame *frame) {
// Compiled frames are always complete.
if (Nuitka_FrameIsCompiled(frame)) {
return false;
}

bool r = _PyFrame_IsIncomplete(frame);

return r;
}

static PyObject *orig_sys_getframemodulename = NULL;

static PyObject *_sys_getframemodulename_replacement(PyObject *self, PyObject *args, PyObject *kwds) {
PyObject *depth_arg = NULL;

if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:_getframemodulename", kw_list_depth, &depth_arg)) {
return NULL;
}

PyObject *index_value = Nuitka_Number_IndexAsLong(depth_arg ? depth_arg : const_int_0);

if (unlikely(index_value == NULL)) {
return NULL;
}

Py_ssize_t depth_ssize = PyLong_AsSsize_t(index_value);

Py_DECREF(index_value);

PyThreadState *tstate = _PyThreadState_GET();

_PyInterpreterFrame *frame = tstate->cframe->current_frame;
while ((frame != NULL) && ((Nuitka_FrameIsIncomplete(frame)) || depth_ssize-- > 0)) {
frame = frame->previous;
}

if ((frame != NULL) && (Nuitka_FrameIsCompiled(frame))) {
PyObject *frame_globals = PyObject_GetAttrString((PyObject *)frame->frame_obj, "f_globals");

PyObject *result = LOOKUP_ATTRIBUTE(tstate, frame_globals, const_str_plain___name__);
Py_DECREF(frame_globals);

return result;
}

return CALL_FUNCTION_WITH_SINGLE_ARG(tstate, orig_sys_getframemodulename, depth_arg);
}

// spell-checker: ignore getframemodulename
static PyMethodDef _method_def_sys_getframemodulename_replacement = {
"getcoroutinestate", (PyCFunction)_sys_getframemodulename_replacement, METH_VARARGS | METH_KEYWORDS, NULL};

#endif

/* Replace inspect functions with ones that handle compiles types too. */
void patchInspectModule(PyThreadState *tstate) {
static bool is_done = false;
Expand Down Expand Up @@ -217,6 +281,16 @@ types._GeneratorWrapper = GeneratorWrapperEnhanced\

#endif

#endif

#if PYTHON_VERSION >= 0x3c0
orig_sys_getframemodulename = Nuitka_SysGetObject("_getframemodulename");

PyObject *sys_getframemodulename_replacement =
PyCFunction_New(&_method_def_sys_getframemodulename_replacement, NULL);
CHECK_OBJECT(sys_getframemodulename_replacement);

Nuitka_SysSetObject("_getframemodulename", sys_getframemodulename_replacement);
#endif

is_done = true;
Expand Down

0 comments on commit 139d9d6

Please sign in to comment.