Commits

desmaj committed ed348cb

refactorings to support programmatic use of the innards (better for testing)

  • Participants
  • Parent commits 534463f

Comments (0)

Files changed (6)

File instrumental/api.py

+import sys
+
+from instrumental.importer import ImportHook
+from instrumental.instrument import AnnotatorFactory
+from instrumental.monkey import monkeypatch_imp
+from instrumental.monkey import unmonkeypatch_imp
+from instrumental.recorder import ExecutionRecorder
+
+class Coverage(object):
+    
+    def __init__(self):
+        self.recorder = ExecutionRecorder.get()
+        self._import_hooks = []
+
+    def start(self, targets, ignores):
+        annotator_factory = AnnotatorFactory(self.recorder)
+        monkeypatch_imp(targets, ignores, annotator_factory)
+        for target in targets:
+            hook = ImportHook(target, ignores, annotator_factory)
+            self._import_hooks.append(hook)
+            sys.meta_path.append(hook)
+        self.recorder.start()
+        
+    def stop(self):
+        self.recorder.stop()
+        for hook in self._import_hooks:
+            sys.meta_path.remove(hook)
+        unmonkeypatch_imp()

File instrumental/monkey.py

 from instrumental.compat import exec_f
 
 _imp_load_module = imp.load_module
-def monkey_patch_imp(targets, ignores, visitor_factory):
+def monkeypatch_imp(targets, ignores, visitor_factory):
     imp.load_module = load_module_factory(targets, ignores, visitor_factory)
 
+def unmonkeypatch_imp():
+    imp.load_module = _imp_load_module
+
 def load_module_factory(targets, ignores, visitor_factory):
     def load_module(name, fh, pathname, description):
         if ((not any([re.match(target, name) for target in targets]))

File instrumental/recorder.py

         self._statements = {}
         self._branches = {}
         self.pragmas = {}
+        self.recording = False
+        
+    def start(self):
+        self.recording = True
+    
+    def stop(self):
+        self.recording = False
     
     def add_source(self, modulename, source):
         self._sources[modulename] = source
         return kall
     
     def record(self, arg, label, *args, **kwargs):
-        self._constructs[label].record(arg, *args, **kwargs)
+        if self.recording:
+            self._constructs[label].record(arg, *args, **kwargs)
         return arg
     
     def add_BoolOp(self, modulename, node, pragmas, parent):
         return kall_stmt
     
     def record_statement(self, modulename, lineno):
-        self._statements[modulename][lineno] = True
+        if self.recording:
+            self._statements[modulename][lineno] = True
     
     def add_statement(self, modulename, node):
         lines = self._statements.setdefault(modulename, {})

File instrumental/run.py

 from subprocess import Popen
 import sys
 
+from instrumental.api import Coverage
 from instrumental.compat import execfile
-from instrumental.importer import ImportHook
-from instrumental.instrument import AnnotatorFactory
-from instrumental.monkey import monkey_patch_imp
 from instrumental.recorder import ExecutionRecorder
 from instrumental.reporting import ExecutionReport
 
         sys.stdout.write("No targets specified. Use the '-t' option to specify packages to cover")
         sys.exit()
     
-    recorder = ExecutionRecorder.get()
-    annotator_factory = AnnotatorFactory(recorder)
-    monkey_patch_imp(opts.targets, opts.ignores, annotator_factory)
-    for target in opts.targets:
-        sys.meta_path.append(ImportHook(target, opts.ignores, annotator_factory))
+    coverage = Coverage()
+    coverage.start(opts.targets, opts.ignores)
     
     xml_filename = os.path.abspath('instrumental.xml')
     
                 opts.statements,
                 opts.xml,
                 opts.html]):
+            coverage.stop()
             sys.stdout.write("\n")
+            recorder = coverage.recorder
             report = ExecutionReport(here, recorder.constructs, recorder.statements, recorder.sources)
             if opts.summary:
                 sys.stdout.write(report.summary() + "\n")

File instrumental/test/test_condition_coverage.py

         # First clear out the recorder so that we'll create a new one
         ExecutionRecorder.reset()
         self.recorder = ExecutionRecorder.get()
+        self.recorder.start()
+    
+    def teardown(self):
+        self.recorder.stop()
     
     def _load_and_compile_module(self, module_func):
         module, source = load_module(module_func)

File instrumental/test/test_monkey.py

     def test_monkeypatch(self):
         import imp
         from instrumental.instrument import AnnotatorFactory
-        from instrumental.monkey import monkey_patch_imp
+        from instrumental.monkey import monkeypatch_imp
         
         original_load_module = imp.load_module
-        monkey_patch_imp([], [], AnnotatorFactory(None))
+        monkeypatch_imp([], [], AnnotatorFactory(None))
         assert original_load_module != imp.load_module
 
 class TestLoadModule(object):