Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ignore Jinja rules in Jinja escaped blocks #236

Merged
merged 2 commits into from
Jan 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes in **salt-lint** are documented below.
## [Unreleased]
### Fixed
- 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)).
- Ignore Jinja specific rules in Jinja escaped blocks ([#236](https://github.com/warpnet/salt-lint/pull/236)).

## [0.5.1] (2021-01-19)
### Fixed
Expand Down
40 changes: 39 additions & 1 deletion saltlint/linter/rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from saltlint.utils import get_rule_skips_from_line, get_file_type
from saltlint.linter.match import Match
from saltlint.utils import LANGUAGE_SLS
from saltlint.utils import LANGUAGE_SLS, LANGUAGE_JINJA


class Rule(object):
Expand Down Expand Up @@ -89,6 +89,44 @@ def matchfulltext(self, file, text):
return matches


class JinjaRule(Rule):
languages = [LANGUAGE_SLS, LANGUAGE_JINJA]
tags = ['formatting', 'jinja']

# Regex for matching all escaped Jinja blocks in the text
jinja_escape_regex = re.compile(
r"{%[+-]?\s?raw\s?[+-]?%}.*{%[+-]?\s?endraw\s?[+-]?%}",
re.DOTALL | re.MULTILINE
)

def matchlines(self, file, text):
"""
Match the text line by line but ignore all escaped Jinja blocks, e.g.
content between {% raw %} and {% endraw %}.

Returns a list of Match objects.
"""
escaped_text = text
# Replace escaped Jinja blocks with the same number of empty lines
for match in self.jinja_escape_regex.finditer(text):
start = match.start()
end = match.end()
# Get the number of newlines in the escaped match
lines = text[start:end].splitlines()
num_of_lines = len(lines) - 1

# Replace escaped Jinja block in the escaped text by newlines to
# keep all the line numbers consistent
pre_text = escaped_text[:start]
post_text = escaped_text[end:]
newlines = '\n' * num_of_lines
escaped_text = pre_text + newlines + post_text

# Call the matchlines() on the parent class with the escaped text
matches = super(JinjaRule, self).matchlines(file, escaped_text) # pylint: disable=R1725
return matches


class DeprecationRule(Rule):
id = None
state = None
Expand Down
9 changes: 3 additions & 6 deletions saltlint/rules/JinjaCommentHasSpacesRule.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016 Will Thames and contributors
# Copyright (c) 2018 Ansible Project
# Modified work Copyright (c) 2020 Warpnet B.V.
# Modified work Copyright (c) 2020-2021 Warpnet B.V.

import re
from saltlint.linter.rule import Rule
from saltlint.utils import LANGUAGE_JINJA, LANGUAGE_SLS
from saltlint.linter.rule import JinjaRule


class JinjaCommentHasSpacesRule(Rule):
class JinjaCommentHasSpacesRule(JinjaRule):
id = '209'
shortdesc = "Jinja comment should have spaces before and after: '{# comment #}'"
description = "Jinja comment should have spaces before and after: '{# comment #}'"
severity = 'LOW'
languages = [LANGUAGE_SLS, LANGUAGE_JINJA]
tags = ['formatting', 'jinja']
version_added = 'v0.0.5'

bracket_regex = re.compile(r"{#[^ \-\+]|{#[\-\+][^ ]|[^ \-\+]#}|[^ ][\-\+]#}")
Expand Down
9 changes: 3 additions & 6 deletions saltlint/rules/JinjaPillarGrainsGetFormatRule.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016 Will Thames and contributors
# Copyright (c) 2018 Ansible Project
# Modified work Copyright (c) 2020 Warpnet B.V.
# Modified work Copyright (c) 2020-2021 Warpnet B.V.

import re
from saltlint.linter.rule import Rule
from saltlint.utils import LANGUAGE_JINJA, LANGUAGE_SLS
from saltlint.linter.rule import JinjaRule


class JinjaPillarGrainsGetFormatRule(Rule):
class JinjaPillarGrainsGetFormatRule(JinjaRule):
id = '211'
shortdesc = 'pillar.get or grains.get should be formatted differently'
description = "pillar.get and grains.get should always be formatted " \
"like salt['pillar.get']('item'), grains['item1'] or " \
" pillar.get('item')"
severity = 'HIGH'
languages = [LANGUAGE_SLS, LANGUAGE_JINJA]
tags = ['formatting', 'jinja']
version_added = 'v0.0.10'

bracket_regex = re.compile(r"{{( |\-|\+)?.(pillar|grains).get\[.+}}")
Expand Down
9 changes: 3 additions & 6 deletions saltlint/rules/JinjaStatementHasSpacesRule.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016 Will Thames and contributors
# Copyright (c) 2018 Ansible Project
# Modified work Copyright (c) 2020 Warpnet B.V.
# Modified work Copyright (c) 2020-2021 Warpnet B.V.

import re
from saltlint.linter.rule import Rule
from saltlint.utils import LANGUAGE_JINJA, LANGUAGE_SLS
from saltlint.linter.rule import JinjaRule


class JinjaStatementHasSpacesRule(Rule):
class JinjaStatementHasSpacesRule(JinjaRule):
id = '202'
shortdesc = "Jinja statement should have spaces before and after: '{% statement %}'"
description = "Jinja statement should have spaces before and after: '{% statement %}'"
severity = 'LOW'
languages = [LANGUAGE_SLS, LANGUAGE_JINJA]
tags = ['formatting', 'jinja']
version_added = 'v0.0.2'

bracket_regex = re.compile(r"{%[^ \-\+]|{%[\-\+][^ ]|[^ \-\+]%}|[^ ][\-\+]%}")
Expand Down
9 changes: 3 additions & 6 deletions saltlint/rules/JinjaVariableHasSpacesRule.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016 Will Thames and contributors
# Copyright (c) 2018 Ansible Project
# Modified work Copyright (c) 2020 Warpnet B.V.
# Modified work Copyright (c) 2020-2021 Warpnet B.V.

import re
from saltlint.linter.rule import Rule
from saltlint.utils import LANGUAGE_JINJA, LANGUAGE_SLS
from saltlint.linter.rule import JinjaRule


class JinjaVariableHasSpacesRule(Rule):
class JinjaVariableHasSpacesRule(JinjaRule):
id = '206'
shortdesc = "Jinja variables should have spaces before and after: '{{ var_name }}'"
description = "Jinja variables should have spaces before and after: '{{ var_name }}'"
severity = 'LOW'
languages = [LANGUAGE_SLS, LANGUAGE_JINJA]
tags = ['formatting', 'jinja']
version_added = 'v0.0.1'

bracket_regex = re.compile(r"{{[^ \-\+\d]|{{[-\+][^ ]|[^ \-\+\d]}}|[^ {][-\+\d]}}")
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/TestJinjaCommentHasSpaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@

GOOD_COMMENT_LINE = '''
{#- set example='good' +#}

{% raw %}
# The following line should be ignored as it is placed in a Jinja escape
# block
{#-set example='bad'+#}
{% endraw %}
'''

BAD_COMMENT_LINE = '''
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/TestJinjaStatementHasSpaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@

GOOD_STATEMENT_LINE = '''
{%- set example='good' +%}

{% raw %}
# The following line should be ignored as it is placed in a Jinja escape
# block
{%-set example='bad'+%}
{% endraw %}
'''

BAD_STATEMENT_LINE = '''
Expand Down
28 changes: 27 additions & 1 deletion tests/unit/TestJinjaVariableHasSpaces.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2013-2018 Will Thames <will@thames.id.au>
# Copyright (c) 2018 Ansible by Red Hat
# Modified work Copyright (c) 2020 Warpnet B.V.
# Modified work Copyright (c) 2020-2021 Warpnet B.V.

import unittest

Expand All @@ -14,6 +14,19 @@
{{- variable +}}
'''

GOOD_VARIABLE_LINE_RAW = '''
{% raw %}
{{variable}}
{% endraw %}
'''

BAD_VARIABLE_LINE_RAW = '''
{% raw %}
{{variable}}
{% endraw %}
{{variable}} # line 5
'''

BAD_VARIABLE_LINE = '''
{{-variable+}}
'''
Expand Down Expand Up @@ -49,6 +62,19 @@ def test_statement_positive(self):
results = self.runner.run_state(GOOD_VARIABLE_LINE)
self.assertEqual(0, len(results))

def test_statement_jinja_raw_positive(self):
"""Check if Jinja looking variables between raw-blocks are ignored."""
results = self.runner.run_state(GOOD_VARIABLE_LINE_RAW)
self.assertEqual(0, len(results))

def test_statement_jinja_raw_negative(self):
"""Check if Jinja looking variables between raw-blocks are ignored."""
results = self.runner.run_state(BAD_VARIABLE_LINE_RAW)
# Check if the correct number of matches are found
self.assertEqual(1, len(results))
# Check if the match occurred on the correct line
self.assertEqual(results[0].linenumber, 5)

def test_statement_negative(self):
results = self.runner.run_state(BAD_VARIABLE_LINE)
self.assertEqual(1, len(results))
Expand Down