diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2011-04-27 09:49:23 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2011-04-27 09:49:23 -0400 |
commit | e91c97da931e54b27a838106d25d6ae5529256ae (patch) | |
tree | 352b9857bd6fbee4f6f07dfd80a85b8d5b286a3c /coverage/tracer.c | |
parent | f1d4dcbe9e5b8b8b335521f6aa806f8438fde917 (diff) | |
parent | a243a6a2b34eb9ef5cba3346796160e06ba77930 (diff) | |
download | python-coveragepy-git-e91c97da931e54b27a838106d25d6ae5529256ae.tar.gz |
Merge bug_123 work into default.
Diffstat (limited to 'coverage/tracer.c')
-rw-r--r-- | coverage/tracer.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/coverage/tracer.c b/coverage/tracer.c index e046596a..1017c9d4 100644 --- a/coverage/tracer.c +++ b/coverage/tracer.c @@ -365,6 +365,9 @@ Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg_unused) } } self->cur_file_data = file_data; + /* Make the frame right in case settrace(gettrace()) happens. */ + Py_INCREF(self); + frame->f_trace = (PyObject*)self; SHOWLOG(self->depth, frame->f_lineno, filename, "traced"); } else { @@ -462,7 +465,7 @@ Tracer_pytrace(Tracer *self, PyObject *args) { PyFrameObject *frame; PyObject *what_str; - PyObject *arg_unused; + PyObject *arg; int what; static char *what_names[] = { "call", "exception", "line", "return", @@ -470,8 +473,12 @@ Tracer_pytrace(Tracer *self, PyObject *args) NULL }; + #if WHAT_LOG + printf("pytrace\n"); + #endif + if (!PyArg_ParseTuple(args, "O!O!O:Tracer_pytrace", - &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg_unused)) { + &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg)) { goto done; } @@ -484,7 +491,7 @@ Tracer_pytrace(Tracer *self, PyObject *args) } /* Invoke the C function, and return ourselves. */ - if (Tracer_trace(self, frame, what, arg_unused) == RET_OK) { + if (Tracer_trace(self, frame, what, arg) == RET_OK) { return PyObject_GetAttrString((PyObject*)self, "pytrace"); } @@ -492,6 +499,24 @@ done: return NULL; } +/* + * Python has two ways to set the trace function: sys.settrace(fn), which + * takes a Python callable, and PyEval_SetTrace(func, obj), which takes + * a C function and a Python object. The way these work together is that + * sys.settrace(pyfn) calls PyEval_SetTrace(builtin_func, pyfn), using the + * Python callable as the object in PyEval_SetTrace. So sys.gettrace() + * simply returns the Python object used as the second argument to + * PyEval_SetTrace. So sys.gettrace() will return our self parameter, which + * means it must be callable to be used in sys.settrace(). + * + * So we make our self callable, equivalent to invoking our trace function. + */ +static PyObject * +Tracer_call(Tracer *self, PyObject *args, PyObject *kwds_unused) +{ + return Tracer_pytrace(self, args); +} + static PyObject * Tracer_start(Tracer *self, PyObject *args_unused) { @@ -590,7 +615,7 @@ TracerType = { 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ - 0, /*tp_call*/ + (ternaryfunc)Tracer_call, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ @@ -678,3 +703,4 @@ inittracer(void) } #endif /* Py3k */ + |