Skip to content

Instantly share code, notes, and snippets.

@Elizaveta239
Created January 13, 2017 14:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Elizaveta239/a9774ea5c0f5f05416b84e1cb379edf9 to your computer and use it in GitHub Desktop.
Save Elizaveta239/a9774ea5c0f5f05416b84e1cb379edf9 to your computer and use it in GitHub Desktop.
cdef extern from *:
ctypedef void freefunc(void *)
ctypedef void PyObject
ctypedef struct PyCodeObject:
int co_argcount; # arguments, except *args */
int co_kwonlyargcount; # keyword only arguments */
int co_nlocals; # local variables */
int co_stacksize; # entries needed for evaluation stack */
int co_flags; # CO_..., see below */
int co_firstlineno; # first source line number */
PyObject *co_code; # instruction opcodes */
PyObject *co_consts; # list (constants used) */
PyObject *co_names; # list of strings (names used) */
PyObject *co_varnames; # tuple of strings (local variable names) */
PyObject *co_freevars; # tuple of strings (free variable names) */
PyObject *co_cellvars; # tuple of strings (cell variable names) */
unsigned char *co_cell2arg; # Maps cell vars which are arguments. */
PyObject *co_filename; # unicode (where it was loaded from) */
PyObject *co_name; # unicode (name, for reference) */
PyObject *co_lnotab; # string (encoding addr<->lineno mapping) See
# Objects/lnotab_notes.txt for details. */
void *co_zombieframe; # for optimization only (see frameobject.c) */
PyObject *co_weakreflist; # to support weakrefs to code objects */
void *co_extra;
cdef extern from "frameobject.h":
ctypedef struct PyFrameObject:
PyCodeObject *f_code # code segment
PyObject *f_builtins # builtin symbol table (PyDictObject)
PyObject *f_globals # global symbol table (PyDictObject) */
PyObject *f_locals # local symbol table (any mapping) */
PyObject **f_valuestack #
PyObject **f_stacktop
PyObject *f_trace # Trace function */
PyObject *f_exc_type
PyObject *f_exc_value
PyObject *f_exc_traceback
PyObject *f_gen;
int f_lasti; #/* Last instruction if called */
int f_lineno; #/* Current line number */
int f_iblock; #/* index in f_blockstack */
char f_executing; #/* whether the frame is still executing */
PyObject *f_localsplus[1];
cdef extern from "code.h":
int _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
int _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
cdef extern from "Python.h":
void PyObject_Free(void *ptr)
void PyObject_Del(PyObject *op)
void Py_INCREF(object o)
void Py_DECREF(object o)
object PyImport_ImportModule(char *name)
PyObject* PyObject_CallFunction(PyObject *callable, const char *format, ...)
object PyObject_GetAttrString(object o, char *attr_name)
cdef extern from "pystate.h":
ctypedef PyObject* _PyFrameEvalFunction(PyFrameObject *frame, int exc)
ctypedef struct PyInterpreterState:
PyInterpreterState *next
PyInterpreterState *tstate_head
PyObject *modules
PyObject *modules_by_index
PyObject *sysdict
PyObject *builtins
PyObject *importlib
PyObject *codec_search_path
PyObject *codec_search_cache
PyObject *codec_error_registry
int codecs_initialized
int fscodec_initialized
int dlopenflags
PyObject *builtins_copy
PyObject *import_func
# Initialized to PyEval_EvalFrameDefault().
_PyFrameEvalFunction eval_frame
ctypedef struct PyThreadState:
PyThreadState *prev
PyThreadState *next
PyInterpreterState *interp
# ...
PyThreadState *PyThreadState_Get()
cdef extern from "ceval.h":
int _PyEval_RequestCodeExtraIndex(freefunc);
PyFrameObject *PyEval_GetFrame()
PyObject* PyEval_CallFunction(PyObject *callable, const char *format, ...)
PyObject* _PyEval_EvalFrameDefault(PyFrameObject *frame, int exc)
import dis
from _pydevd_bundle.pydevd_comm import get_global_debugger
from _pydevd_frame_eval.pydevd_frame_tracing import pydev_trace_code_wrapper, update_globals_dict
from _pydevd_frame_eval.pydevd_modify_bytecode import insert_code
from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE
def get_breakpoints_for_file(filename):
main_debugger = get_global_debugger()
breakpoints_for_file = main_debugger.breakpoints.get(filename)
return breakpoints_for_file
cdef PyObject* get_bytecode_while_frame_eval(PyFrameObject *frame, int exc):
filepath = str(<object> frame.f_code.co_filename)
skip_file = False
breakpoints = None
cdef void** extra = NULL
for file in DONT_TRACE.keys():
if filepath.endswith(file):
skip_file = True
break
if not skip_file:
breakpoints = get_breakpoints_for_file(filepath)
_PyCode_GetExtra(<PyObject*> frame.f_code, 0, extra)
if extra is not NULL:
val = <object>(<PyObject*> extra)
print(val)
if breakpoints:
was_break = False
for offset, line in dis.findlinestarts(<object> frame.f_code):
if line in breakpoints:
was_break = True
new_code = insert_code(<object> frame.f_code, pydev_trace_code_wrapper.__code__, line)
Py_INCREF(new_code)
frame.f_code = <PyCodeObject *> new_code
if was_break:
dis.dis(new_code)
index = _PyEval_RequestCodeExtraIndex(PyObject_Free)
print(index)
_PyCode_SetExtra(<PyObject*> frame.f_code, index, <PyObject*> "mod")
update_globals_dict(<object> frame.f_globals)
return _PyEval_EvalFrameDefault(frame, exc)
def frame_eval_func():
cdef PyThreadState *state = PyThreadState_Get()
state.interp.eval_frame = get_bytecode_while_frame_eval
def stop_frame_eval():
cdef PyThreadState *state = PyThreadState_Get()
state.interp.eval_frame = _PyEval_EvalFrameDefault
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment