From eab3e1b18e21aa4361e7c7f8c7a18140cb26b2a9 Mon Sep 17 00:00:00 2001 From: Satoru SATOH Date: Tue, 20 Apr 2021 19:32:49 +0900 Subject: [PATCH] add 'file: Lintable' argument to BaseRule.matchtask method (#1535) Add 'file: Lintable' argument to matchtask method of the rule classes which is None by default, because there are cases that it is necessary to do some analyses depends on the context, that is, file: Lintable, like the followings. - want to restrict tasks in 'main.yml' use include_tasks only - want to restrict the level of inclusions with include_tasks to 2 Signed-Off-By: Satoru SATOH --- examples/rules/TaskHasTag.py | 11 +++++++++-- src/ansiblelint/_internal/rules.py | 6 +++++- src/ansiblelint/rules/CommandHasChangesCheckRule.py | 11 +++++++++-- .../rules/CommandsInsteadOfArgumentsRule.py | 11 +++++++++-- .../rules/CommandsInsteadOfModulesRule.py | 11 +++++++++-- src/ansiblelint/rules/ComparisonToEmptyStringRule.py | 11 +++++++++-- src/ansiblelint/rules/ComparisonToLiteralBoolRule.py | 11 +++++++++-- src/ansiblelint/rules/DeprecatedModuleRule.py | 11 +++++++++-- src/ansiblelint/rules/EnvVarsInCommandRule.py | 11 +++++++++-- src/ansiblelint/rules/GitHasVersionRule.py | 11 +++++++++-- src/ansiblelint/rules/MercurialHasRevisionRule.py | 11 +++++++++-- src/ansiblelint/rules/MissingFilePermissionsRule.py | 12 ++++++++++-- src/ansiblelint/rules/NestedJinjaRule.py | 12 +++++++++--- src/ansiblelint/rules/NoFormattingInWhenRule.py | 8 ++++++-- src/ansiblelint/rules/NoTabsRule.py | 11 +++++++++-- src/ansiblelint/rules/OctalPermissionsRule.py | 11 +++++++++-- src/ansiblelint/rules/PackageIsNotLatestRule.py | 11 +++++++++-- src/ansiblelint/rules/RoleRelativePath.py | 11 +++++++++-- src/ansiblelint/rules/ShellWithoutPipefail.py | 11 +++++++++-- src/ansiblelint/rules/TaskHasNameRule.py | 11 +++++++++-- src/ansiblelint/rules/TaskNoLocalAction.py | 1 - .../rules/UseCommandInsteadOfShellRule.py | 11 +++++++++-- .../rules/UseHandlerRatherThanWhenChangedRule.py | 8 +++++--- .../rules/UsingBareVariablesIsDeprecatedRule.py | 11 +++++++++-- src/ansiblelint/rules/VariableHasSpacesRule.py | 8 +++++--- src/ansiblelint/rules/__init__.py | 2 +- 26 files changed, 203 insertions(+), 52 deletions(-) diff --git a/examples/rules/TaskHasTag.py b/examples/rules/TaskHasTag.py index 24394eabdd..c5e4d66792 100644 --- a/examples/rules/TaskHasTag.py +++ b/examples/rules/TaskHasTag.py @@ -1,8 +1,13 @@ """Example implementation of a rule requiring tasks to have tags set.""" -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class TaskHasTag(AnsibleLintRule): """Tasks must have tag.""" @@ -12,7 +17,9 @@ class TaskHasTag(AnsibleLintRule): description = 'Tasks must have tag' tags = ['productivity', 'tags'] - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: """Task matching method.""" if isinstance(task, str): return False diff --git a/src/ansiblelint/_internal/rules.py b/src/ansiblelint/_internal/rules.py index a241fa9646..268922966c 100644 --- a/src/ansiblelint/_internal/rules.py +++ b/src/ansiblelint/_internal/rules.py @@ -2,6 +2,8 @@ from typing import TYPE_CHECKING, Any, Dict, List, Union if TYPE_CHECKING: + from typing import Optional + from ansiblelint.constants import odict from ansiblelint.errors import MatchError from ansiblelint.file_utils import Lintable @@ -43,7 +45,9 @@ def matchlines(self, file: "Lintable") -> List["MatchError"]: """Return matches found for a specific line.""" return [] - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: "Optional[Lintable]" = None + ) -> Union[bool, str]: """Confirm if current rule is matching a specific task.""" return False diff --git a/src/ansiblelint/rules/CommandHasChangesCheckRule.py b/src/ansiblelint/rules/CommandHasChangesCheckRule.py index 6926dc90fa..27761687f0 100644 --- a/src/ansiblelint/rules/CommandHasChangesCheckRule.py +++ b/src/ansiblelint/rules/CommandHasChangesCheckRule.py @@ -18,10 +18,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class CommandHasChangesCheckRule(AnsibleLintRule): id = 'no-changed-when' @@ -38,7 +43,9 @@ class CommandHasChangesCheckRule(AnsibleLintRule): _commands = ['command', 'shell', 'raw'] - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: if task["__ansible_action_type__"] == 'task': if task["action"]["__ansible_module__"] in self._commands: return ( diff --git a/src/ansiblelint/rules/CommandsInsteadOfArgumentsRule.py b/src/ansiblelint/rules/CommandsInsteadOfArgumentsRule.py index e1bb05314d..0eedf4ca4c 100644 --- a/src/ansiblelint/rules/CommandsInsteadOfArgumentsRule.py +++ b/src/ansiblelint/rules/CommandsInsteadOfArgumentsRule.py @@ -19,11 +19,16 @@ # THE SOFTWARE. import os -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule from ansiblelint.utils import convert_to_boolean, get_first_cmd_arg +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class CommandsInsteadOfArgumentsRule(AnsibleLintRule): id = 'deprecated-command-syntax' @@ -47,7 +52,9 @@ class CommandsInsteadOfArgumentsRule(AnsibleLintRule): 'rm': 'state=absent', } - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: if task["action"]["__ansible_module__"] in self._commands: first_cmd_arg = get_first_cmd_arg(task) if not first_cmd_arg: diff --git a/src/ansiblelint/rules/CommandsInsteadOfModulesRule.py b/src/ansiblelint/rules/CommandsInsteadOfModulesRule.py index 402f248196..1a76f6a00b 100644 --- a/src/ansiblelint/rules/CommandsInsteadOfModulesRule.py +++ b/src/ansiblelint/rules/CommandsInsteadOfModulesRule.py @@ -19,11 +19,16 @@ # THE SOFTWARE. import os -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule from ansiblelint.utils import convert_to_boolean, get_first_cmd_arg +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class CommandsInsteadOfModulesRule(AnsibleLintRule): id = 'command-instead-of-module' @@ -59,7 +64,9 @@ class CommandsInsteadOfModulesRule(AnsibleLintRule): 'yum': 'yum', } - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: if task['action']['__ansible_module__'] not in self._commands: return False diff --git a/src/ansiblelint/rules/ComparisonToEmptyStringRule.py b/src/ansiblelint/rules/ComparisonToEmptyStringRule.py index c16813cf39..34b1d093b8 100644 --- a/src/ansiblelint/rules/ComparisonToEmptyStringRule.py +++ b/src/ansiblelint/rules/ComparisonToEmptyStringRule.py @@ -3,11 +3,16 @@ import re import sys -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule from ansiblelint.utils import nested_items +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class ComparisonToEmptyStringRule(AnsibleLintRule): id = 'empty-string-compare' @@ -22,7 +27,9 @@ class ComparisonToEmptyStringRule(AnsibleLintRule): empty_string_compare = re.compile("[=!]= ?(\"{2}|'{2})") - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: for k, v, _ in nested_items(task): if k == 'when': if isinstance(v, str): diff --git a/src/ansiblelint/rules/ComparisonToLiteralBoolRule.py b/src/ansiblelint/rules/ComparisonToLiteralBoolRule.py index 840205800e..717d97c1f4 100644 --- a/src/ansiblelint/rules/ComparisonToLiteralBoolRule.py +++ b/src/ansiblelint/rules/ComparisonToLiteralBoolRule.py @@ -2,11 +2,16 @@ # Copyright (c) 2018-2021, Ansible Project import re -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule from ansiblelint.utils import nested_items +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class ComparisonToLiteralBoolRule(AnsibleLintRule): id = 'literal-compare' @@ -21,7 +26,9 @@ class ComparisonToLiteralBoolRule(AnsibleLintRule): literal_bool_compare = re.compile("[=!]= ?(True|true|False|false)") - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: for k, v, _ in nested_items(task): if k == 'when': if isinstance(v, str): diff --git a/src/ansiblelint/rules/DeprecatedModuleRule.py b/src/ansiblelint/rules/DeprecatedModuleRule.py index 00adeff5c1..d4cece99ac 100644 --- a/src/ansiblelint/rules/DeprecatedModuleRule.py +++ b/src/ansiblelint/rules/DeprecatedModuleRule.py @@ -1,9 +1,14 @@ # Copyright (c) 2018, Ansible Project -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class DeprecatedModuleRule(AnsibleLintRule): id = 'deprecated-module' @@ -60,7 +65,9 @@ class DeprecatedModuleRule(AnsibleLintRule): 'include', ] - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: module = task["action"]["__ansible_module__"] if module in self._modules: message = '{0} {1}' diff --git a/src/ansiblelint/rules/EnvVarsInCommandRule.py b/src/ansiblelint/rules/EnvVarsInCommandRule.py index 8e511be2a5..dab1bd1039 100644 --- a/src/ansiblelint/rules/EnvVarsInCommandRule.py +++ b/src/ansiblelint/rules/EnvVarsInCommandRule.py @@ -18,11 +18,16 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule from ansiblelint.utils import FILENAME_KEY, LINE_NUMBER_KEY, get_first_cmd_arg +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class EnvVarsInCommandRule(AnsibleLintRule): id = 'inline-env-var' @@ -51,7 +56,9 @@ class EnvVarsInCommandRule(AnsibleLintRule): FILENAME_KEY, ] - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: if task["action"]["__ansible_module__"] in ['command']: first_cmd_arg = get_first_cmd_arg(task) if not first_cmd_arg: diff --git a/src/ansiblelint/rules/GitHasVersionRule.py b/src/ansiblelint/rules/GitHasVersionRule.py index e3578c898b..b80e75ee2e 100644 --- a/src/ansiblelint/rules/GitHasVersionRule.py +++ b/src/ansiblelint/rules/GitHasVersionRule.py @@ -18,10 +18,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class GitHasVersionRule(AnsibleLintRule): id = 'git-latest' @@ -34,7 +39,9 @@ class GitHasVersionRule(AnsibleLintRule): tags = ['idempotency'] version_added = 'historic' - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: return bool( task['action']['__ansible_module__'] == 'git' and task['action'].get('version', 'HEAD') == 'HEAD' diff --git a/src/ansiblelint/rules/MercurialHasRevisionRule.py b/src/ansiblelint/rules/MercurialHasRevisionRule.py index 67ce3812f9..8327c6b1a6 100644 --- a/src/ansiblelint/rules/MercurialHasRevisionRule.py +++ b/src/ansiblelint/rules/MercurialHasRevisionRule.py @@ -18,10 +18,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class MercurialHasRevisionRule(AnsibleLintRule): id = 'hg-latest' @@ -34,7 +39,9 @@ class MercurialHasRevisionRule(AnsibleLintRule): tags = ['idempotency'] version_added = 'historic' - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: return bool( task['action']['__ansible_module__'] == 'hg' and task['action'].get('revision', 'default') == 'default' diff --git a/src/ansiblelint/rules/MissingFilePermissionsRule.py b/src/ansiblelint/rules/MissingFilePermissionsRule.py index 9a8475bb24..b0674b638c 100644 --- a/src/ansiblelint/rules/MissingFilePermissionsRule.py +++ b/src/ansiblelint/rules/MissingFilePermissionsRule.py @@ -17,10 +17,16 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + + # Despite documentation mentioning 'preserve' only these modules support it: _modules_with_preserve = ( 'copy', @@ -60,7 +66,9 @@ class MissingFilePermissionsRule(AnsibleLintRule): 'lineinfile': False, } - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: module = task["action"]["__ansible_module__"] mode = task['action'].get('mode', None) diff --git a/src/ansiblelint/rules/NestedJinjaRule.py b/src/ansiblelint/rules/NestedJinjaRule.py index 73792ae00e..997fc23ce2 100644 --- a/src/ansiblelint/rules/NestedJinjaRule.py +++ b/src/ansiblelint/rules/NestedJinjaRule.py @@ -22,10 +22,15 @@ # THE SOFTWARE. import re -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class NestedJinjaRule(AnsibleLintRule): id = 'no-jinja-nesting' @@ -42,8 +47,9 @@ class NestedJinjaRule(AnsibleLintRule): pattern = re.compile(r"{{(?:[^{}]*)?[^'\"]{{") - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: - + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: command = "".join( str(value) # task properties are stored in the 'action' key diff --git a/src/ansiblelint/rules/NoFormattingInWhenRule.py b/src/ansiblelint/rules/NoFormattingInWhenRule.py index 18e4b7854e..20516d5ab7 100644 --- a/src/ansiblelint/rules/NoFormattingInWhenRule.py +++ b/src/ansiblelint/rules/NoFormattingInWhenRule.py @@ -3,6 +3,8 @@ from ansiblelint.rules import AnsibleLintRule if TYPE_CHECKING: + from typing import Optional + from ansiblelint.constants import odict from ansiblelint.errors import MatchError from ansiblelint.file_utils import Lintable @@ -31,7 +33,7 @@ def matchplay( if 'roles' not in data or data['roles'] is None: return errors for role in data['roles']: - if self.matchtask(role): + if self.matchtask(role, file=file): errors.append(self.create_matcherror(details=str({'when': role}))) if isinstance(data, list): for play_item in data: @@ -40,5 +42,7 @@ def matchplay( errors = errors + sub_errors return errors - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: return 'when' in task and not self._is_valid(task['when']) diff --git a/src/ansiblelint/rules/NoTabsRule.py b/src/ansiblelint/rules/NoTabsRule.py index df6c684f53..4dba350ea3 100644 --- a/src/ansiblelint/rules/NoTabsRule.py +++ b/src/ansiblelint/rules/NoTabsRule.py @@ -1,11 +1,16 @@ # Copyright (c) 2016, Will Thames and contributors # Copyright (c) 2018, Ansible Project import sys -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule from ansiblelint.utils import nested_items +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class NoTabsRule(AnsibleLintRule): id = 'no-tabs' @@ -21,7 +26,9 @@ class NoTabsRule(AnsibleLintRule): ("lineinfile", "line"), ] - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: for k, v, parent in nested_items(task): if isinstance(k, str) and '\t' in k: return True diff --git a/src/ansiblelint/rules/OctalPermissionsRule.py b/src/ansiblelint/rules/OctalPermissionsRule.py index 181b2b95d6..48a0d96f85 100644 --- a/src/ansiblelint/rules/OctalPermissionsRule.py +++ b/src/ansiblelint/rules/OctalPermissionsRule.py @@ -18,10 +18,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class OctalPermissionsRule(AnsibleLintRule): id = 'risky-octal' @@ -80,7 +85,9 @@ def is_invalid_permission(self, mode: int) -> bool: or group_more_generous_than_user ) - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: if task["action"]["__ansible_module__"] in self._modules: mode = task['action'].get('mode', None) diff --git a/src/ansiblelint/rules/PackageIsNotLatestRule.py b/src/ansiblelint/rules/PackageIsNotLatestRule.py index f911d73ed4..088ad8905d 100644 --- a/src/ansiblelint/rules/PackageIsNotLatestRule.py +++ b/src/ansiblelint/rules/PackageIsNotLatestRule.py @@ -18,10 +18,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class PackageIsNotLatestRule(AnsibleLintRule): id = 'package-latest' @@ -62,7 +67,9 @@ class PackageIsNotLatestRule(AnsibleLintRule): 'zypper', ] - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: return ( task['action']['__ansible_module__'] in self._package_managers and not task['action'].get('version') diff --git a/src/ansiblelint/rules/RoleRelativePath.py b/src/ansiblelint/rules/RoleRelativePath.py index 7996bfc106..1018d37f0d 100644 --- a/src/ansiblelint/rules/RoleRelativePath.py +++ b/src/ansiblelint/rules/RoleRelativePath.py @@ -1,10 +1,15 @@ # Copyright (c) 2016, Tsukinowa Inc. # Copyright (c) 2018, Ansible Project -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class RoleRelativePath(AnsibleLintRule): id = 'no-relative-paths' @@ -23,7 +28,9 @@ class RoleRelativePath(AnsibleLintRule): 'win_template': 'win_templates', } - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: module = task['action']['__ansible_module__'] if module not in self._module_to_path_folder: return False diff --git a/src/ansiblelint/rules/ShellWithoutPipefail.py b/src/ansiblelint/rules/ShellWithoutPipefail.py index 8895979287..9710154e7e 100644 --- a/src/ansiblelint/rules/ShellWithoutPipefail.py +++ b/src/ansiblelint/rules/ShellWithoutPipefail.py @@ -1,9 +1,14 @@ import re -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule from ansiblelint.utils import convert_to_boolean +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class ShellWithoutPipefail(AnsibleLintRule): id = 'risky-shell-pipe' @@ -23,7 +28,9 @@ class ShellWithoutPipefail(AnsibleLintRule): _pipefail_re = re.compile(r"^\s*set.*[+-][A-z]*o\s*pipefail", re.M) _pipe_re = re.compile(r"(? Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: if task["__ansible_action_type__"] != "task": return False diff --git a/src/ansiblelint/rules/TaskHasNameRule.py b/src/ansiblelint/rules/TaskHasNameRule.py index a26a76d41a..e7ef87d405 100644 --- a/src/ansiblelint/rules/TaskHasNameRule.py +++ b/src/ansiblelint/rules/TaskHasNameRule.py @@ -18,10 +18,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class TaskHasNameRule(AnsibleLintRule): id = 'unnamed-task' @@ -34,5 +39,7 @@ class TaskHasNameRule(AnsibleLintRule): tags = ['idiom'] version_added = 'historic' - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: return not task.get('name') diff --git a/src/ansiblelint/rules/TaskNoLocalAction.py b/src/ansiblelint/rules/TaskNoLocalAction.py index 04afaa13ad..e07967027f 100644 --- a/src/ansiblelint/rules/TaskNoLocalAction.py +++ b/src/ansiblelint/rules/TaskNoLocalAction.py @@ -1,6 +1,5 @@ # Copyright (c) 2016, Tsukinowa Inc. # Copyright (c) 2018, Ansible Project - from ansiblelint.rules import AnsibleLintRule diff --git a/src/ansiblelint/rules/UseCommandInsteadOfShellRule.py b/src/ansiblelint/rules/UseCommandInsteadOfShellRule.py index 283b6fde0d..0d18d3bee3 100644 --- a/src/ansiblelint/rules/UseCommandInsteadOfShellRule.py +++ b/src/ansiblelint/rules/UseCommandInsteadOfShellRule.py @@ -18,10 +18,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class UseCommandInsteadOfShellRule(AnsibleLintRule): id = 'command-instead-of-shell' @@ -35,7 +40,9 @@ class UseCommandInsteadOfShellRule(AnsibleLintRule): tags = ['command-shell', 'idiom'] version_added = 'historic' - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: # Use unjinja so that we don't match on jinja filters # rather than pipes if task["action"]["__ansible_module__"] == 'shell': diff --git a/src/ansiblelint/rules/UseHandlerRatherThanWhenChangedRule.py b/src/ansiblelint/rules/UseHandlerRatherThanWhenChangedRule.py index ae564aafd1..3f15564849 100644 --- a/src/ansiblelint/rules/UseHandlerRatherThanWhenChangedRule.py +++ b/src/ansiblelint/rules/UseHandlerRatherThanWhenChangedRule.py @@ -19,8 +19,9 @@ # THE SOFTWARE. import sys -from typing import Any, Dict, Union +from typing import Any, Dict, Optional, Union +from ansiblelint.file_utils import Lintable from ansiblelint.rules import AnsibleLintRule @@ -52,7 +53,9 @@ class UseHandlerRatherThanWhenChangedRule(AnsibleLintRule): tags = ['idiom'] version_added = 'historic' - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: Optional[Lintable] = None + ) -> Union[bool, str]: if task["__ansible_action_type__"] != 'task': return False @@ -68,7 +71,6 @@ def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: if 'pytest' in sys.modules: - from ansiblelint.file_utils import Lintable from ansiblelint.rules import RulesCollection from ansiblelint.runner import Runner diff --git a/src/ansiblelint/rules/UsingBareVariablesIsDeprecatedRule.py b/src/ansiblelint/rules/UsingBareVariablesIsDeprecatedRule.py index e7d09e34c7..9c8e18e069 100644 --- a/src/ansiblelint/rules/UsingBareVariablesIsDeprecatedRule.py +++ b/src/ansiblelint/rules/UsingBareVariablesIsDeprecatedRule.py @@ -20,10 +20,15 @@ import os import re -from typing import Any, Dict, Union +from typing import TYPE_CHECKING, Any, Dict, Union from ansiblelint.rules import AnsibleLintRule +if TYPE_CHECKING: + from typing import Optional + + from ansiblelint.file_utils import Lintable + class UsingBareVariablesIsDeprecatedRule(AnsibleLintRule): id = 'deprecated-bare-vars' @@ -40,7 +45,9 @@ class UsingBareVariablesIsDeprecatedRule(AnsibleLintRule): _jinja = re.compile(r"{{.*}}", re.DOTALL) _glob = re.compile('[][*?]') - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: 'Optional[Lintable]' = None + ) -> Union[bool, str]: loop_type = next((key for key in task if key.startswith("with_")), None) if loop_type: if loop_type in [ diff --git a/src/ansiblelint/rules/VariableHasSpacesRule.py b/src/ansiblelint/rules/VariableHasSpacesRule.py index f424bd0b58..e1af823172 100644 --- a/src/ansiblelint/rules/VariableHasSpacesRule.py +++ b/src/ansiblelint/rules/VariableHasSpacesRule.py @@ -3,8 +3,9 @@ import re import sys -from typing import Any, Dict, Union +from typing import Any, Dict, Optional, Union +from ansiblelint.file_utils import Lintable from ansiblelint.rules import AnsibleLintRule from ansiblelint.utils import nested_items @@ -21,7 +22,9 @@ class VariableHasSpacesRule(AnsibleLintRule): bracket_regex = re.compile(r"{{[^{\n' -]|[^ '\n}-]}}", re.MULTILINE | re.DOTALL) exclude_json_re = re.compile(r"[^{]{'\w+': ?[^{]{.*?}}") - def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: + def matchtask( + self, task: Dict[str, Any], file: Optional[Lintable] = None + ) -> Union[bool, str]: for k, v, _ in nested_items(task): if isinstance(v, str): cleaned = self.exclude_json_re.sub("", v) @@ -32,7 +35,6 @@ def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]: if 'pytest' in sys.modules: - from ansiblelint.file_utils import Lintable from ansiblelint.rules import RulesCollection from ansiblelint.runner import Runner diff --git a/src/ansiblelint/rules/__init__.py b/src/ansiblelint/rules/__init__.py index 0da25e4ef0..cf55b1e719 100644 --- a/src/ansiblelint/rules/__init__.py +++ b/src/ansiblelint/rules/__init__.py @@ -114,7 +114,7 @@ def matchtasks(self, file: Lintable) -> List[MatchError]: if 'action' not in task: continue - result = self.matchtask(task) + result = self.matchtask(task, file=file) if not result: continue