diff options
-rw-r--r-- | coverage/misc.py | 14 | ||||
-rw-r--r-- | coverage/parser.py | 4 |
2 files changed, 17 insertions, 1 deletions
diff --git a/coverage/misc.py b/coverage/misc.py index 8e4b3362..329a8417 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -45,6 +45,20 @@ def format_lines(statements, lines): return ret +def expensive(fn): + """A decorator to cache the result of an expensive operation. + + Only applies to methods with no arguments. + + """ + attr = "_cache_" + fn.__name__ + def _wrapped(self): + if not hasattr(self, attr): + setattr(self, attr, fn(self)) + return getattr(self, attr) + return _wrapped + + class CoverageException(Exception): """An exception specific to Coverage.""" pass diff --git a/coverage/parser.py b/coverage/parser.py index 9e0bd158..760e4e47 100644 --- a/coverage/parser.py +++ b/coverage/parser.py @@ -4,7 +4,7 @@ import glob, opcode, os, re, sys, token, tokenize from coverage.backward import set, sorted, StringIO # pylint: disable-msg=W0622 from coverage.bytecode import ByteCodes, CodeObjects -from coverage.misc import nice_pair, CoverageException, NoSource +from coverage.misc import nice_pair, CoverageException, NoSource, expensive class CodeParser(object): @@ -193,6 +193,7 @@ class CodeParser(object): if fl1 != fl2: all_arcs.append((fl1, fl2)) return sorted(all_arcs) + arcs = expensive(arcs) def exit_counts(self): """Get a mapping from line numbers to count of exits from that line. @@ -212,6 +213,7 @@ class CodeParser(object): exit_counts[l1] += 1 return exit_counts + exit_counts = expensive(exit_counts) ## Opcodes that guide the ByteParser. |