Skip to content

Commit 533e598

Browse files
committed
Config option to exclude block tags by regex
1 parent 53d114a commit 533e598

3 files changed

Lines changed: 58 additions & 9 deletions

File tree

README.rst

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

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

102-
[tool.coverage.run]
103-
plugins = [
104-
'django_coverage_plugin',
105-
]
105+
[run]
106+
plugins = django_coverage_plugin
107+
108+
[django_coverage_plugin]
109+
exclude_blocks = ["my_tag.+"]
106110

107-
[tool.coverage.django_coverage_plugin]
108-
template_extensions = 'html, txt, tex, email'
109111

110112
Caveats
111113
~~~~~~~

django_coverage_plugin/plugin.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ class DjangoTemplatePlugin(
116116
def __init__(self, options):
117117
extensions = options.get("template_extensions", "html,htm,txt")
118118
self.extensions = [e.strip() for e in extensions.split(",")]
119+
120+
self.exclude_blocks = options.get("exclude_blocks")
119121

120122
self.debug_checked = False
121123

@@ -151,7 +153,7 @@ def file_tracer(self, filename):
151153
return None
152154

153155
def file_reporter(self, filename):
154-
return FileReporter(filename)
156+
return FileReporter(filename, self.exclude_blocks)
155157

156158
def find_executable_files(self, src_dir):
157159
# We're only interested in files that look like reasonable HTML
@@ -259,10 +261,16 @@ def get_line_map(self, filename):
259261

260262

261263
class FileReporter(coverage.plugin.FileReporter):
262-
def __init__(self, filename):
264+
def __init__(self, filename, exclude_blocks):
263265
super().__init__(filename)
264266
# TODO: html filenames are absolute.
265267

268+
if exclude_blocks:
269+
self.exclude_blocks_regex = re.compile(join_regex(exclude_blocks))
270+
else:
271+
self.exclude_blocks_regex = None
272+
self._excluded = set()
273+
266274
self._source = None
267275

268276
def source(self):
@@ -318,6 +326,12 @@ def lines(self):
318326
# In an inheriting template, ignore all tags outside of
319327
# blocks.
320328
continue
329+
330+
# Ignore any block token content that has been explcitly
331+
# excluded in config
332+
if self.exclude_block_token(token):
333+
self._excluded.add(token.lineno)
334+
continue
321335

322336
if token.contents == "comment":
323337
comment = True
@@ -356,6 +370,12 @@ def lines(self):
356370

357371
return source_lines
358372

373+
def excluded_lines(self):
374+
return self._excluded
375+
376+
def exclude_block_token(self, token):
377+
if self.exclude_blocks_regex:
378+
return self.exclude_blocks_regex.search(token.contents)
359379

360380
def running_sum(seq):
361381
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)