summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2015-12-31 16:20:09 -0500
committerNed Batchelder <ned@nedbatchelder.com>2015-12-31 16:20:09 -0500
commit5a6627ce5050d331095c4b03aed8e540f3ed651f (patch)
treef7081c0f17055cf3d97c0c535d7b4c99192e0893
parent4b33f09a3d46e5dd051d060a1926567fd418cbb7 (diff)
downloadpython-coveragepy-git-5a6627ce5050d331095c4b03aed8e540f3ed651f.tar.gz
Make other comprehensions work on py2 and py3
--HG-- branch : ast-branch
-rw-r--r--coverage/parser.py20
-rw-r--r--tests/test_arcs.py37
2 files changed, 48 insertions, 9 deletions
diff --git a/coverage/parser.py b/coverage/parser.py
index ff2d2bec..36fa729c 100644
--- a/coverage/parser.py
+++ b/coverage/parser.py
@@ -10,6 +10,7 @@ import re
import token
import tokenize
+from coverage import env
from coverage.backward import range # pylint: disable=redefined-builtin
from coverage.backward import bytes_to_ints, string_class
from coverage.bytecode import ByteCodes, CodeObjects
@@ -323,7 +324,7 @@ class TryBlock(object):
class AstArcAnalyzer(object):
def __init__(self, text):
self.root_node = ast.parse(text)
- #ast_dump(self.root_node)
+ ast_dump(self.root_node)
self.arcs = None
self.block_stack = []
@@ -542,6 +543,10 @@ class AstArcAnalyzer(object):
print("*** Unhandled: {}".format(node))
return set([self.line_for_node(node)])
+ CODE_COMPREHENSIONS = set(["GeneratorExp", "DictComp", "SetComp"])
+ if env.PY3:
+ CODE_COMPREHENSIONS.add("ListComp")
+
def add_arcs_for_code_objects(self, root_node):
for node in ast.walk(root_node):
node_name = node.__class__.__name__
@@ -557,13 +562,12 @@ class AstArcAnalyzer(object):
self.block_stack.pop()
for exit in func_exits:
self.arcs.add((exit, -start))
- elif node_name == "comprehension":
- start = self.line_for_node(node)
- self.arcs.add((-1, start))
- self.arcs.add((start, -start))
- # TODO: guaranteed this won't work for multi-line comps.
-
-
+ elif node_name in self.CODE_COMPREHENSIONS:
+ for gen in node.generators:
+ start = self.line_for_node(gen)
+ self.arcs.add((-1, start))
+ self.arcs.add((start, -start))
+ # TODO: guaranteed this won't work for multi-line comps.
## Opcodes that guide the ByteParser.
diff --git a/tests/test_arcs.py b/tests/test_arcs.py
index 0407b560..a371401f 100644
--- a/tests/test_arcs.py
+++ b/tests/test_arcs.py
@@ -260,7 +260,7 @@ class LoopArcTest(CoverageTest):
if env.PY3:
arcz = ".1 12 23 34 45 36 63 57 7."
else:
- arcz = ".1 12 23 27 34 45 36 62 57 7."
+ arcz = ".1 12 23 34 45 36 62 57 7."
self.check_coverage("""\
a, i = 1, 0
while True:
@@ -341,6 +341,41 @@ class LoopArcTest(CoverageTest):
""",
arcz=arcz, arcz_missing="", arcz_unpredicted="")
+ def test_other_comprehensions(self):
+ # Generator expression:
+ self.check_coverage("""\
+ o = ((1,2), (3,4))
+ o = (a for a in o)
+ for tup in o:
+ x = tup[0]
+ y = tup[1]
+ """,
+ arcz=".1 .2 2-2 12 23 34 45 53 3.",
+ arcz_missing="", arcz_unpredicted=""
+ )
+ # Set comprehension:
+ self.check_coverage("""\
+ o = ((1,2), (3,4))
+ o = {a for a in o}
+ for tup in o:
+ x = tup[0]
+ y = tup[1]
+ """,
+ arcz=".1 .2 2-2 12 23 34 45 53 3.",
+ arcz_missing="", arcz_unpredicted=""
+ )
+ # Dict comprehension:
+ self.check_coverage("""\
+ o = ((1,2), (3,4))
+ o = {a:1 for a in o}
+ for tup in o:
+ x = tup[0]
+ y = tup[1]
+ """,
+ arcz=".1 .2 2-2 12 23 34 45 53 3.",
+ arcz_missing="", arcz_unpredicted=""
+ )
+
class ExceptionArcTest(CoverageTest):
"""Arc-measuring tests involving exception handling."""