diff options
author | Vincent Driessen <vincent@datafox.nl> | 2010-08-04 10:03:05 +0200 |
---|---|---|
committer | Vincent Driessen <vincent@datafox.nl> | 2010-08-04 10:03:05 +0200 |
commit | a380c9b99cc9b790b9daa62bbb996735d11bded3 (patch) | |
tree | 9bb2c99016d289f1fcfb0b881776ea828e926840 /machineout.py | |
parent | 2c49fbe379788966ec813c383a15bc73afd13015 (diff) | |
download | nose-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.
Diffstat (limited to 'machineout.py')
-rw-r--r-- | machineout.py | 49 |
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] |