diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2011-08-08 20:37:38 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2011-08-08 20:37:38 -0400 |
commit | 829215d157dca64cd1d88be27908e73a084715a7 (patch) | |
tree | 4ea73ce6678a4ebd4be47e23ee58ae4603bedd70 /coverage/tracer.c | |
parent | cbf42dc7273bfb828c8124c7b7229be15c15b202 (diff) | |
download | python-coveragepy-git-829215d157dca64cd1d88be27908e73a084715a7.tar.gz |
A fullcoverage tracer that works. Events are stashed, then replayed when coverage is started.
Diffstat (limited to 'coverage/tracer.c')
-rw-r--r-- | coverage/tracer.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/coverage/tracer.c b/coverage/tracer.c index a7a4f418..e9fc56b4 100644 --- a/coverage/tracer.c +++ b/coverage/tracer.c @@ -468,14 +468,26 @@ Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg_unused) * means it must be callable to be used in sys.settrace(). * * So we make our self callable, equivalent to invoking our trace function. + * + * To help with the process of replaying stored frames, this function has an + * optional keyword argument: + * + * def Tracer_call(frame, event, arg, lineno=0) + * + * If provided, the lineno argument is used as the line number, and the + * frame's f_lineno member is ignored. */ static PyObject * -Tracer_call(Tracer *self, PyObject *args, PyObject *kwds_unused) +Tracer_call(Tracer *self, PyObject *args, PyObject *kwds) { PyFrameObject *frame; PyObject *what_str; PyObject *arg; + int lineno = 0; int what; + int orig_lineno; + PyObject *ret = NULL; + static char *what_names[] = { "call", "exception", "line", "return", "c_call", "c_exception", "c_return", @@ -486,8 +498,10 @@ Tracer_call(Tracer *self, PyObject *args, PyObject *kwds_unused) printf("pytrace\n"); #endif - if (!PyArg_ParseTuple(args, "O!O!O:Tracer_call", - &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg)) { + static char *kwlist[] = {"frame", "event", "arg", "lineno", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O|i:Tracer_call", kwlist, + &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg, &lineno)) { goto done; } @@ -499,14 +513,23 @@ Tracer_call(Tracer *self, PyObject *args, PyObject *kwds_unused) } } + /* Save off the frame's lineno, and use the forced one, if provided. */ + orig_lineno = frame->f_lineno; + if (lineno > 0) { + frame->f_lineno = lineno; + } + /* Invoke the C function, and return ourselves. */ if (Tracer_trace(self, frame, what, arg) == RET_OK) { Py_INCREF(self); - return (PyObject *)self; + ret = (PyObject *)self; } + /* Clean up. */ + frame->f_lineno = orig_lineno; + done: - return NULL; + return ret; } static PyObject * |