Skip to content

Commit b99bc1b

Browse files
authored
Properly raise load-failure when utf-8 decoding fails (#2152)
1 parent 7225a51 commit b99bc1b

File tree

7 files changed

+22
-5
lines changed

7 files changed

+22
-5
lines changed

.github/workflows/tox.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ jobs:
155155
WSLENV: FORCE_COLOR:PYTEST_REQPASS:TOXENV:TOX_PARALLEL_NO_SPINNER
156156
# Number of expected test passes, safety measure for accidental skip of
157157
# tests. Update value if you add/remove tests.
158-
PYTEST_REQPASS: 648
158+
PYTEST_REQPASS: 649
159159

160160
steps:
161161
- name: Activate WSL1

examples/broken/encoding.j2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
�-�

src/ansiblelint/file_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ def get(self, key: Any, default: Any = None) -> Any:
203203
return default
204204

205205
def _populate_content_cache_from_disk(self) -> None:
206+
# Can raise UnicodeDecodeError
206207
self._content = self.path.resolve().read_text(encoding="utf-8")
207208
if self._original_content is None:
208209
self._original_content = self._content

src/ansiblelint/rules/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,13 +385,13 @@ def run(
385385
try:
386386
if file.content is not None: # loads the file content
387387
pass
388-
except IOError as exc:
388+
except (IOError, UnicodeDecodeError) as exc:
389389
return [
390390
MatchError(
391391
message=str(exc),
392392
filename=file,
393393
rule=LoadingFailureRule(),
394-
tag=exc.__class__.__name__.lower(),
394+
tag=f"{LoadingFailureRule.id}[{exc.__class__.__name__.lower()}]",
395395
)
396396
]
397397

test/eco/colsystem.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ warn_list: # or 'skip_list' to silence them completely
1616

1717

1818
STDOUT:
19-
.ansible-lint:1: load-failure: [Errno 2] No such file or directory: '~/.cache/ansible-lint-eco/colsystem/tests/ansible-lint.yml' (filenotfounderror)
19+
.ansible-lint:1: load-failure: [Errno 2] No such file or directory: '~/.cache/ansible-lint-eco/colsystem/tests/ansible-lint.yml' (load-failure[filenotfounderror])
2020
playbooks/molecule/sudo/molecule.yml:17: yaml: line too long (576 > 160 characters) (line-length)
2121
roles/authorized_key/meta/main.yml:1: schema: 7 is not one of ['6.1', '7.1', '7.2', 'all'] (schema[meta])
2222
roles/common/meta/main.yml:1: schema: 2.8 is not of type 'string' (schema[meta])

test/eco/hardening.result

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ CMD: ansible-lint -f pep8 -x fqcn-builtins
33
RC: 2
44

55
STDERR:
6-
WARNING Listing 49 violation(s) that are fatal
6+
WARNING Listing 50 violation(s) that are fatal
77
You can skip specific rules or tags by adding them to your configuration file:
88
# .config/ansible-lint.yml
99
warn_list: # or 'skip_list' to silence them completely
1010
- experimental # all rules tagged as experimental
11+
- load-failure # Failed to load or parse file.
1112
- schema # Perform JSON Schema Validation for known lintable kinds.
1213

1314

@@ -62,3 +63,4 @@ tasks/systemdconf.yml:1: schema: 'yes' is not of type 'boolean' (schema[tasks])
6263
tasks/timesyncd.yml:1: schema: 'yes' is not of type 'boolean' (schema[tasks])
6364
tasks/umask.yml:1: schema: 'yes' is not of type 'boolean' (schema[tasks])
6465
tasks/users.yml:1: schema: 'yes' is not of type 'boolean' (schema[tasks])
66+
templates/usr/share/dict/passwords.list.j2:1: load-failure: 'utf-8' codec can't decode byte 0xc3 in position 104779: invalid continuation byte (load-failure[unicodedecodeerror])

test/test_load_failure.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Tests for LoadFailureRule."""
2+
from ansiblelint.rules import RulesCollection
3+
from ansiblelint.runner import Runner
4+
5+
6+
def test_load_failure_encoding(default_rules_collection: RulesCollection) -> None:
7+
"""Check that we fail when file encoding is wrong."""
8+
runner = Runner("examples/broken/encoding.j2", rules=default_rules_collection)
9+
matches = runner.run()
10+
assert len(matches) == 1, matches
11+
assert matches[0].rule.id == "load-failure"
12+
assert "'utf-8' codec can't decode byte" in matches[0].message
13+
assert matches[0].tag == "load-failure[unicodedecodeerror]"

0 commit comments

Comments
 (0)