summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Driessen <vincent@datafox.nl>2010-08-04 10:03:05 +0200
committerVincent Driessen <vincent@datafox.nl>2010-08-04 10:03:05 +0200
commita380c9b99cc9b790b9daa62bbb996735d11bded3 (patch)
tree9bb2c99016d289f1fcfb0b881776ea828e926840
parent2c49fbe379788966ec813c383a15bc73afd13015 (diff)
downloadnose-machineout-a380c9b99cc9b790b9daa62bbb996735d11bded3.tar.bz2
nose-machineout-a380c9b99cc9b790b9daa62bbb996735d11bded3.tar.xz
nose-machineout-a380c9b99cc9b790b9daa62bbb996735d11bded3.zip
Changed the implementation of the stack frame selector.
The new logic is a bit more explicit on how the best stack frame is selected: the traceback is now fully walked, and for each frame a score is calculated that increases when certain conditions match. The best score wins.
-rw-r--r--machineout.py49
1 files changed, 35 insertions, 14 deletions
diff --git a/machineout.py b/machineout.py
index c5144ea..8a09689 100644
--- a/machineout.py
+++ b/machineout.py
@@ -41,23 +41,44 @@ class NoseMachineReadableOutput(Plugin):
41 self.stream = stream 41 self.stream = stream
42 return DummyStream() 42 return DummyStream()
43 43
44 def _calcScore(self, frame):
45 """Calculates a score for this stack frame, so that can be used as a
46 quality indicator to compare to other stack frames in selecting the
47 most developer-friendly one to show in one-line output.
48
49 """
50 fname, _, funname, _ = frame
51 score = 0
52
53 # Being in the project directory means it's one of our own files
54 if fname.startswith(self.basepath):
55 score += 4
56
57 # Being one of our tests means it's a better match
58 if os.path.basename(fname).find('test') >= 0:
59 score += 2
60
61 # The check for the `assert' prefix allows the user to extend
62 # unittest.TestCase with custom assert-methods, while
63 # machineout still returns the most useful error line number.
64 if not funname.startswith('assert'):
65 score += 1
66 return score
67
68 def _selectBestStackFrame(self, traceback):
69 best_score = 0
70 best = traceback[-1] # fallback value
71 for frame in traceback:
72 curr_score = self._calcScore(frame)
73 if curr_score > best_score:
74 best = frame
75 best_score = curr_score
76 return best
77
44 def add_formatted(self, etype, err): 78 def add_formatted(self, etype, err):
45 exctype, value, tb = err 79 exctype, value, tb = err
46 fulltb = traceback.extract_tb(tb) 80 fulltb = traceback.extract_tb(tb)
47 81 fname, lineno, funname, msg = self._selectBestStackFrame(fulltb)
48 fallback = fulltb[-1]
49 try:
50 while True:
51 fname, lineno, funname, msg = fulltb.pop()
52
53 # The check for the `assert' prefix allows the user to extend
54 # unittest.TestCase with custom assert-methods, while
55 # machineout still returns the most useful error line number.
56 if fname.startswith(self.basepath) \
57 and not funname.startswith('assert'):
58 break
59 except IndexError:
60 fname, lineno, funname, msg = fallback
61 82
62 lines = traceback.format_exception_only(exctype, value) 83 lines = traceback.format_exception_only(exctype, value)
63 lines = [line.strip('\n') for line in lines] 84 lines = [line.strip('\n') for line in lines]