diff options
Diffstat (limited to 'src/ansiblelint/file_utils.py')
-rw-r--r-- | src/ansiblelint/file_utils.py | 54 |
1 files changed, 46 insertions, 8 deletions
diff --git a/src/ansiblelint/file_utils.py b/src/ansiblelint/file_utils.py index 15c92d2..04ce3cd 100644 --- a/src/ansiblelint/file_utils.py +++ b/src/ansiblelint/file_utils.py @@ -1,4 +1,5 @@ """Utility functions related to file operations.""" + from __future__ import annotations import copy @@ -16,12 +17,15 @@ import wcmatch.pathlib import wcmatch.wcmatch from yaml.error import YAMLError -from ansiblelint.config import BASE_KINDS, Options, options +from ansiblelint.app import get_app +from ansiblelint.config import ANSIBLE_OWNED_KINDS, BASE_KINDS, Options, options from ansiblelint.constants import CONFIG_FILENAMES, FileType, States if TYPE_CHECKING: from collections.abc import Iterator, Sequence + from ansiblelint.errors import MatchError + _logger = logging.getLogger(__package__) @@ -69,9 +73,9 @@ def is_relative_to(path: Path, *other: Any) -> bool: """Return True if the path is relative to another path or False.""" try: path.resolve().absolute().relative_to(*other) - return True except ValueError: return False + return True def normpath_path(path: str | Path) -> Path: @@ -197,6 +201,10 @@ class Lintable: self.exc: Exception | None = None # Stores data loading exceptions self.parent = parent self.explicit = False # Indicates if the file was explicitly provided or was indirectly included. + self.line_offset = ( + 0 # Amount to offset line numbers by to get accurate position + ) + self.matches: list[MatchError] = [] if isinstance(name, str): name = Path(name) @@ -219,7 +227,12 @@ class Lintable: parts = self.path.parent.parts if "roles" in parts: role = self.path - while role.parent.name != "roles" and role.name: + roles_path = get_app(cached=True).runtime.config.default_roles_path + while ( + str(role.parent.absolute()) not in roles_path + and role.parent.name != "roles" + and role.name + ): role = role.parent if role.exists(): self.role = role.name @@ -252,7 +265,12 @@ class Lintable: self.parent = _guess_parent(self) if self.kind == "yaml": - _ = self.data # pylint: disable=pointless-statement + _ = self.data + + def __del__(self) -> None: + """Clean up temporary files when the instance is cleaned up.""" + if hasattr(self, "file"): + self.file.close() def _guess_kind(self) -> None: if self.kind == "yaml": @@ -350,10 +368,16 @@ class Lintable: lintable.write(force=True) """ - if not force and not self.updated: + dump_filename = self.path.expanduser().resolve() + if os.environ.get("ANSIBLE_LINT_WRITE_TMP", "0") == "1": + dump_filename = dump_filename.with_suffix( + f".tmp{dump_filename.suffix}", + ) + elif not force and not self.updated: # No changes to write. return - self.path.expanduser().resolve().write_text( + + dump_filename.write_text( self._content or "", encoding="utf-8", ) @@ -372,6 +396,16 @@ class Lintable: """Return user friendly representation of a lintable.""" return f"{self.name} ({self.kind})" + def is_owned_by_ansible(self) -> bool: + """Return true for YAML files that are managed by Ansible.""" + return self.kind in ANSIBLE_OWNED_KINDS + + def failed(self) -> bool: + """Return true if we already found syntax-check errors on this file.""" + return any( + match.rule.id in ("syntax-check", "load-failure") for match in self.matches + ) + @property def data(self) -> Any: """Return loaded data representation for current file, if possible.""" @@ -396,7 +430,11 @@ class Lintable: # pylint: disable=import-outside-toplevel from ansiblelint.skip_utils import append_skipped_rules - self.state = append_skipped_rules(self.state, self) + # pylint: disable=possibly-used-before-assignment + self.state = append_skipped_rules( + self.state, + self, + ) else: logging.debug( "data set to None for %s due to being '%s' (%s) kind.", @@ -513,7 +551,7 @@ def expand_dirs_in_lintables(lintables: set[Lintable]) -> None: for item in copy.copy(lintables): if item.path.is_dir(): for filename in all_files: - if filename.startswith(str(item.path)): + if filename.startswith((str(item.path), str(item.path.absolute()))): lintables.add(Lintable(filename)) |