diff options
Diffstat (limited to '')
-rw-r--r-- | src/ansiblelint/rules/literal_compare.py | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/ansiblelint/rules/literal_compare.py b/src/ansiblelint/rules/literal_compare.py new file mode 100644 index 0000000..1129d1d --- /dev/null +++ b/src/ansiblelint/rules/literal_compare.py @@ -0,0 +1,86 @@ +"""Implementation of the literal-compare rule.""" +# Copyright (c) 2016, Will Thames and contributors +# Copyright (c) 2018-2021, Ansible Project + +from __future__ import annotations + +import re +import sys +from typing import TYPE_CHECKING + +from ansiblelint.rules import AnsibleLintRule +from ansiblelint.yaml_utils import nested_items_path + +if TYPE_CHECKING: + from ansiblelint.file_utils import Lintable + from ansiblelint.utils import Task + + +class ComparisonToLiteralBoolRule(AnsibleLintRule): + """Don't compare to literal True/False.""" + + id = "literal-compare" + description = ( + "Use ``when: var`` rather than ``when: var == True`` " + "(or conversely ``when: not var``)" + ) + severity = "HIGH" + tags = ["idiom"] + version_added = "v4.0.0" + + literal_bool_compare = re.compile("[=!]= ?(True|true|False|false)") + + def matchtask( + self, + task: Task, + file: Lintable | None = None, + ) -> bool | str: + for k, v, _ in nested_items_path(task): + if k == "when": + if isinstance(v, str): + if self.literal_bool_compare.search(v): + return True + elif isinstance(v, bool): + pass + else: + for item in v: + if isinstance(item, str) and self.literal_bool_compare.search( + item, + ): + return True + + return False + + +if "pytest" in sys.modules: + import pytest + + from ansiblelint.rules import RulesCollection # pylint: disable=ungrouped-imports + from ansiblelint.runner import Runner # pylint: disable=ungrouped-imports + + @pytest.mark.parametrize( + ("test_file", "failures"), + ( + pytest.param( + "examples/playbooks/rule_literal_compare_fail.yml", + 3, + id="fail", + ), + pytest.param( + "examples/playbooks/rule_literal_compare_pass.yml", + 0, + id="pass", + ), + ), + ) + def test_literal_compare( + default_rules_collection: RulesCollection, + test_file: str, + failures: int, + ) -> None: + """Test rule matches.""" + # Enable checking of loop variable prefixes in roles + results = Runner(test_file, rules=default_rules_collection).run() + for result in results: + assert result.rule.id == "literal-compare" + assert len(results) == failures |