Skip to content

Commit a9ea6ab

Browse files
authored
fix: ignore Jinja rules in Jinja escaped blocks (#236)
Ignore Jinja specific rules in Jinja escaped blocks. Fixes #201 Signed-off-by: Roald Nefs <info@roaldnefs.com>
1 parent 05dc6f2 commit a9ea6ab

9 files changed

+91
-26
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ All notable changes in **salt-lint** are documented below.
44
## [Unreleased]
55
### Fixed
66
- Append the contents of the `CHANGELOG.md` file to the long description of the package instead of the duplicate `README.md` contents ([#234](https://github.com/warpnet/salt-lint/pull/234)).
7+
- Ignore Jinja specific rules in Jinja escaped blocks ([#236](https://github.com/warpnet/salt-lint/pull/236)).
78

89
## [0.5.1] (2021-01-19)
910
### Fixed

saltlint/linter/rule.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from saltlint.utils import get_rule_skips_from_line, get_file_type
99
from saltlint.linter.match import Match
10-
from saltlint.utils import LANGUAGE_SLS
10+
from saltlint.utils import LANGUAGE_SLS, LANGUAGE_JINJA
1111

1212

1313
class Rule(object):
@@ -89,6 +89,44 @@ def matchfulltext(self, file, text):
8989
return matches
9090

9191

92+
class JinjaRule(Rule):
93+
languages = [LANGUAGE_SLS, LANGUAGE_JINJA]
94+
tags = ['formatting', 'jinja']
95+
96+
# Regex for matching all escaped Jinja blocks in the text
97+
jinja_escape_regex = re.compile(
98+
r"{%[+-]?\s?raw\s?[+-]?%}.*{%[+-]?\s?endraw\s?[+-]?%}",
99+
re.DOTALL | re.MULTILINE
100+
)
101+
102+
def matchlines(self, file, text):
103+
"""
104+
Match the text line by line but ignore all escaped Jinja blocks, e.g.
105+
content between {% raw %} and {% endraw %}.
106+
107+
Returns a list of Match objects.
108+
"""
109+
escaped_text = text
110+
# Replace escaped Jinja blocks with the same number of empty lines
111+
for match in self.jinja_escape_regex.finditer(text):
112+
start = match.start()
113+
end = match.end()
114+
# Get the number of newlines in the escaped match
115+
lines = text[start:end].splitlines()
116+
num_of_lines = len(lines) - 1
117+
118+
# Replace escaped Jinja block in the escaped text by newlines to
119+
# keep all the line numbers consistent
120+
pre_text = escaped_text[:start]
121+
post_text = escaped_text[end:]
122+
newlines = '\n' * num_of_lines
123+
escaped_text = pre_text + newlines + post_text
124+
125+
# Call the matchlines() on the parent class with the escaped text
126+
matches = super(JinjaRule, self).matchlines(file, escaped_text) # pylint: disable=R1725
127+
return matches
128+
129+
92130
class DeprecationRule(Rule):
93131
id = None
94132
state = None

saltlint/rules/JinjaCommentHasSpacesRule.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
# -*- coding: utf-8 -*-
22
# Copyright (c) 2016 Will Thames and contributors
33
# Copyright (c) 2018 Ansible Project
4-
# Modified work Copyright (c) 2020 Warpnet B.V.
4+
# Modified work Copyright (c) 2020-2021 Warpnet B.V.
55

66
import re
7-
from saltlint.linter.rule import Rule
8-
from saltlint.utils import LANGUAGE_JINJA, LANGUAGE_SLS
7+
from saltlint.linter.rule import JinjaRule
98

109

11-
class JinjaCommentHasSpacesRule(Rule):
10+
class JinjaCommentHasSpacesRule(JinjaRule):
1211
id = '209'
1312
shortdesc = "Jinja comment should have spaces before and after: '{# comment #}'"
1413
description = "Jinja comment should have spaces before and after: '{# comment #}'"
1514
severity = 'LOW'
16-
languages = [LANGUAGE_SLS, LANGUAGE_JINJA]
17-
tags = ['formatting', 'jinja']
1815
version_added = 'v0.0.5'
1916

2017
bracket_regex = re.compile(r"{#[^ \-\+]|{#[\-\+][^ ]|[^ \-\+]#}|[^ ][\-\+]#}")

saltlint/rules/JinjaPillarGrainsGetFormatRule.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
# -*- coding: utf-8 -*-
22
# Copyright (c) 2016 Will Thames and contributors
33
# Copyright (c) 2018 Ansible Project
4-
# Modified work Copyright (c) 2020 Warpnet B.V.
4+
# Modified work Copyright (c) 2020-2021 Warpnet B.V.
55

66
import re
7-
from saltlint.linter.rule import Rule
8-
from saltlint.utils import LANGUAGE_JINJA, LANGUAGE_SLS
7+
from saltlint.linter.rule import JinjaRule
98

109

11-
class JinjaPillarGrainsGetFormatRule(Rule):
10+
class JinjaPillarGrainsGetFormatRule(JinjaRule):
1211
id = '211'
1312
shortdesc = 'pillar.get or grains.get should be formatted differently'
1413
description = "pillar.get and grains.get should always be formatted " \
1514
"like salt['pillar.get']('item'), grains['item1'] or " \
1615
" pillar.get('item')"
1716
severity = 'HIGH'
18-
languages = [LANGUAGE_SLS, LANGUAGE_JINJA]
19-
tags = ['formatting', 'jinja']
2017
version_added = 'v0.0.10'
2118

2219
bracket_regex = re.compile(r"{{( |\-|\+)?.(pillar|grains).get\[.+}}")

saltlint/rules/JinjaStatementHasSpacesRule.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
# -*- coding: utf-8 -*-
22
# Copyright (c) 2016 Will Thames and contributors
33
# Copyright (c) 2018 Ansible Project
4-
# Modified work Copyright (c) 2020 Warpnet B.V.
4+
# Modified work Copyright (c) 2020-2021 Warpnet B.V.
55

66
import re
7-
from saltlint.linter.rule import Rule
8-
from saltlint.utils import LANGUAGE_JINJA, LANGUAGE_SLS
7+
from saltlint.linter.rule import JinjaRule
98

109

11-
class JinjaStatementHasSpacesRule(Rule):
10+
class JinjaStatementHasSpacesRule(JinjaRule):
1211
id = '202'
1312
shortdesc = "Jinja statement should have spaces before and after: '{% statement %}'"
1413
description = "Jinja statement should have spaces before and after: '{% statement %}'"
1514
severity = 'LOW'
16-
languages = [LANGUAGE_SLS, LANGUAGE_JINJA]
17-
tags = ['formatting', 'jinja']
1815
version_added = 'v0.0.2'
1916

2017
bracket_regex = re.compile(r"{%[^ \-\+]|{%[\-\+][^ ]|[^ \-\+]%}|[^ ][\-\+]%}")

saltlint/rules/JinjaVariableHasSpacesRule.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
# -*- coding: utf-8 -*-
22
# Copyright (c) 2016 Will Thames and contributors
33
# Copyright (c) 2018 Ansible Project
4-
# Modified work Copyright (c) 2020 Warpnet B.V.
4+
# Modified work Copyright (c) 2020-2021 Warpnet B.V.
55

66
import re
7-
from saltlint.linter.rule import Rule
8-
from saltlint.utils import LANGUAGE_JINJA, LANGUAGE_SLS
7+
from saltlint.linter.rule import JinjaRule
98

109

11-
class JinjaVariableHasSpacesRule(Rule):
10+
class JinjaVariableHasSpacesRule(JinjaRule):
1211
id = '206'
1312
shortdesc = "Jinja variables should have spaces before and after: '{{ var_name }}'"
1413
description = "Jinja variables should have spaces before and after: '{{ var_name }}'"
1514
severity = 'LOW'
16-
languages = [LANGUAGE_SLS, LANGUAGE_JINJA]
17-
tags = ['formatting', 'jinja']
1815
version_added = 'v0.0.1'
1916

2017
bracket_regex = re.compile(r"{{[^ \-\+\d]|{{[-\+][^ ]|[^ \-\+\d]}}|[^ {][-\+\d]}}")

tests/unit/TestJinjaCommentHasSpaces.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212

1313
GOOD_COMMENT_LINE = '''
1414
{#- set example='good' +#}
15+
16+
{% raw %}
17+
# The following line should be ignored as it is placed in a Jinja escape
18+
# block
19+
{#-set example='bad'+#}
20+
{% endraw %}
1521
'''
1622

1723
BAD_COMMENT_LINE = '''

tests/unit/TestJinjaStatementHasSpaces.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212

1313
GOOD_STATEMENT_LINE = '''
1414
{%- set example='good' +%}
15+
16+
{% raw %}
17+
# The following line should be ignored as it is placed in a Jinja escape
18+
# block
19+
{%-set example='bad'+%}
20+
{% endraw %}
1521
'''
1622

1723
BAD_STATEMENT_LINE = '''

tests/unit/TestJinjaVariableHasSpaces.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22
# Copyright (c) 2013-2018 Will Thames <will@thames.id.au>
33
# Copyright (c) 2018 Ansible by Red Hat
4-
# Modified work Copyright (c) 2020 Warpnet B.V.
4+
# Modified work Copyright (c) 2020-2021 Warpnet B.V.
55

66
import unittest
77

@@ -14,6 +14,19 @@
1414
{{- variable +}}
1515
'''
1616

17+
GOOD_VARIABLE_LINE_RAW = '''
18+
{% raw %}
19+
{{variable}}
20+
{% endraw %}
21+
'''
22+
23+
BAD_VARIABLE_LINE_RAW = '''
24+
{% raw %}
25+
{{variable}}
26+
{% endraw %}
27+
{{variable}} # line 5
28+
'''
29+
1730
BAD_VARIABLE_LINE = '''
1831
{{-variable+}}
1932
'''
@@ -49,6 +62,19 @@ def test_statement_positive(self):
4962
results = self.runner.run_state(GOOD_VARIABLE_LINE)
5063
self.assertEqual(0, len(results))
5164

65+
def test_statement_jinja_raw_positive(self):
66+
"""Check if Jinja looking variables between raw-blocks are ignored."""
67+
results = self.runner.run_state(GOOD_VARIABLE_LINE_RAW)
68+
self.assertEqual(0, len(results))
69+
70+
def test_statement_jinja_raw_negative(self):
71+
"""Check if Jinja looking variables between raw-blocks are ignored."""
72+
results = self.runner.run_state(BAD_VARIABLE_LINE_RAW)
73+
# Check if the correct number of matches are found
74+
self.assertEqual(1, len(results))
75+
# Check if the match occurred on the correct line
76+
self.assertEqual(results[0].linenumber, 5)
77+
5278
def test_statement_negative(self):
5379
results = self.runner.run_state(BAD_VARIABLE_LINE)
5480
self.assertEqual(1, len(results))

0 commit comments

Comments
 (0)