diff options
-rw-r--r-- | coverage/parser.py | 24 | ||||
-rw-r--r-- | tests/test_arcs.py | 18 |
2 files changed, 40 insertions, 2 deletions
diff --git a/coverage/parser.py b/coverage/parser.py index fb2cf955..4b920f10 100644 --- a/coverage/parser.py +++ b/coverage/parser.py @@ -341,8 +341,9 @@ class AstArcAnalyzer(object): handler = getattr(self, "handle_" + node_name, self.handle_default) return handler(node) - def add_body_arcs(self, body, from_line): - prev_lines = set([from_line]) + def add_body_arcs(self, body, from_line=None, prev_lines=None): + if prev_lines is None: + prev_lines = set([from_line]) for body_node in body: lineno = self.line_for_node(body_node) for prev_lineno in prev_lines: @@ -363,6 +364,7 @@ class AstArcAnalyzer(object): # TODO: listcomps hidden in lists: x = [[i for i in range(10)]] # TODO: multi-line listcomps # TODO: nested function definitions + # TODO: multiple `except` clauses def handle_Break(self, node): here = self.line_for_node(node) @@ -411,12 +413,30 @@ class AstArcAnalyzer(object): def handle_Module(self, node): raise Exception("TODO: this shouldn't happen") + def handle_Raise(self, node): + # `raise` statement jumps away, no exits from here. + return set([]) + def handle_Return(self, node): here = self.line_for_node(node) # TODO: what if self.function_start is None? self.arcs.add((here, -self.function_start)) return set([]) + def handle_Try(self, node): + start = self.line_for_node(node) + exits = self.add_body_arcs(node.body, from_line=start) + handler_exits = set() + for handler_node in node.handlers: + handler_start = self.line_for_node(handler_node) + # TODO: handler_node.name and handler_node.type + handler_exits |= self.add_body_arcs(handler_node.body, from_line=handler_start) + # TODO: node.orelse + # TODO: node.finalbody + if node.finalbody: + exits = self.add_body_arcs(node.finalbody, prev_lines=exits|handler_exits) + return exits + def handle_While(self, node): constant_test = self.is_constant_expr(node.test) start = to_top = self.line_for_node(node.test) diff --git a/tests/test_arcs.py b/tests/test_arcs.py index f136b755..04c0df6e 100644 --- a/tests/test_arcs.py +++ b/tests/test_arcs.py @@ -481,6 +481,7 @@ class ExceptionArcTest(CoverageTest): def test_break_in_finally(self): + # TODO: the name and the code don't seem to match self.check_coverage("""\ a, c, d, i = 1, 1, 1, 99 try: @@ -566,6 +567,23 @@ class ExceptionArcTest(CoverageTest): arcz=".1 12 .3 3-2 24 45 56 67 7B 89 9B BC C.", arcz_missing="67 7B", arcz_unpredicted="68") + def test_multiple_except_clauses(self): + self.check_coverage("""\ + a, b, c = 1, 1, 1 + try: + a = 3 + except ValueError: + b = 5 + except IndexError: + a = 7 + finally: + c = 9 + assert a == 3 and b == 1 and c == 9 + """, + arcz=".1 12 23 45 39 59 67 79 9A A.", arcz_missing="45 59 67 79") + # TODO: do it again, with line 3 raising a caught exception + # TODO: do it again, with line 3 raising an uncaught exception. + class YieldTest(CoverageTest): """Arc tests for generators.""" |