summaryrefslogtreecommitdiff
path: root/coverage/tracer.c
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2011-08-08 20:37:38 -0400
committerNed Batchelder <ned@nedbatchelder.com>2011-08-08 20:37:38 -0400
commit829215d157dca64cd1d88be27908e73a084715a7 (patch)
tree4ea73ce6678a4ebd4be47e23ee58ae4603bedd70 /coverage/tracer.c
parentcbf42dc7273bfb828c8124c7b7229be15c15b202 (diff)
downloadpython-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.c33
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 *