summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coverage/parser.py27
-rw-r--r--coverage/results.py4
-rw-r--r--tests/test_parser.py20
3 files changed, 37 insertions, 14 deletions
diff --git a/coverage/parser.py b/coverage/parser.py
index 42b9bcad..bc79a30a 100644
--- a/coverage/parser.py
+++ b/coverage/parser.py
@@ -38,7 +38,7 @@ class PythonParser(object):
except IOError as err:
raise NoSource(
"No source for code: '%s': %s" % (self.filename, err)
- )
+ )
self.exclude = exclude
@@ -112,7 +112,7 @@ class PythonParser(object):
print("%10s %5s %-20r %r" % (
tokenize.tok_name.get(toktype, toktype),
nice_pair((slineno, elineno)), ttext, ltext
- ))
+ ))
if toktype == token.INDENT:
indent += 1
elif toktype == token.DEDENT:
@@ -203,12 +203,16 @@ class PythonParser(object):
"""
try:
self._raw_parse()
- except (tokenize.TokenError, IndentationError) as tokerr:
- msg, lineno = tokerr.args # pylint: disable=unpacking-non-sequence
+ except (tokenize.TokenError, IndentationError) as err:
+ if hasattr(err, "lineno"):
+ lineno = err.lineno # IndentationError
+ else:
+ lineno = err.args[1][0] # TokenError
raise NotPython(
- "Couldn't parse '%s' as Python source: '%s' at %s" %
- (self.filename, msg, lineno)
+ "Couldn't parse '%s' as Python source: '%s' at line %d" % (
+ self.filename, err.args[0], lineno
)
+ )
excluded_lines = self.first_lines(self.excluded)
ignore = set()
@@ -290,7 +294,7 @@ OPS_CODE_END = _opcode_set('RETURN_VALUE')
OPS_CHUNK_END = _opcode_set(
'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'RETURN_VALUE', 'RAISE_VARARGS',
'BREAK_LOOP', 'CONTINUE_LOOP',
- )
+)
# Opcodes that unconditionally begin a new code chunk. By starting new chunks
# with unconditional jump instructions, we neatly deal with jumps to jumps
@@ -300,7 +304,7 @@ OPS_CHUNK_BEGIN = _opcode_set('JUMP_ABSOLUTE', 'JUMP_FORWARD')
# Opcodes that push a block on the block stack.
OPS_PUSH_BLOCK = _opcode_set(
'SETUP_LOOP', 'SETUP_EXCEPT', 'SETUP_FINALLY', 'SETUP_WITH'
- )
+)
# Block types for exception handling.
OPS_EXCEPT_BLOCKS = _opcode_set('SETUP_EXCEPT', 'SETUP_FINALLY')
@@ -343,10 +347,9 @@ class ByteParser(object):
for attr in ['co_lnotab', 'co_firstlineno', 'co_consts', 'co_code']:
if not hasattr(self.code, attr):
raise CoverageException(
- "This implementation of Python doesn't support code "
- "analysis.\n"
+ "This implementation of Python doesn't support code analysis.\n"
"Run coverage.py under CPython for this command."
- )
+ )
def child_parsers(self):
"""Iterate over all the code objects nested within this one.
@@ -664,4 +667,4 @@ class Chunk(object):
"!" if self.first else "",
"v" if self.entrance else "",
list(self.exits),
- )
+ )
diff --git a/coverage/results.py b/coverage/results.py
index 3f6ba123..2e82e24d 100644
--- a/coverage/results.py
+++ b/coverage/results.py
@@ -12,9 +12,9 @@ from coverage.misc import format_lines
class Analysis(object):
"""The results of analyzing a FileReporter."""
- def __init__(self, data, file_reporters):
+ def __init__(self, data, file_reporter):
self.data = data
- self.file_reporter = file_reporters
+ self.file_reporter = file_reporter
self.filename = self.file_reporter.filename
self.statements = self.file_reporter.statements()
self.excluded = self.file_reporter.excluded_statements()
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 18621d15..84b9a214 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -8,6 +8,7 @@ import textwrap
from tests.coveragetest import CoverageTest
from coverage import env
+from coverage.misc import NotPython
from coverage.parser import PythonParser
@@ -116,6 +117,25 @@ class PythonParserTest(CoverageTest):
""")
self.assertEqual(parser.exit_counts(), { 1:1, 2:1, 3:1, 6:1 })
+ def test_indentation_error(self):
+ msg = (
+ "Couldn't parse '<code>' as Python source: "
+ "'unindent does not match any outer indentation level' at line 3"
+ )
+ with self.assertRaisesRegex(NotPython, msg):
+ _ = self.parse_source("""\
+ 0 spaces
+ 2
+ 1
+ """)
+
+ def test_token_error(self):
+ msg = "Couldn't parse '<code>' as Python source: 'EOF in multi-line string' at line 1"
+ with self.assertRaisesRegex(NotPython, msg):
+ _ = self.parse_source("""\
+ '''
+ """)
+
class ParserFileTest(CoverageTest):
"""Tests for coverage.py's code parsing from files."""