Skip to content

Commit 35d262f

Browse files
committed
Config option to exclude block tags by regex
1 parent ca45852 commit 35d262f

File tree

3 files changed

+60
-9
lines changed

3 files changed

+60
-9
lines changed

README.rst

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,17 @@ extensions if you like::
9191
[django_coverage_plugin]
9292
template_extensions = html, txt, tex, email
9393

94-
If you use ``pyproject.toml`` for tool configuration use::
94+
To exclude specific individual lines in a template, use the usual
95+
``# pragma: no cover`` notation inline. Template tags can also be excluded using regexes to
96+
match the block content; for example, to exclude a custom template tag
97+
``{% my_tag ... %}``, use::
9598

96-
[tool.coverage.run]
97-
plugins = [
98-
'django_coverage_plugin',
99-
]
99+
[run]
100+
plugins = django_coverage_plugin
101+
102+
[django_coverage_plugin]
103+
exclude_blocks = ["my_tag.+"]
100104

101-
[tool.coverage.django_coverage_plugin]
102-
template_extensions = 'html, txt, tex, email'
103105

104106
Caveats
105107
~~~~~~~

django_coverage_plugin/plugin.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import os.path
77
import re
88

9+
from coverage.misc import join_regex
10+
911
try:
1012
from coverage.exceptions import NoSource
1113
except ImportError:
@@ -149,6 +151,8 @@ class DjangoTemplatePlugin(
149151
def __init__(self, options):
150152
extensions = options.get("template_extensions", "html,htm,txt")
151153
self.extensions = [e.strip() for e in extensions.split(",")]
154+
155+
self.exclude_blocks = options.get("exclude_blocks")
152156

153157
self.debug_checked = False
154158

@@ -184,7 +188,7 @@ def file_tracer(self, filename):
184188
return None
185189

186190
def file_reporter(self, filename):
187-
return FileReporter(filename)
191+
return FileReporter(filename, self.exclude_blocks)
188192

189193
def find_executable_files(self, src_dir):
190194
# We're only interested in files that look like reasonable HTML
@@ -292,10 +296,16 @@ def get_line_map(self, filename):
292296

293297

294298
class FileReporter(coverage.plugin.FileReporter):
295-
def __init__(self, filename):
299+
def __init__(self, filename, exclude_blocks):
296300
super().__init__(filename)
297301
# TODO: html filenames are absolute.
298302

303+
if exclude_blocks:
304+
self.exclude_blocks_regex = re.compile(join_regex(exclude_blocks))
305+
else:
306+
self.exclude_blocks_regex = None
307+
self._excluded = set()
308+
299309
self._source = None
300310

301311
def source(self):
@@ -351,6 +361,12 @@ def lines(self):
351361
# In an inheriting template, ignore all tags outside of
352362
# blocks.
353363
continue
364+
365+
# Ignore any block token content that has been explcitly
366+
# excluded in config
367+
if self.exclude_block_token(token):
368+
self._excluded.add(token.lineno)
369+
continue
354370

355371
if token.contents == "comment":
356372
comment = True
@@ -389,6 +405,12 @@ def lines(self):
389405

390406
return source_lines
391407

408+
def excluded_lines(self):
409+
return self._excluded
410+
411+
def exclude_block_token(self, token):
412+
if self.exclude_blocks_regex:
413+
return self.exclude_blocks_regex.search(token.contents)
392414

393415
def running_sum(seq):
394416
total = 0

tests/test_simple.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,30 @@ def test_with_branch_enabled(self):
264264
)
265265
self.assertEqual(text, 'Hello\nWorld\n\nGoodbye')
266266
self.assert_analysis([1, 2, 3, 4])
267+
268+
269+
class ExcludeTest(DjangoPluginTestCase):
270+
"""Tests of excluding block tokens by regex."""
271+
272+
def test_exclude_block(self):
273+
self.make_template("""\
274+
First
275+
{% with foo='bar' %}
276+
{{ foo }}
277+
{% endwith %}
278+
Last
279+
""")
280+
text = self.run_django_coverage()
281+
self.assertEqual(text, "First\n\n bar\n\nLast\n")
282+
self.assert_analysis([1, 2, 3, 5])
283+
284+
self.make_file(".coveragerc", """\
285+
[run]
286+
plugins = django_coverage_plugin
287+
[django_coverage_plugin]
288+
exclude_blocks = [".+foo.+"]
289+
""")
290+
291+
text = self.run_django_coverage()
292+
self.assertEqual(text, "First\n\n bar\n\nLast\n")
293+
self.assert_analysis([1, 3, 5])

0 commit comments

Comments
 (0)