summaryrefslogtreecommitdiff
path: root/coverage/parser.py
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2015-11-28 14:45:27 -0500
committerNed Batchelder <ned@nedbatchelder.com>2015-11-28 14:45:27 -0500
commited73d02203e0096a7fcec28506a23cc860c506f5 (patch)
treeb22dcd7f0da4b6f32df60723fae3d593af4726bd /coverage/parser.py
parent5a3f3c5525a97e5da2220f7ba30275c7e464111b (diff)
downloadpython-coveragepy-ed73d02203e0096a7fcec28506a23cc860c506f5.tar.gz
Pragmas on decorators apply to the entire function or class. #131
Diffstat (limited to 'coverage/parser.py')
-rw-r--r--coverage/parser.py39
1 files changed, 27 insertions, 12 deletions
diff --git a/coverage/parser.py b/coverage/parser.py
index 111826d..7b8a60f 100644
--- a/coverage/parser.py
+++ b/coverage/parser.py
@@ -117,9 +117,11 @@ class PythonParser(object):
indent = 0
exclude_indent = 0
excluding = False
+ excluding_decorators = False
prev_toktype = token.INDENT
first_line = None
empty = True
+ first_on_line = True
tokgen = generate_tokens(self.text)
for toktype, ttext, (slineno, _), (elineno, _), ltext in tokgen:
@@ -132,18 +134,29 @@ class PythonParser(object):
indent += 1
elif toktype == token.DEDENT:
indent -= 1
- elif toktype == token.NAME and ttext == 'class':
- # Class definitions look like branches in the byte code, so
- # we need to exclude them. The simplest way is to note the
- # lines with the 'class' keyword.
- self.raw_classdefs.add(slineno)
- elif toktype == token.OP and ttext == ':':
- if not excluding and elineno in self.raw_excluded:
- # Start excluding a suite. We trigger off of the colon
- # token so that the #pragma comment will be recognized on
- # the same line as the colon.
- exclude_indent = indent
- excluding = True
+ elif toktype == token.NAME:
+ if ttext == 'class':
+ # Class definitions look like branches in the byte code, so
+ # we need to exclude them. The simplest way is to note the
+ # lines with the 'class' keyword.
+ self.raw_classdefs.add(slineno)
+ elif toktype == token.OP:
+ if ttext == ':':
+ should_exclude = (elineno in self.raw_excluded) or excluding_decorators
+ if not excluding and should_exclude:
+ # Start excluding a suite. We trigger off of the colon
+ # token so that the #pragma comment will be recognized on
+ # the same line as the colon.
+ self.raw_excluded.add(elineno)
+ exclude_indent = indent
+ excluding = True
+ excluding_decorators = False
+ elif ttext == '@' and first_on_line:
+ # A decorator.
+ if elineno in self.raw_excluded:
+ excluding_decorators = True
+ if excluding_decorators:
+ self.raw_excluded.add(elineno)
elif toktype == token.STRING and prev_toktype == token.INDENT:
# Strings that are first on an indented line are docstrings.
# (a trick from trace.py in the stdlib.) This works for
@@ -158,6 +171,7 @@ class PythonParser(object):
for l in range(first_line, elineno+1):
self._multiline[l] = first_line
first_line = None
+ first_on_line = True
if ttext.strip() and toktype != tokenize.COMMENT:
# A non-whitespace token.
@@ -171,6 +185,7 @@ class PythonParser(object):
excluding = False
if excluding:
self.raw_excluded.add(elineno)
+ first_on_line = False
prev_toktype = toktype