Skip to content

Commit 49d3016

Browse files
Add noqa skips in otherwise empty lines to the next non-empty line (#4567)
Co-authored-by: Ian Wienand <[email protected]>
1 parent 243e02b commit 49d3016

File tree

4 files changed

+63
-3
lines changed

4 files changed

+63
-3
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
# noqa: jinja[spacing]
3+
foo_postgresql_grafana_password_encoded: >-
4+
{% if '!' in foo_postgresql_grafana_password or '#' in foo_postgresql_grafana_password %}
5+
{{- ('\"\"\"' + foo_postgresql_grafana_password + '\"\"\"') | b64encode -}}
6+
{% else %}
7+
{{- foo_postgresql_grafana_password | b64encode -}}
8+
{% endif %}
9+
10+
# noqa: jinja[spacing]
11+
12+
foo_postgresql_grafana_password_encoded_2: >-
13+
{% if '!' in foo_postgresql_grafana_password or '#' in foo_postgresql_grafana_password %}
14+
{{- ('\"\"\"' + foo_postgresql_grafana_password + '\"\"\"') | b64encode -}}
15+
{% else %}
16+
{{- foo_postgresql_grafana_password | b64encode -}}
17+
{% endif %}
18+
19+
inner:
20+
# noqa: jinja[spacing]
21+
foo_postgresql_grafana_password_encoded: >-
22+
{% if '!' in foo_postgresql_grafana_password or '#' in foo_postgresql_grafana_password %}
23+
{{- ('\"\"\"' + foo_postgresql_grafana_password + '\"\"\"') | b64encode -}}
24+
{% else %}
25+
{{- foo_postgresql_grafana_password | b64encode -}}
26+
{% endif %}

src/ansiblelint/skip_utils.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555

5656
_logger = logging.getLogger(__name__)
5757
_found_deprecated_tags: set[str] = set()
58-
_noqa_comment_re = re.compile(r"^# noqa(\s|:)")
58+
_noqa_comment_re = re.compile(r"^\s*# noqa(\s|:)", flags=re.MULTILINE)
59+
_noqa_comment_line_re = re.compile(r"^\s*# noqa(\s|:).*$")
5960

6061
# playbook: Sequence currently expects only instances of one of the two
6162
# classes below but we should consider avoiding this chimera.
@@ -257,6 +258,25 @@ def get_nested_tasks(task: Any) -> Generator[Any, None, None]:
257258
yield task
258259

259260

261+
def _continue_skip_next_lines(
262+
lintable: Lintable,
263+
) -> None:
264+
"""When a line only contains a noqa comment (and possibly indentation), add the skip also to the next non-empty line."""
265+
# If line starts with _noqa_comment_line_re, add next non-empty line to same lintable.line_skips
266+
line_content = lintable.content.splitlines()
267+
for line_no in list(lintable.line_skips.keys()):
268+
if _noqa_comment_line_re.fullmatch(line_content[line_no - 1]):
269+
# Find next non-empty line
270+
next_line_no = line_no
271+
while next_line_no < len(line_content) and not line_content[next_line_no].strip():
272+
next_line_no += 1
273+
if next_line_no >= len(line_content):
274+
continue
275+
lintable.line_skips[next_line_no + 1].update(
276+
lintable.line_skips[line_no],
277+
)
278+
279+
260280
def _get_rule_skips_from_yaml(
261281
yaml_input: Sequence[Any],
262282
lintable: Lintable,
@@ -268,7 +288,13 @@ def _get_rule_skips_from_yaml(
268288
return []
269289

270290
def traverse_yaml(obj: Any) -> None:
271-
for entry in obj.ca.items.values():
291+
traversable = list(obj.ca.items.values())
292+
if obj.ca.comment:
293+
traversable.append(obj.ca.comment)
294+
for entry in traversable:
295+
# flatten all lists we might have in entries. Some arcane ruamel CommentedMap magic
296+
entry = [item for sublist in entry if sublist is not None
297+
for item in (sublist if isinstance(sublist, list) else [sublist])]
272298
for v in entry:
273299
if isinstance(v, CommentToken):
274300
comment_str = v.value
@@ -298,6 +324,7 @@ def traverse_yaml(obj: Any) -> None:
298324
for comment_obj_str in yaml_comment_obj_strings:
299325
for line in comment_obj_str.split(r"\n"):
300326
rule_id_list.extend(get_rule_skips_from_line(line, lintable=lintable))
327+
_continue_skip_next_lines(lintable)
301328

302329
return [normalize_tag(tag) for tag in rule_id_list]
303330

test/test_skiputils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ def test_playbook_noqa2(default_text_runner: RunFromText) -> None:
6464
assert len(results) == 1
6565

6666

67+
def test_var_noqa(default_text_runner: RunFromText) -> None:
68+
"""Check that noqa is properly taken into account on vars and tasks."""
69+
results = default_text_runner.run(Path("examples/playbooks/vars/noqa_multiline.yml"))
70+
# Should raise no error at "SOME_VAR".
71+
assert len(results) == 0
72+
73+
6774
@pytest.mark.parametrize(
6875
("lintable", "yaml", "expected_form"),
6976
(

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ set_env =
5656
PIP_CONSTRAINT = {tox_root}/.config/constraints.txt
5757
PIP_DISABLE_PIP_VERSION_CHECK = 1
5858
PRE_COMMIT_COLOR = always
59-
PYTEST_REQPASS = 912
59+
PYTEST_REQPASS = 913
6060
UV_CONSTRAINT = {tox_root}/.config/constraints.txt
6161
deps, devel, hook, lint, pkg, pre, py310, schemas: PIP_CONSTRAINT = /dev/null
6262
deps, devel, hook, lint, pkg, pre, py310, schemas: UV_CONSTRAINT = /dev/null

0 commit comments

Comments
 (0)