|
10 | 10 | import django |
11 | 11 | import django.template |
12 | 12 | from coverage.exceptions import NoSource |
| 13 | +from coverage.misc import join_regex |
13 | 14 | from django.template.base import Lexer, NodeList, Template, TextNode, TokenType |
14 | 15 | from django.template.defaulttags import VerbatimNode |
15 | 16 | from django.templatetags.i18n import BlockTranslateNode |
@@ -116,6 +117,8 @@ class DjangoTemplatePlugin( |
116 | 117 | def __init__(self, options): |
117 | 118 | extensions = options.get("template_extensions", "html,htm,txt") |
118 | 119 | self.extensions = [e.strip() for e in extensions.split(",")] |
| 120 | + |
| 121 | + self.exclude_blocks = options.get("exclude_blocks") |
119 | 122 |
|
120 | 123 | self.debug_checked = False |
121 | 124 |
|
@@ -151,7 +154,7 @@ def file_tracer(self, filename): |
151 | 154 | return None |
152 | 155 |
|
153 | 156 | def file_reporter(self, filename): |
154 | | - return FileReporter(filename) |
| 157 | + return FileReporter(filename, self.exclude_blocks) |
155 | 158 |
|
156 | 159 | def find_executable_files(self, src_dir): |
157 | 160 | # We're only interested in files that look like reasonable HTML |
@@ -259,10 +262,16 @@ def get_line_map(self, filename): |
259 | 262 |
|
260 | 263 |
|
261 | 264 | class FileReporter(coverage.plugin.FileReporter): |
262 | | - def __init__(self, filename): |
| 265 | + def __init__(self, filename, exclude_blocks): |
263 | 266 | super().__init__(filename) |
264 | 267 | # TODO: html filenames are absolute. |
265 | 268 |
|
| 269 | + if exclude_blocks: |
| 270 | + self.exclude_blocks_regex = re.compile(join_regex(exclude_blocks)) |
| 271 | + else: |
| 272 | + self.exclude_blocks_regex = None |
| 273 | + self._excluded = set() |
| 274 | + |
266 | 275 | self._source = None |
267 | 276 |
|
268 | 277 | def source(self): |
@@ -318,6 +327,12 @@ def lines(self): |
318 | 327 | # In an inheriting template, ignore all tags outside of |
319 | 328 | # blocks. |
320 | 329 | continue |
| 330 | + |
| 331 | + # Ignore any block token content that has been explcitly |
| 332 | + # excluded in config |
| 333 | + if self.exclude_block_token(token): |
| 334 | + self._excluded.add(token.lineno) |
| 335 | + continue |
321 | 336 |
|
322 | 337 | if token.contents == "comment": |
323 | 338 | comment = True |
@@ -356,6 +371,12 @@ def lines(self): |
356 | 371 |
|
357 | 372 | return source_lines |
358 | 373 |
|
| 374 | + def excluded_lines(self): |
| 375 | + return self._excluded |
| 376 | + |
| 377 | + def exclude_block_token(self, token): |
| 378 | + if self.exclude_blocks_regex: |
| 379 | + return self.exclude_blocks_regex.search(token.contents) |
359 | 380 |
|
360 | 381 | def running_sum(seq): |
361 | 382 | total = 0 |
|
0 commit comments