From 3c4d6f0e752ede4616de386f9cae411ccda1d8ef Mon Sep 17 00:00:00 2001 From: shatakshiiii Date: Mon, 3 Jun 2024 19:41:27 +0530 Subject: [PATCH] Utility function to expand_path --- src/ansible_navigator/actions/lint.py | 4 +- src/ansible_navigator/actions/run.py | 42 +++++++------------ .../configuration_subsystem/definitions.py | 6 +-- .../navigator_configuration.py | 4 +- .../navigator_post_processor.py | 22 +++++----- src/ansible_navigator/utils/functions.py | 11 +++++ .../test_settings_effective.py | 4 +- 7 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/ansible_navigator/actions/lint.py b/src/ansible_navigator/actions/lint.py index 0268076b34..639ca87078 100644 --- a/src/ansible_navigator/actions/lint.py +++ b/src/ansible_navigator/actions/lint.py @@ -40,7 +40,7 @@ from ansible_navigator.ui_framework import error_notification from ansible_navigator.ui_framework import nonblocking_notification from ansible_navigator.ui_framework import success_notification -from ansible_navigator.utils.functions import abs_user_path +from ansible_navigator.utils.functions import expand_path from ansible_navigator.utils.functions import remove_ansi from ansible_navigator.utils.functions import time_stamp_for_file @@ -160,7 +160,7 @@ def massage_issue(issue: dict[Any, Any]) -> dict[Any, Any]: massaged["__message"] = issue["check_name"].split("]")[1].strip() else: massaged["__message"] = issue["description"] - massaged["__path"] = abs_user_path(issue["location"]["path"]) + massaged["__path"] = expand_path(issue["location"]["path"]) if isinstance(issue["location"]["lines"]["begin"], Mapping): massaged["__line"] = issue["location"]["lines"]["begin"]["line"] else: diff --git a/src/ansible_navigator/actions/run.py b/src/ansible_navigator/actions/run.py index a0abd29015..d4a7bf961b 100644 --- a/src/ansible_navigator/actions/run.py +++ b/src/ansible_navigator/actions/run.py @@ -11,49 +11,39 @@ import shutil import time import uuid - from math import floor from operator import itemgetter from pathlib import Path from queue import Queue -from typing import TYPE_CHECKING -from typing import Any +from typing import TYPE_CHECKING, Any, Union from ansible_navigator.action_base import ActionBase from ansible_navigator.action_defs import RunStdoutReturn -from ansible_navigator.configuration_subsystem import to_effective -from ansible_navigator.configuration_subsystem import to_sources -from ansible_navigator.content_defs import ContentView -from ansible_navigator.content_defs import SerializationFormat +from ansible_navigator.configuration_subsystem import to_effective, to_sources +from ansible_navigator.content_defs import ContentView, SerializationFormat from ansible_navigator.runner import CommandAsync from ansible_navigator.steps import Step -from ansible_navigator.ui_framework import CursesLine -from ansible_navigator.ui_framework import CursesLinePart -from ansible_navigator.ui_framework import CursesLines -from ansible_navigator.ui_framework import Interaction -from ansible_navigator.ui_framework import dict_to_form -from ansible_navigator.ui_framework import form_to_dict -from ansible_navigator.ui_framework import nonblocking_notification -from ansible_navigator.ui_framework import warning_notification -from ansible_navigator.utils.functions import abs_user_path -from ansible_navigator.utils.functions import check_playbook_type -from ansible_navigator.utils.functions import human_time -from ansible_navigator.utils.functions import is_jinja -from ansible_navigator.utils.functions import now_iso -from ansible_navigator.utils.functions import remove_ansi -from ansible_navigator.utils.functions import round_half_up +from ansible_navigator.ui_framework import (CursesLine, CursesLinePart, + CursesLines, Interaction, + dict_to_form, form_to_dict, + nonblocking_notification, + warning_notification) +from ansible_navigator.utils.functions import (check_playbook_type, + expand_path, human_time, + is_jinja, now_iso, remove_ansi, + round_half_up) from ansible_navigator.utils.serialize import serialize_write_file from . import _actions as actions from . import run_action from .stdout import Action as stdout_action - if TYPE_CHECKING: from collections.abc import Callable from ansible_navigator.app_public import AppPublic - from ansible_navigator.configuration_subsystem.definitions import ApplicationConfiguration + from ansible_navigator.configuration_subsystem.definitions import \ + ApplicationConfiguration RESULT_TO_COLOR = [ @@ -877,7 +867,7 @@ def write_artifact(self, filename: str | None = None) -> None: """Write the artifact. :param filename: The file to write to - :type filename: str + :type filename: Union[str, None] """ if filename or self._args.playbook_artifact_enable is True: status, status_color = self._get_status() @@ -892,7 +882,7 @@ def write_artifact(self, filename: str | None = None) -> None: time_stamp=now_iso(self._args.time_zone), ) self._logger.debug("Formatted artifact file name set to %s", filename) - filename = abs_user_path(filename) + filename = expand_path(filename) # type: ignore[assignment] self._logger.debug("Resolved artifact file name set to %s", filename) try: diff --git a/src/ansible_navigator/configuration_subsystem/definitions.py b/src/ansible_navigator/configuration_subsystem/definitions.py index 87f7fa3e8a..d6cd9944ea 100644 --- a/src/ansible_navigator/configuration_subsystem/definitions.py +++ b/src/ansible_navigator/configuration_subsystem/definitions.py @@ -15,7 +15,7 @@ from typing import NewType from typing import TypeVar -from ansible_navigator.utils.functions import abs_user_path +from ansible_navigator.utils.functions import expand_path from ansible_navigator.utils.functions import oxfordcomma @@ -396,8 +396,8 @@ def __post_init__(self, options_string: str) -> None: # Resolve the source and destination # frozen, cannot use simple assignment to initialize fields, and must use: - object.__setattr__(self, "fs_source", abs_user_path(self.fs_source)) - object.__setattr__(self, "fs_destination", abs_user_path(self.fs_destination)) + object.__setattr__(self, "fs_source", expand_path(self.fs_source)) + object.__setattr__(self, "fs_destination", expand_path(self.fs_destination)) # Source must exist if not Path(self.fs_source).exists(): diff --git a/src/ansible_navigator/configuration_subsystem/navigator_configuration.py b/src/ansible_navigator/configuration_subsystem/navigator_configuration.py index b4891d1026..d544a5add0 100644 --- a/src/ansible_navigator/configuration_subsystem/navigator_configuration.py +++ b/src/ansible_navigator/configuration_subsystem/navigator_configuration.py @@ -11,7 +11,7 @@ from ansible_navigator.utils.definitions import ExitMessage from ansible_navigator.utils.definitions import LogMessage -from ansible_navigator.utils.functions import abs_user_path +from ansible_navigator.utils.functions import expand_path from ansible_navigator.utils.functions import generate_cache_path from ansible_navigator.utils.functions import oxfordcomma from ansible_navigator.utils.packaged_data import ImageEntry @@ -550,7 +550,7 @@ class Internals: short_description="Specify the full path for the ansible-navigator log file", settings_file_path_override="logging.file", value=SettingsEntryValue( - default=abs_user_path("./ansible-navigator.log"), + default=expand_path("./ansible-navigator.log"), schema_default="./ansible-navigator.log", ), version_added="v1.0", diff --git a/src/ansible_navigator/configuration_subsystem/navigator_post_processor.py b/src/ansible_navigator/configuration_subsystem/navigator_post_processor.py index 7de7ca2bd9..50214428d8 100644 --- a/src/ansible_navigator/configuration_subsystem/navigator_post_processor.py +++ b/src/ansible_navigator/configuration_subsystem/navigator_post_processor.py @@ -23,9 +23,9 @@ from ansible_navigator.utils.definitions import ExitMessage from ansible_navigator.utils.definitions import ExitPrefix from ansible_navigator.utils.definitions import LogMessage -from ansible_navigator.utils.functions import abs_user_path from ansible_navigator.utils.functions import check_for_ansible from ansible_navigator.utils.functions import check_playbook_type +from ansible_navigator.utils.functions import expand_path from ansible_navigator.utils.functions import flatten_list from ansible_navigator.utils.functions import oxfordcomma from ansible_navigator.utils.functions import str2bool @@ -122,7 +122,7 @@ def ansible_runner_artifact_dir( messages: list[LogMessage] = [] exit_messages: list[ExitMessage] = [] if entry.value.current is not C.NOT_SET: - entry.value.current = abs_user_path(entry.value.current) + entry.value.current = expand_path(entry.value.current) return messages, exit_messages @staticmethod @@ -186,7 +186,7 @@ def collection_doc_cache_path( """ messages: list[LogMessage] = [] exit_messages: list[ExitMessage] = [] - entry.value.current = abs_user_path(entry.value.current) + entry.value.current = expand_path(entry.value.current) return messages, exit_messages @staticmethod @@ -593,7 +593,7 @@ def inventory(entry: SettingsEntry, config: ApplicationConfiguration) -> PostPro if isinstance(ansible_cfg, dict): ansible_cfg_entry = ansible_cfg.get("defaults", {}).get("inventory") if isinstance(ansible_cfg_entry, str): - entry.value.current = [abs_user_path(i) for i in ansible_cfg_entry.split(",")] + entry.value.current = [expand_path(i) for i in ansible_cfg_entry.split(",")] entry.value.source = C.ANSIBLE_CFG else: # Use the specified @@ -605,7 +605,7 @@ def inventory(entry: SettingsEntry, config: ApplicationConfiguration) -> PostPro entry.value.current.append(inv_entry) else: # file path - entry.value.current.append(abs_user_path(inv_entry)) + entry.value.current.append(expand_path(inv_entry)) # Something may be required app_match = config.app == "inventory" @@ -692,11 +692,11 @@ def lintables( if isinstance(entry.value.current, str) and config.app == "lint": entry_name = entry.settings_file_path(prefix="") entry_source = entry.value.source - source = abs_user_path(entry.value.current) + source = expand_path(entry.value.current) try: mount = VolumeMount( - fs_source=source, - fs_destination=source, + fs_source=str(source), + fs_destination=str(source), settings_entry=entry_name, source=entry_source, options_string="", @@ -730,7 +730,7 @@ def log_file(entry: SettingsEntry, config: ApplicationConfiguration) -> PostProc """ messages: list[LogMessage] = [] exit_messages: list[ExitMessage] = [] - entry.value.current = abs_user_path(entry.value.current) + entry.value.current = expand_path(entry.value.current) try: os.makedirs(os.path.dirname(entry.value.current), exist_ok=True) Path(entry.value.current).touch() @@ -940,7 +940,7 @@ def playbook(entry: SettingsEntry, config: ApplicationConfiguration) -> PostProc entry.value.current, str, ): - entry.value.current = abs_user_path(entry.value.current) + entry.value.current = expand_path(entry.value.current) return messages, exit_messages @_post_processor @@ -1003,7 +1003,7 @@ def playbook_artifact_replay( return messages, exit_messages if isinstance(entry.value.current, str): - entry.value.current = abs_user_path(entry.value.current) + entry.value.current = expand_path(entry.value.current) if config.app == "replay" and not os.path.isfile(entry.value.current): exit_msg = f"The specified playbook artifact could not be found: {entry.value.current}" diff --git a/src/ansible_navigator/utils/functions.py b/src/ansible_navigator/utils/functions.py index 16c1e63855..d7ac9f1eb0 100644 --- a/src/ansible_navigator/utils/functions.py +++ b/src/ansible_navigator/utils/functions.py @@ -60,6 +60,17 @@ def abs_user_path(file_path: str) -> str: return os.path.abspath(os.path.expanduser(os.path.expandvars(file_path))) +def expand_path(path: str) -> Path: + """Resolve a path. + + :param path: The file path to resolve + :returns: Resolved file path + """ + _path = Path(os.path.expandvars(path)) + _path = _path.expanduser() + return _path.resolve() + + def check_for_ansible() -> tuple[list[LogMessage], list[ExitMessage]]: """Check for the ansible-playbook command, runner will need it. diff --git a/tests/unit/configuration_subsystem/test_settings_effective.py b/tests/unit/configuration_subsystem/test_settings_effective.py index 3ba8db695b..d6df8d4f85 100644 --- a/tests/unit/configuration_subsystem/test_settings_effective.py +++ b/tests/unit/configuration_subsystem/test_settings_effective.py @@ -22,7 +22,7 @@ from ansible_navigator.configuration_subsystem import SettingsSchemaType from ansible_navigator.configuration_subsystem import to_effective from ansible_navigator.initialization import parse_and_update -from ansible_navigator.utils.functions import abs_user_path +from ansible_navigator.utils.functions import expand_path from ansible_navigator.utils.json_schema import validate @@ -138,4 +138,4 @@ def test_settings_full( else: assert isinstance(effective_value, str) assert isinstance(sample_value, str) - assert abs_user_path(effective_value) == abs_user_path(sample_value) + assert expand_path(effective_value) == expand_path(sample_value)