From f92280fd6b94bd581535e70145997a4ed32293c1 Mon Sep 17 00:00:00 2001 From: Kate Case Date: Mon, 11 Sep 2023 16:18:03 -0400 Subject: [PATCH] Try to change the line number associated with the yaml read also clean up some bad ideas --- src/ansiblelint/file_utils.py | 35 ++++++++++++++++------------------- src/ansiblelint/utils.py | 3 ++- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/ansiblelint/file_utils.py b/src/ansiblelint/file_utils.py index c8ab17c1074..cdd70af7f0e 100644 --- a/src/ansiblelint/file_utils.py +++ b/src/ansiblelint/file_utils.py @@ -1,6 +1,7 @@ """Utility functions related to file operations.""" from __future__ import annotations +import ast import copy import logging import os @@ -12,9 +13,9 @@ from typing import TYPE_CHECKING, Any, cast import pathspec -from ansible.parsing.plugin_docs import read_docstring import wcmatch.pathlib import wcmatch.wcmatch +from ansible.parsing.plugin_docs import read_docstring from yaml.error import YAMLError from ansiblelint.config import BASE_KINDS, Options, options @@ -208,7 +209,7 @@ def __init__( name = normpath_path(name) # we need to be sure that we expanduser() because otherwise a simple # test like .path.exists() will return unexpected results. - self.path = self._original_path = name.expanduser() + self.path = name.expanduser() # Filename is effective file on disk, for stdin is a namedtempfile self.name = self.filename = str(name) @@ -269,8 +270,8 @@ def __init__( self.path = Path(self.file.name) self.base_kind = "text/yaml" - def __del__(self) -> None: + """Clean up temporary files when the instance is cleaned up.""" if hasattr(self, "file"): self.file.close() @@ -393,10 +394,18 @@ def __repr__(self) -> str: return f"{self.name} ({self.kind})" def parse_examples_from_plugin(self) -> str: - """Parse yaml inside plugin EXAMPLES string as ansible.utils.parse_yaml but with linenumbers. + """Parse yaml inside plugin EXAMPLES string. - The line numbers are stored in each node's LINE_NUMBER_KEY key. + Store a line number offset to realign returned line numbers later """ + parsed = ast.parse(self.content) + for child in parsed.body: + if isinstance(child, ast.Assign): + label = child.targets[0] + if isinstance(label, ast.Name) and label.id == "EXAMPLES": + self._line_offset = child.lineno + break + docs = read_docstring(str(self.path)) examples = docs["plainexamples"] return examples or "" @@ -414,7 +423,8 @@ def data(self) -> Any: parse_yaml_linenumbers, ) - self.state = parse_yaml_linenumbers(self) + offset = getattr(self, "_line_offset", 0) + self.state = parse_yaml_linenumbers(self, line_number_offset=offset) # now that _data is not empty, we can try guessing if playbook or rulebook # it has to be done before append_skipped_rules() call as it's relying # on self.kind. @@ -426,19 +436,6 @@ def data(self) -> Any: from ansiblelint.skip_utils import append_skipped_rules self.state = append_skipped_rules(self.state, self) - elif self.kind == "plugin": - from ansiblelint.utils import ( # pylint: disable=import-outside-toplevel - parse_plugin, - ) - - self._data = parse_plugin(self) - if self._data: - # Lazy import to avoid delays and cyclic-imports - if "append_skipped_rules" not in globals(): - # pylint: disable=import-outside-toplevel - from ansiblelint.skip_utils import append_skipped_rules - - self._data = append_skipped_rules(self._data, self) else: logging.debug( diff --git a/src/ansiblelint/utils.py b/src/ansiblelint/utils.py index 85e91177e3b..9519c68bded 100644 --- a/src/ansiblelint/utils.py +++ b/src/ansiblelint/utils.py @@ -852,6 +852,7 @@ def get_action_tasks(data: AnsibleBaseYAMLObject, file: Lintable) -> list[Any]: @cache def parse_yaml_linenumbers( lintable: Lintable, + line_number_offset: int = 0, ) -> AnsibleBaseYAMLObject: """Parse yaml as ansible.utils.parse_yaml but with linenumbers. @@ -866,7 +867,7 @@ def compose_node(parent: yaml.nodes.Node, index: int) -> yaml.nodes.Node: if not isinstance(node, yaml.nodes.Node): msg = "Unexpected yaml data." raise RuntimeError(msg) - node.__line__ = line + 1 # type: ignore[attr-defined] + node.__line__ = line + (line_number_offset or 1) # type: ignore[attr-defined] return node def construct_mapping(