summaryrefslogtreecommitdiff
path: root/coverage
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2016-08-06 13:25:31 -0400
committerNed Batchelder <ned@nedbatchelder.com>2016-08-06 13:25:31 -0400
commita23ab8eb5b1d1522120970e1f72fbf629b4d77e2 (patch)
treee2da20d903d4069cafd0cadb1b182b7432889ae5 /coverage
parent90ecf09e3fc3f9c8950deba71fca699c7623edbf (diff)
downloadpython-coveragepy-git-a23ab8eb5b1d1522120970e1f72fbf629b4d77e2.tar.gz
Built-in support for using aspectlib to debug execution.
Diffstat (limited to 'coverage')
-rw-r--r--coverage/__init__.py4
-rw-r--r--coverage/debug.py47
2 files changed, 51 insertions, 0 deletions
diff --git a/coverage/__init__.py b/coverage/__init__.py
index 19223992..d9a13936 100644
--- a/coverage/__init__.py
+++ b/coverage/__init__.py
@@ -12,6 +12,7 @@ from coverage.version import __version__, __url__, version_info
from coverage.control import Coverage, process_startup
from coverage.data import CoverageData
+from coverage.debug import enable_aspectlib_maybe
from coverage.misc import CoverageException
from coverage.plugin import CoveragePlugin, FileTracer, FileReporter
from coverage.pytracer import PyTracer
@@ -19,6 +20,9 @@ from coverage.pytracer import PyTracer
# Backward compatibility.
coverage = Coverage
+# Possibly enable aspectlib to debug our execution.
+enable_aspectlib_maybe()
+
# On Windows, we encode and decode deep enough that something goes wrong and
# the encodings.utf_8 module is loaded and then unloaded, I don't know why.
# Adding a reference here prevents it from being unloaded. Yuk.
diff --git a/coverage/debug.py b/coverage/debug.py
index 8ed664ce..96e57920 100644
--- a/coverage/debug.py
+++ b/coverage/debug.py
@@ -5,6 +5,7 @@
import inspect
import os
+import re
import sys
from coverage.misc import isolate_module
@@ -112,3 +113,49 @@ def log(msg, stack=False): # pragma: debugging
f.write("{pid}: {msg}\n".format(pid=os.getpid(), msg=msg))
if stack:
dump_stack_frames(out=f)
+
+
+def enable_aspectlib_maybe():
+ """For debugging, we can use aspectlib to trace execution.
+
+ Define COVERAGE_ASPECTLIB to enable and configure aspectlib to trace
+ execution::
+
+ COVERAGE_ASPECTLIB=covaspect.txt:coverage.Coverage:coverage.data.CoverageData program...
+
+ This will trace all the public methods on Coverage and CoverageData,
+ writing the information to covaspect.txt.
+
+ """
+ aspects = os.environ.get("COVERAGE_ASPECTLIB", "")
+ if not aspects:
+ return
+
+ import aspectlib # pylint: disable=import-error
+ import aspectlib.debug # pylint: disable=import-error
+
+ class AspectlibOutputFile(object):
+ """A file-like object that includes pid and cwd information."""
+ def __init__(self, outfile):
+ self.outfile = outfile
+ self.cwd = None
+
+ def write(self, text):
+ """Just like file.write"""
+ cwd = os.getcwd()
+ if cwd != self.cwd:
+ self._write("cwd is now {0!r}\n".format(cwd))
+ self.cwd = cwd
+ self._write(text)
+
+ def _write(self, text):
+ """The raw text-writer, so that we can use it ourselves."""
+ self.outfile.write("{0:5d}: {1}".format(os.getpid(), text))
+
+ aspects = aspects.split(':')
+ aspects_file = AspectlibOutputFile(open(aspects[0], "a"))
+ aspect_log = aspectlib.debug.log(print_to=aspects_file, use_logging=False)
+ aspects = aspects[1:]
+ public_methods = re.compile(r'^(__init__|[a-zA-Z].*)$')
+ for aspect in aspects:
+ aspectlib.weave(aspect, aspect_log, methods=public_methods)