diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2010-08-26 08:12:29 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2010-08-26 08:12:29 -0400 |
commit | a7881d330129a3f80ba5f4bffc9c069020e22731 (patch) | |
tree | 8448b8d4eb9a36f7f92fc037cfc95c06e35f43a2 /coverage/tracer.c | |
parent | 9726ca6bbdc7d1ed5b0f732071210eed4ceada34 (diff) | |
download | python-coveragepy-git-a7881d330129a3f80ba5f4bffc9c069020e22731.tar.gz |
The thread-startup dance caused Thread.run() to not be measured. This fixes it, I hope without introducing too much more new code. Fixes #85.
Diffstat (limited to 'coverage/tracer.c')
-rw-r--r-- | coverage/tracer.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/coverage/tracer.c b/coverage/tracer.c index 1d227295..583ed80e 100644 --- a/coverage/tracer.c +++ b/coverage/tracer.c @@ -25,14 +25,16 @@ #if PY_MAJOR_VERSION >= 3
+#define MyText_Type PyUnicode_Type
#define MyText_Check(o) PyUnicode_Check(o)
-#define MyText_AS_STRING(o) FOOEY_DONT_KNOW_YET(o)
+#define MyText_AS_STRING(o) PyBytes_AS_STRING(PyUnicode_AsASCIIString(o))
#define MyInt_FromLong(l) PyLong_FromLong(l)
#define MyType_HEAD_INIT PyVarObject_HEAD_INIT(NULL, 0)
#else
+#define MyText_Type PyString_Type
#define MyText_Check(o) PyString_Check(o)
#define MyText_AS_STRING(o) PyString_AS_STRING(o)
#define MyInt_FromLong(l) PyInt_FromLong(l)
@@ -117,7 +119,7 @@ typedef struct { #define STACK_DELTA 100
static int
-Tracer_init(Tracer *self, PyObject *args, PyObject *kwds)
+Tracer_init(Tracer *self, PyObject *args_unused, PyObject *kwds_unused)
{
#if COLLECT_STATS
self->stats.calls = 0;
@@ -247,7 +249,7 @@ Tracer_record_pair(Tracer *self, int l1, int l2) * The Trace Function
*/
static int
-Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg)
+Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg_unused)
{
int ret = RET_OK;
PyObject * filename = NULL;
@@ -449,19 +451,58 @@ Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg) return RET_OK;
}
+/*
+ * A sys.settrace-compatible function that invokes our C trace function.
+ */
static PyObject *
-Tracer_start(Tracer *self, PyObject *args)
+Tracer_pytrace(Tracer *self, PyObject *args)
+{
+ PyFrameObject *frame;
+ PyObject *what_str;
+ PyObject *arg_unused;
+ int what;
+ static char *what_names[] = {
+ "call", "exception", "line", "return",
+ "c_call", "c_exception", "c_return",
+ NULL
+ };
+
+ if (!PyArg_ParseTuple(args, "O!O!O:Tracer_pytrace",
+ &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg_unused)) {
+ goto done;
+ }
+
+ /* In Python, the what argument is a string, we need to find an int
+ for the C function. */
+ for (what = 0; what_names[what]; what++) {
+ if (!strcmp(MyText_AS_STRING(what_str), what_names[what])) {
+ break;
+ }
+ }
+
+ /* Invoke the C function, and return ourselves. */
+ if (Tracer_trace(self, frame, what, arg_unused) == RET_OK) {
+ return PyObject_GetAttrString((PyObject*)self, "pytrace");
+ }
+
+done:
+ return NULL;
+}
+
+static PyObject *
+Tracer_start(Tracer *self, PyObject *args_unused)
{
PyEval_SetTrace((Py_tracefunc)Tracer_trace, (PyObject*)self);
self->started = 1;
self->tracing_arcs = self->arcs && PyObject_IsTrue(self->arcs);
self->last_line = -1;
- return Py_BuildValue("");
+ /* start() returns a trace function usable with sys.settrace() */
+ return PyObject_GetAttrString((PyObject*)self, "pytrace");
}
static PyObject *
-Tracer_stop(Tracer *self, PyObject *args)
+Tracer_stop(Tracer *self, PyObject *args_unused)
{
if (self->started) {
PyEval_SetTrace(NULL, NULL);
@@ -512,6 +553,9 @@ Tracer_members[] = { static PyMethodDef
Tracer_methods[] = {
+ { "pytrace", (PyCFunction) Tracer_pytrace, METH_VARARGS,
+ PyDoc_STR("A trace function compatible with sys.settrace()") },
+
{ "start", (PyCFunction) Tracer_start, METH_VARARGS,
PyDoc_STR("Start the tracer") },
|