diff --git a/pyproject.toml b/pyproject.toml index 6ef2f337c..17ea371c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,9 +72,16 @@ color_output = true error_summary = true # disallow_untyped_calls = true # disallow_untyped_defs = true -# disallow_any_generics = true +disallow_any_generics = true incremental = false +[[tool.mypy.overrides]] +# https://github.com/ansible/ansible-runner/issues/1340 +module = [ + "ansible_runner" +] +ignore_missing_imports = true + [tool.pydoclint] allow-init-docstring = true arg-type-hints-in-docstring = false diff --git a/src/ansible_navigator/command_runner/command_runner.py b/src/ansible_navigator/command_runner/command_runner.py index e52956c33..db9746667 100644 --- a/src/ansible_navigator/command_runner/command_runner.py +++ b/src/ansible_navigator/command_runner/command_runner.py @@ -9,6 +9,7 @@ from dataclasses import dataclass from dataclasses import field from queue import Queue +from typing import Any from ansible_navigator.utils.definitions import LogMessage @@ -27,11 +28,11 @@ class Command: # pylint: disable=too-many-instance-attributes identity: str command: str - post_process: Callable + post_process: Callable[..., Any] return_code: int = 0 stdout: str = "" stderr: str = "" - details: list = field(default_factory=list) + details: list[Any] = field(default_factory=list) errors: str = "" messages: list[LogMessage] = field(default_factory=list) @@ -73,7 +74,9 @@ def run_command(command: Command) -> None: command.stderr = str(exc.stderr) -def worker(pending_queue: multiprocessing.Queue, completed_queue: multiprocessing.Queue) -> None: +def worker( + pending_queue: multiprocessing.Queue[Any], completed_queue: multiprocessing.Queue[Any] +) -> None: """Read pending, run, post process, and place in completed. :param pending_queue: All pending commands diff --git a/src/ansible_navigator/configuration_subsystem/definitions.py b/src/ansible_navigator/configuration_subsystem/definitions.py index 4c8006121..da7399d52 100644 --- a/src/ansible_navigator/configuration_subsystem/definitions.py +++ b/src/ansible_navigator/configuration_subsystem/definitions.py @@ -467,10 +467,12 @@ class PaeChangeRequest: # and some common ones # A type used for the settings as a dictionary -SettingsFileType = NewType("SettingsFileType", dict[str, bool | dict | int | str | list]) +SettingsFileType = NewType( + "SettingsFileType", dict[str, bool | dict[Any, Any] | int | str | list[Any]] +) # A type used to describe a schema file for the settings SettingsSchemaType = NewType( "SettingsSchemaType", - dict[str, dict[str, bool | dict | int | str | list]], + dict[str, dict[str, bool | dict[Any, Any] | int | str | list[Any]]], ) diff --git a/src/ansible_navigator/configuration_subsystem/navigator_post_processor.py b/src/ansible_navigator/configuration_subsystem/navigator_post_processor.py index fa094c1e7..b19aa598d 100644 --- a/src/ansible_navigator/configuration_subsystem/navigator_post_processor.py +++ b/src/ansible_navigator/configuration_subsystem/navigator_post_processor.py @@ -74,7 +74,7 @@ class NavigatorPostProcessor: # pylint:disable=too-many-public-methods """Application post processor.""" - def __init__(self): + def __init__(self) -> None: """Initialize the post processor.""" #: Volume mounts accumulated from post processing various config entries. #: These get processed towards the end, in the (delayed) diff --git a/src/ansible_navigator/configuration_subsystem/utils.py b/src/ansible_navigator/configuration_subsystem/utils.py index 5c595d5d5..15bda2f28 100644 --- a/src/ansible_navigator/configuration_subsystem/utils.py +++ b/src/ansible_navigator/configuration_subsystem/utils.py @@ -22,7 +22,7 @@ def create_settings_file_sample( settings_path: str, - placeholder: bool | int | str | dict | list = "", + placeholder: bool | int | str | dict[Any, Any] | list[Any] = "", ) -> SettingsFileType: """Generate a settings file sample. diff --git a/src/ansible_navigator/content_defs.py b/src/ansible_navigator/content_defs.py index e53f0b895..9aae46c74 100644 --- a/src/ansible_navigator/content_defs.py +++ b/src/ansible_navigator/content_defs.py @@ -57,7 +57,7 @@ def asdict( self, content_view: ContentView, serialization_format: SerializationFormat, - ) -> DictType: + ) -> DictType[Any]: """Convert thy self into a dictionary. :param content_view: The content view @@ -77,28 +77,28 @@ def asdict( return asdict(self) return dump_self_as_dict() - def serialize_json_full(self) -> DictType: + def serialize_json_full(self) -> DictType[Any]: """Provide dictionary for ``JSON`` with all attributes. :returns: A dictionary created from self """ return asdict(self) - def serialize_json_normal(self) -> DictType: + def serialize_json_normal(self) -> DictType[Any]: """Provide dictionary for ``JSON`` with curated attributes. :returns: A dictionary created from self """ return asdict(self) - def serialize_yaml_full(self) -> DictType: + def serialize_yaml_full(self) -> DictType[Any]: """Provide dictionary for ``YAML`` with all attributes. :returns: A dictionary created from self """ return asdict(self) - def serialize_yaml_normal(self) -> DictType: + def serialize_yaml_normal(self) -> DictType[Any]: """Provide dictionary for ``JSON`` with curated attributes. :returns: A dictionary created from self @@ -131,8 +131,8 @@ def items(self): return asdict(self).items() -ContentTypeSingle = bool | float | int | str | dict[str, Any] | ContentBase -ContentTypeSequence = list[Any] | Sequence[ContentBase] +ContentTypeSingle = bool | float | int | str | dict[str, Any] | ContentBase[Any] +ContentTypeSequence = list[Any] | Sequence[ContentBase[Any]] ContentType = ContentTypeSingle | ContentTypeSequence diff --git a/src/ansible_navigator/data/catalog_collections.py b/src/ansible_navigator/data/catalog_collections.py index fa7ecb98a..739d6359f 100644 --- a/src/ansible_navigator/data/catalog_collections.py +++ b/src/ansible_navigator/data/catalog_collections.py @@ -58,11 +58,11 @@ def __init__(self, directories: list[Path]): :param directories: A list of directories that may contain collections """ self._directories: list[Path] = directories - self._collections: OrderedDict[str, dict] = OrderedDict() + self._collections: OrderedDict[str, dict[Any, Any]] = OrderedDict() self._errors: list[dict[str, str]] = [] self._messages: list[str] = [] - def _catalog_plugins(self, collection: dict) -> None: + def _catalog_plugins(self, collection: dict[Any, Any]) -> None: """Catalog the plugins within a collection. :param collection: Details describing the collection @@ -202,7 +202,7 @@ def _catalog_roles(self, collection: dict[str, Any]) -> None: collection["roles"].append(role) @staticmethod - def _generate_checksum(file_path: Path, relative_path: Path) -> dict: + def _generate_checksum(file_path: Path, relative_path: Path) -> dict[str, Any]: """Generate a standard checksum for a file. :param file_path: The path to the file to generate a checksum for @@ -226,8 +226,8 @@ def _process_plugin_dir( self, plugin_type: str, filenames: Generator[Path, None, None], - file_checksums: dict[str, dict], - collection: dict, + file_checksums: dict[str, dict[Any, Any]], + collection: dict[Any, Any], ) -> None: """Process each plugin within one plugin directory. @@ -321,7 +321,7 @@ def _find_shadows(self) -> None: i_collection["path"], ) - def process_directories(self) -> tuple[dict, list]: + def process_directories(self) -> tuple[dict[Any, Any], list[dict[str, str]]]: """Process each parent directory. :returns: All collections found and any errors @@ -339,7 +339,7 @@ def process_directories(self) -> tuple[dict, list]: def add_pseudo_builtin(self) -> None: """Add the pseudo builtin collection.""" - collection: dict[str, str | list | dict] = {} + collection: dict[str, str | list[str] | dict[Any, Any]] = {} collection["known_as"] = "ansible.builtin" collection["plugin_checksums"] = {} collection["path"] = str(Path(plugins.__file__).parents[1]) @@ -351,7 +351,9 @@ def add_pseudo_builtin(self) -> None: self._messages.append(msg) -def worker(pending_queue: multiprocessing.Queue, completed_queue: multiprocessing.Queue) -> None: +def worker( + pending_queue: multiprocessing.Queue[Any], completed_queue: multiprocessing.Queue[Any] +) -> None: """Extract the documentation from a plugin, place in completed queue. :param pending_queue: A queue with plugins to process @@ -402,7 +404,9 @@ def worker(pending_queue: multiprocessing.Queue, completed_queue: multiprocessin completed_queue.put(("error", (checksum, plugin_path, err_message))) -def identify_missing(collections: dict, collection_cache: KeyValueStore) -> tuple[set, list, int]: +def identify_missing( + collections: dict[Any, Any], collection_cache: KeyValueStore +) -> tuple[set[Any], list[Any], int]: """Identify plugins missing from the cache. :param collections: All plugins found across all collections @@ -466,7 +470,7 @@ def parse_args() -> tuple[argparse.Namespace, list[Path]]: return parsed_args, resolved -def retrieve_collections_paths() -> dict: +def retrieve_collections_paths() -> dict[Any, Any]: """Retrieve the currently set collection paths. :returns: Errors or the configured collection directories @@ -488,9 +492,9 @@ def retrieve_collections_paths() -> dict: def retrieve_docs( collection_cache: KeyValueStore, - errors: list, - missing: list, - stats: dict, + errors: list[dict[str, str]], + missing: list[str], + stats: dict[Any, Any], ) -> None: # pylint: disable=too-many-locals """Extract the docs from the plugins. @@ -528,7 +532,7 @@ def retrieve_docs( stats["cache_added_errors"] += 1 -def run_command(cmd: list) -> dict: +def run_command(cmd: list[str]) -> dict[str, str]: """Run a command using subprocess. :param cmd: The command to run, split @@ -547,7 +551,7 @@ def run_command(cmd: list) -> dict: return {"error": str(exc)} -def main() -> dict: +def main() -> dict[Any, Any]: # pylint: disable=protected-access # pylint: disable=used-before-assignment """Run the collection catalog process. diff --git a/src/ansible_navigator/data/image_introspect.py b/src/ansible_navigator/data/image_introspect.py index 451e4e310..293f80e78 100644 --- a/src/ansible_navigator/data/image_introspect.py +++ b/src/ansible_navigator/data/image_introspect.py @@ -13,9 +13,11 @@ from queue import Queue from types import SimpleNamespace from typing import Any +from typing import TypeAlias -JSONTypes = bool | int | str | dict | list +# https://github.com/python/typing/issues/182#issuecomment-1320974824 +JSONTypes: TypeAlias = dict[str, "JSONTypes"] | list["JSONTypes"] | str | int | float | bool | None class Command(SimpleNamespace): @@ -23,7 +25,7 @@ class Command(SimpleNamespace): id_: str command: str - parse: Callable + parse: Callable[..., Any] stdout: str = "" stderr: str = "" details: list[str] | dict[Any, Any] | str = "" @@ -49,7 +51,7 @@ def run_command(command: Command) -> None: command.errors = [str(exc.stderr)] -def worker(pending_queue: Queue, completed_queue: Queue) -> None: +def worker(pending_queue: Queue[Any], completed_queue: Queue[Any]) -> None: """Run a command from pending, parse, and place in completed. :param pending_queue: A queue with plugins to process @@ -75,8 +77,8 @@ class CommandRunner: def __init__(self): """Initialize the command runner.""" - self._completed_queue: Queue | None = None - self._pending_queue: Queue | None = None + self._completed_queue: Queue[Any] | None = None + self._pending_queue: Queue[Any] | None = None def run_multi_thread(self, command_classes): """Run commands with multiple threads. diff --git a/src/ansible_navigator/image_manager/inspector.py b/src/ansible_navigator/image_manager/inspector.py index 40386d644..4058deb8d 100644 --- a/src/ansible_navigator/image_manager/inspector.py +++ b/src/ansible_navigator/image_manager/inspector.py @@ -89,7 +89,7 @@ def parse(command: Command): command.details = valid_images -def inspect_all(container_engine: str) -> tuple[list, str]: +def inspect_all(container_engine: str) -> tuple[list[str], str]: """Run inspect against all images in the list. :param container_engine: Name of the container engine diff --git a/src/ansible_navigator/runner/ansible_doc.py b/src/ansible_navigator/runner/ansible_doc.py index 9884032c0..6e6b8a3c9 100644 --- a/src/ansible_navigator/runner/ansible_doc.py +++ b/src/ansible_navigator/runner/ansible_doc.py @@ -15,7 +15,7 @@ class AnsibleDoc(Base): def fetch_plugin_doc( self, - plugin_names: list, + plugin_names: list[str | None], plugin_type: str | None = None, response_format: str | None = "json", snippet: bool | None = None, diff --git a/src/ansible_navigator/runner/ansible_inventory.py b/src/ansible_navigator/runner/ansible_inventory.py index d45d2e7f0..2d5ff2196 100644 --- a/src/ansible_navigator/runner/ansible_inventory.py +++ b/src/ansible_navigator/runner/ansible_inventory.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing import Any + from ansible_runner import get_inventory from .base import Base @@ -14,7 +16,7 @@ class AnsibleInventory(Base): def fetch_inventory( self, action: str, - inventories: list, + inventories: list[Any], response_format: str | None = None, host: str | None = None, playbook_dir: str | None = None, diff --git a/src/ansible_navigator/runner/base.py b/src/ansible_navigator/runner/base.py index 537a32db6..6b91a0fb9 100644 --- a/src/ansible_navigator/runner/base.py +++ b/src/ansible_navigator/runner/base.py @@ -85,7 +85,7 @@ def __init__( self.cancelled: bool = False self.finished: bool = False self.status: str | None = None - self._runner_args: dict = {} + self._runner_args: dict[str, Any] = {} # when the ce is podman, set the container user to root if self._ce == "podman": diff --git a/src/ansible_navigator/runner/command_async.py b/src/ansible_navigator/runner/command_async.py index 8c2c2e736..8b2baa1b7 100644 --- a/src/ansible_navigator/runner/command_async.py +++ b/src/ansible_navigator/runner/command_async.py @@ -8,6 +8,7 @@ from copy import deepcopy from queue import Queue +from typing import Any from ansible_runner import run_command_async @@ -17,7 +18,7 @@ class CommandAsync(CommandBase): """A wrapper for the asynchronous runner.""" - def __init__(self, executable_cmd: str, queue: Queue, write_job_events: bool, **kwargs): + def __init__(self, executable_cmd: str, queue: Queue[Any], write_job_events: bool, **kwargs): """Initialize the arguments for the ``run_command_async`` interface of ``ansible-runner``. For common arguments refer to the documentation of the ``CommandBase`` class. diff --git a/src/ansible_navigator/runner/command_base.py b/src/ansible_navigator/runner/command_base.py index 200b7d117..d0d734c1e 100644 --- a/src/ansible_navigator/runner/command_base.py +++ b/src/ansible_navigator/runner/command_base.py @@ -16,9 +16,9 @@ class CommandBase(Base): def __init__( self, executable_cmd: str, - cmdline: list | None = None, + cmdline: list[str] | None = None, playbook: str | None = None, - inventory: list | None = None, + inventory: list[str] | None = None, **kwargs, ): """Handle common arguments of ``run_command`` interface for ``ansible-runner``. diff --git a/src/ansible_navigator/ui_framework/colorize.py b/src/ansible_navigator/ui_framework/colorize.py index 755b4fa76..e84e36009 100644 --- a/src/ansible_navigator/ui_framework/colorize.py +++ b/src/ansible_navigator/ui_framework/colorize.py @@ -12,6 +12,7 @@ import re from itertools import chain +from typing import Any from ansible_navigator.tm_tokenize.grammars import Grammars from ansible_navigator.tm_tokenize.region import Regions @@ -43,7 +44,7 @@ class ColorSchema: """A storage mechanism for the schema (theme).""" - def __init__(self, schema: dict[str, str | list | dict]): + def __init__(self, schema: dict[str, str | list[Any] | dict[Any, Any]]): """Initialize the ColorSchema class. :param schema: The color scheme, theme to use @@ -164,7 +165,7 @@ def render(self, doc: str, scope: str) -> list[list[SimpleLinePart]]: return res -def scope_to_list(scope: str | list) -> list: +def scope_to_list(scope: str | list[Any]) -> list[Any]: """Convert a token scope to a list if necessary. A scope in a theme should always be a string or list, diff --git a/src/ansible_navigator/ui_framework/field_button.py b/src/ansible_navigator/ui_framework/field_button.py index 9f423de0c..a22e11f2a 100644 --- a/src/ansible_navigator/ui_framework/field_button.py +++ b/src/ansible_navigator/ui_framework/field_button.py @@ -4,6 +4,7 @@ from collections.abc import Callable from dataclasses import dataclass +from typing import Any from .curses_window import Window from .form_defs import FieldValidationStates @@ -21,7 +22,7 @@ class FieldButton: pressed: bool = False color: int = 0 window_handler = FormHandlerButton - validator: Callable = FieldValidators.none + validator: Callable[..., Any] = FieldValidators.none win: Window | None = None @property diff --git a/src/ansible_navigator/ui_framework/field_checks.py b/src/ansible_navigator/ui_framework/field_checks.py index d311480d2..466e88f9a 100644 --- a/src/ansible_navigator/ui_framework/field_checks.py +++ b/src/ansible_navigator/ui_framework/field_checks.py @@ -8,6 +8,7 @@ from dataclasses import dataclass from dataclasses import field from functools import partial +from typing import Any from .form_handler_options import FormHandlerOptions from .sentinels import Unknown @@ -24,7 +25,7 @@ class FieldChecks: name: str current_error: str = "" valid: Unknown | bool = unknown - options: list = field(default_factory=list) + options: list[Any] = field(default_factory=list) max_selected: int = sys.maxsize min_selected: int = 1 window_handler = FormHandlerOptions @@ -54,7 +55,7 @@ def full_prompt(self) -> str: return self.prompt @property - def validator(self) -> Callable: + def validator(self) -> Callable[..., Any]: """Provide a validator based on form type. :returns: Validation of checked entries diff --git a/src/ansible_navigator/ui_framework/field_curses_information.py b/src/ansible_navigator/ui_framework/field_curses_information.py index 0d81a78c6..dbda670ee 100644 --- a/src/ansible_navigator/ui_framework/field_curses_information.py +++ b/src/ansible_navigator/ui_framework/field_curses_information.py @@ -4,6 +4,7 @@ from collections.abc import Callable from dataclasses import dataclass +from typing import Any from .curses_defs import CursesLines from .curses_window import Window @@ -22,7 +23,7 @@ class FieldCursesInformation: current_error: str = "" window_handler = FormHandlerInformation valid: bool | Unknown = unknown - validator: Callable = FieldValidators.null + validator: Callable[..., Any] = FieldValidators.null win: Window | None = None @property diff --git a/src/ansible_navigator/ui_framework/field_information.py b/src/ansible_navigator/ui_framework/field_information.py index ccc9daa2c..ca265245a 100644 --- a/src/ansible_navigator/ui_framework/field_information.py +++ b/src/ansible_navigator/ui_framework/field_information.py @@ -4,6 +4,7 @@ from collections.abc import Callable from dataclasses import dataclass +from typing import Any from .curses_window import Window from .form_handler_information import FormHandlerInformation @@ -21,7 +22,7 @@ class FieldInformation: current_error: str = "" window_handler = FormHandlerInformation valid: bool | Unknown = unknown - validator: Callable = FieldValidators.null + validator: Callable[..., Any] = FieldValidators.null win: Window | None = None @property diff --git a/src/ansible_navigator/ui_framework/field_radio.py b/src/ansible_navigator/ui_framework/field_radio.py index 680b4a48f..15160a29c 100644 --- a/src/ansible_navigator/ui_framework/field_radio.py +++ b/src/ansible_navigator/ui_framework/field_radio.py @@ -6,6 +6,7 @@ from dataclasses import dataclass from dataclasses import field from functools import partial +from typing import Any from .form_handler_options import FormHandlerOptions from .sentinels import Unknown @@ -22,7 +23,7 @@ class FieldRadio: name: str current_error: str = "" valid: Unknown | bool = unknown - options: list = field(default_factory=list) + options: list[Any] = field(default_factory=list) window_handler = FormHandlerOptions @property @@ -50,7 +51,7 @@ def full_prompt(self) -> str: return self.prompt @property - def validator(self) -> Callable: + def validator(self) -> Callable[..., Any]: """Provide a validator based on form type. :returns: Validation of checked entries diff --git a/src/ansible_navigator/ui_framework/field_text.py b/src/ansible_navigator/ui_framework/field_text.py index 8033c87f1..560d6b2f2 100644 --- a/src/ansible_navigator/ui_framework/field_text.py +++ b/src/ansible_navigator/ui_framework/field_text.py @@ -26,7 +26,7 @@ class FieldText: window_handler = FormHandlerText response: str | Unknown = unknown valid: bool | Unknown = unknown - validator: Callable = FieldValidators.none + validator: Callable[..., Any] = FieldValidators.none value: Any = unknown win: Window | None = None diff --git a/src/ansible_navigator/ui_framework/field_working.py b/src/ansible_navigator/ui_framework/field_working.py index eca31ecfc..73f8395f2 100644 --- a/src/ansible_navigator/ui_framework/field_working.py +++ b/src/ansible_navigator/ui_framework/field_working.py @@ -4,6 +4,7 @@ from collections.abc import Callable from dataclasses import dataclass +from typing import Any from .curses_window import Window from .form_handler_working import FormHandlerWorking @@ -21,7 +22,7 @@ class FieldWorking: current_error: str = "" window_handler = FormHandlerWorking valid: bool | Unknown = unknown - validator: Callable = FieldValidators.null + validator: Callable[..., Any] = FieldValidators.null win: Window | None = None @property diff --git a/src/ansible_navigator/ui_framework/form.py b/src/ansible_navigator/ui_framework/form.py index b6afdc598..5375a835f 100644 --- a/src/ansible_navigator/ui_framework/form.py +++ b/src/ansible_navigator/ui_framework/form.py @@ -7,6 +7,7 @@ from curses import ascii as curses_ascii from dataclasses import dataclass from dataclasses import field +from typing import Any from .curses_defs import CursesLine from .curses_defs import CursesLinePart @@ -31,12 +32,12 @@ class Form: type_: FormType cancelled: bool = False - fields: list = field(default_factory=list) + fields: list[Any] = field(default_factory=list) submitted: bool = False title: str = "" title_color: int = 0 - _dict: dict = field(default_factory=dict) + _dict: dict[Any, Any] = field(default_factory=dict) def present(self, screen, ui_config): """Present the form the to user and return the results. diff --git a/src/ansible_navigator/ui_framework/form_handler_button.py b/src/ansible_navigator/ui_framework/form_handler_button.py index 12d4f7dec..84582645f 100644 --- a/src/ansible_navigator/ui_framework/form_handler_button.py +++ b/src/ansible_navigator/ui_framework/form_handler_button.py @@ -6,6 +6,7 @@ from curses import ascii as curses_ascii from typing import TYPE_CHECKING +from typing import Any from .curses_defs import CursesLinePart from .curses_window import CursesWindow @@ -41,7 +42,7 @@ def populate(self): clp_button = CursesLinePart(0, text, color, curses.A_STANDOUT) self._add_line(self.win, 0, ([clp_button])) - def handle(self, idx, form_fields: list) -> tuple[FieldButton, int]: + def handle(self, idx, form_fields: list[Any]) -> tuple[FieldButton, int]: """Handle the check box field. :param form_fields: List of fields diff --git a/src/ansible_navigator/ui_framework/form_handler_information.py b/src/ansible_navigator/ui_framework/form_handler_information.py index 6401f78e6..f2648fbc1 100644 --- a/src/ansible_navigator/ui_framework/form_handler_information.py +++ b/src/ansible_navigator/ui_framework/form_handler_information.py @@ -4,6 +4,7 @@ from curses import ascii as curses_ascii from typing import TYPE_CHECKING +from typing import Any from .curses_window import CursesWindow @@ -25,7 +26,7 @@ def __init__(self, screen, ui_config): self._screen = screen @staticmethod - def handle(idx, form_fields: list) -> tuple[FieldInformation, int]: + def handle(idx, form_fields: list[Any]) -> tuple[FieldInformation, int]: """Handle the information field, immediate return. :param idx: Index to retrieve specific field diff --git a/src/ansible_navigator/ui_framework/form_handler_options.py b/src/ansible_navigator/ui_framework/form_handler_options.py index ffdcb7d0b..c584a58f8 100644 --- a/src/ansible_navigator/ui_framework/form_handler_options.py +++ b/src/ansible_navigator/ui_framework/form_handler_options.py @@ -6,6 +6,7 @@ from curses import ascii as curses_ascii from typing import TYPE_CHECKING +from typing import Any from .curses_defs import CursesLinePart from .curses_window import CursesWindow @@ -48,7 +49,7 @@ def populate(self, form_field, active): clp_text = CursesLinePart(len(option_code) + 1, text, color, decoration) self._add_line(self.win, idx, ([clp_option_code, clp_text])) - def handle(self, idx, form_fields: list) -> tuple[FieldChecks | FieldRadio, int]: + def handle(self, idx, form_fields: list[Any]) -> tuple[FieldChecks | FieldRadio, int]: # pylint: disable=too-many-nested-blocks """Handle the check box field. diff --git a/src/ansible_navigator/ui_framework/form_handler_working.py b/src/ansible_navigator/ui_framework/form_handler_working.py index 330af0613..cc46115f0 100644 --- a/src/ansible_navigator/ui_framework/form_handler_working.py +++ b/src/ansible_navigator/ui_framework/form_handler_working.py @@ -24,7 +24,7 @@ def __init__(self, screen, ui_config): self._screen = screen @staticmethod - def handle(idx, form_fields: list) -> tuple[FieldWorking, int]: + def handle(idx, form_fields: list[str]) -> tuple[FieldWorking, int]: """Handle the information field, immediate return. :param idx: Index to retrieve specific field diff --git a/src/ansible_navigator/ui_framework/form_utils.py b/src/ansible_navigator/ui_framework/form_utils.py index 6b98b8c88..2df7a894d 100644 --- a/src/ansible_navigator/ui_framework/form_utils.py +++ b/src/ansible_navigator/ui_framework/form_utils.py @@ -7,6 +7,7 @@ import textwrap from functools import partial +from typing import Any from ansible_navigator.utils.definitions import ExitMessage from ansible_navigator.utils.definitions import ExitMessages @@ -28,7 +29,7 @@ from .validators import FieldValidators -def dict_to_form(form_data: dict) -> Form: +def dict_to_form(form_data: dict[str, Any]) -> Form: """Convert a python dict to a form. :param form_data: Form data @@ -96,7 +97,7 @@ def dict_to_form(form_data: dict) -> Form: return form -def form_to_dict(form: Form, key_on_name: bool = False) -> dict: +def form_to_dict(form: Form, key_on_name: bool = False) -> dict[str, Any]: """Populate the original _dict of the form with the results. :param form: Holding place for form fields diff --git a/src/ansible_navigator/ui_framework/menu_builder.py b/src/ansible_navigator/ui_framework/menu_builder.py index cfc619857..cccf71e61 100644 --- a/src/ansible_navigator/ui_framework/menu_builder.py +++ b/src/ansible_navigator/ui_framework/menu_builder.py @@ -28,7 +28,7 @@ def __init__( progress_bar_width: int, screen_width: int, number_colors: int, - color_menu_item: Callable, + color_menu_item: Callable[..., Any], ui_config: UIConfig, ): """Initialize the menu builder. @@ -101,7 +101,7 @@ def _menu( menu_lines = self._menu_lines(dicts, menu_layout, indices) return CursesLines(tuple([header])), menu_lines - def _menu_header_line(self, menu_layout: tuple[list, ...]) -> CursesLine: + def _menu_header_line(self, menu_layout: tuple[list[Any], ...]) -> CursesLine: """Generate the menu header line. :param menu_layout: A tuple of menu details: @@ -118,7 +118,7 @@ def _menu_header_line(self, menu_layout: tuple[list, ...]) -> CursesLine: return CursesLine(line_parts) @staticmethod - def _menu_header_line_part(colno: int, menu_layout: tuple[list, ...]) -> CursesLinePart: + def _menu_header_line_part(colno: int, menu_layout: tuple[list[Any], ...]) -> CursesLinePart: """Generate one part of the menu header line. :param colno: The column number @@ -151,7 +151,7 @@ def _menu_header_line_part(colno: int, menu_layout: tuple[list, ...]) -> CursesL def _menu_lines( self, dicts: ContentTypeSequence, - menu_layout: tuple[list, ...], + menu_layout: tuple[list[Any], ...], indices, ) -> CursesLines: """Generate all the menu lines. @@ -170,8 +170,8 @@ def _menu_lines( def _menu_line( self, - menu_entry: dict[str, Any] | ContentBase, - menu_layout: tuple[list, ...], + menu_entry: dict[str, Any] | ContentBase[Any], + menu_layout: tuple[list[Any], ...], ) -> CursesLine: """Generate one the menu line. @@ -196,8 +196,8 @@ def _menu_line_part( self, colno: int, coltext: Any, - menu_entry: dict[str, Any] | ContentBase, - menu_layout: tuple[list, ...], + menu_entry: dict[str, Any] | ContentBase[Any], + menu_layout: tuple[list[Any], ...], ) -> CursesLinePart: # pylint: disable=too-many-locals """Generate one menu line part. diff --git a/src/ansible_navigator/ui_framework/ui.py b/src/ansible_navigator/ui_framework/ui.py index 8b90ef15b..65d492247 100644 --- a/src/ansible_navigator/ui_framework/ui.py +++ b/src/ansible_navigator/ui_framework/ui.py @@ -282,7 +282,7 @@ def _ui(self) -> Ui: ) return res - def _footer(self, key_dict: dict) -> CursesLine: + def _footer(self, key_dict: dict[Any, Any]) -> CursesLine: """Build a footer from the key dict spread the columns out evenly. :param key_dict: the keys and their description diff --git a/src/ansible_navigator/ui_framework/utils.py b/src/ansible_navigator/ui_framework/utils.py index 51189cf1c..09409c655 100644 --- a/src/ansible_navigator/ui_framework/utils.py +++ b/src/ansible_navigator/ui_framework/utils.py @@ -13,7 +13,7 @@ def convert_percentage( - content: dict[str, Any] | ContentBase, + content: dict[str, Any] | ContentBase[Any], columns: list[str], progress_bar_width: int, ) -> None: diff --git a/src/ansible_navigator/ui_framework/validators.py b/src/ansible_navigator/ui_framework/validators.py index 7fc238ece..41e241e0c 100644 --- a/src/ansible_navigator/ui_framework/validators.py +++ b/src/ansible_navigator/ui_framework/validators.py @@ -105,7 +105,7 @@ def one_of(choices: list[str] = [], text: str = "", hint: bool = False) -> Valid @staticmethod def some_of_or_none( - choices: Unknown | list = unknown, + choices: Unknown | list[Any] = unknown, min_selected: Unknown | int = unknown, max_selected: Unknown | int = unknown, hint: bool = False, @@ -264,7 +264,7 @@ class FormValidators: """Validators for a form.""" @staticmethod - def all_true(response: list | None = None, hint: bool = False) -> Validation | str: + def all_true(response: list[Any] | None = None, hint: bool = False) -> Validation | str: """Validate all in list are true. :param response: The list to validate @@ -281,7 +281,7 @@ def all_true(response: list | None = None, hint: bool = False) -> Validation | s @staticmethod def no_validation( - response: list | None = None, + response: list[Any] | None = None, hint: bool = False, ) -> Validation | str: """No validation. diff --git a/src/ansible_navigator/utils/dot_paths.py b/src/ansible_navigator/utils/dot_paths.py index 9046f4f0f..e5180c0dd 100644 --- a/src/ansible_navigator/utils/dot_paths.py +++ b/src/ansible_navigator/utils/dot_paths.py @@ -97,10 +97,10 @@ def remove_and_delete_empty_ascendants(content: MutableMapping[Any, Any], path: def place_at_path( behaviors: tuple[MergeBehaviors, ...], - content: dict, + content: dict[Any, Any], path: str, - value: bool | int | list | float | str | dict, -) -> dict: + value: bool | int | list[Any] | float | str | dict[Any, Any], +) -> dict[Any, Any]: """Place a value at a path in a dictionary. :param behaviors: The merge behaviors @@ -180,10 +180,10 @@ def place_at_path( def move_to_path( behaviors: tuple[MergeBehaviors, ...], - content: dict, + content: dict[Any, Any], new_path: str, old_path: str, -) -> dict: +) -> dict[Any, Any]: """Move a value to a path in a dictionary. :param behaviors: The merge behaviors diff --git a/src/ansible_navigator/utils/functions.py b/src/ansible_navigator/utils/functions.py index 3679d2a39..0ceb4fecc 100644 --- a/src/ansible_navigator/utils/functions.py +++ b/src/ansible_navigator/utils/functions.py @@ -147,7 +147,7 @@ def dispatch(obj, replacements): return obj -def escape_moustaches(obj: Mapping) -> Mapping: +def escape_moustaches(obj: Mapping[Any, Any]) -> Mapping[Any, Any]: """Escape moustaches. :param obj: Variable that may contain moustaches @@ -239,7 +239,7 @@ def find_settings_file() -> tuple[list[LogMessage], list[ExitMessage], str | Non return messages, exit_messages, use -def flatten_list(data_list) -> list: +def flatten_list(data_list: list[Any]) -> list[Any]: """Flatten a list of lists. :param data_list: List to flatten @@ -426,7 +426,7 @@ def str2bool(value: Any) -> bool: # TODO: We are kind-of screwed type-wise by the fact that ast.literal_eval() # returns Any. Need to find a better solution... "Any" isn't it. -def templar(string: str, template_vars: Mapping) -> tuple[list[str], Any]: +def templar(string: str, template_vars: Mapping[Any, Any]) -> tuple[list[str], Any]: """Template some string with jinja2 always to and from json. :param string: The template string @@ -506,7 +506,7 @@ def time_stamp_for_file(path: str, time_zone: str) -> tuple[float | None, str | return modified, iso_stamp -def to_list(thing: str | list | tuple | set | None) -> list: +def to_list(thing: str | list[Any] | tuple[Any] | set[Any] | None) -> list[Any]: """Convert something to a list if necessary. :param thing: Item to convert to a list @@ -521,7 +521,7 @@ def to_list(thing: str | list | tuple | set | None) -> list: return converted_value -def unescape_moustaches(obj: Any) -> Mapping: +def unescape_moustaches(obj: Any) -> Mapping[Any, Any]: """Unescape moustaches. :param obj: Variable that needs to contain moustaches diff --git a/src/ansible_navigator/utils/serialize.py b/src/ansible_navigator/utils/serialize.py index 2937659f7..688da57a7 100644 --- a/src/ansible_navigator/utils/serialize.py +++ b/src/ansible_navigator/utils/serialize.py @@ -197,7 +197,7 @@ class JsonParams(NamedTuple): ensure_ascii: bool = False -def _json_dump(dumpable: ContentType, file_handle: IO) -> None: +def _json_dump(dumpable: ContentType, file_handle: IO[str]) -> None: """Serialize the dumpable to json and write to a file. :param dumpable: The object to dump @@ -234,7 +234,7 @@ def _json_dumps(dumpable: ContentType) -> str: return error_message -def _text_dump(dumpable: str, file_handle: IO) -> None: +def _text_dump(dumpable: str, file_handle: IO[str]) -> None: """Write text to a file. :param dumpable: The text to write @@ -253,7 +253,7 @@ class YamlStyle(NamedTuple): allow_unicode: bool = True -def _yaml_dump(dumpable: ContentType, file_handle: IO): +def _yaml_dump(dumpable: ContentType, file_handle: IO[str]): """Serialize the dumpable to yaml and write to a file. :param dumpable: The object to serialize diff --git a/src/ansible_navigator/utils/version_migration/definitions.py b/src/ansible_navigator/utils/version_migration/definitions.py index e9c2a7e9a..b7a0a000c 100644 --- a/src/ansible_navigator/utils/version_migration/definitions.py +++ b/src/ansible_navigator/utils/version_migration/definitions.py @@ -7,6 +7,7 @@ from collections.abc import Callable from enum import Enum from pathlib import Path +from typing import Any from typing import Generic from typing import TypeVar @@ -69,7 +70,7 @@ def print_not_needed(self) -> None: subtle(color=COLOR, message=information) @classmethod - def register(cls: T, migration_step: T) -> Callable: + def register(cls: T, migration_step: T) -> Callable[..., Any]: """Register the migration step. :param migration_step: The migration step to register @@ -114,12 +115,12 @@ def __init_subclass__(cls, *args, **kwargs): migrations.append(cls) @property - def migration_steps(self) -> tuple[MigrationStep, ...]: + def migration_steps(self) -> tuple[MigrationStep[Any], ...]: """Return the registered diagnostics. :returns: The registered diagnostics """ - steps: list[MigrationStep] = [] + steps: list[MigrationStep[Any]] = [] for func_name in vars(self.__class__): if func_name.startswith("_"): continue @@ -143,7 +144,7 @@ def run(self, *args, **kwargs) -> None: :param kwargs: The keyword arguments """ - def run_step(self, step: MigrationStep, *args, **kwargs) -> None: + def run_step(self, step: MigrationStep[Any], *args, **kwargs) -> None: """Run the migration step. :param step: The migration step to run diff --git a/src/ansible_navigator/utils/version_migration/settings_file.py b/src/ansible_navigator/utils/version_migration/settings_file.py index 8c0864170..d72e777f7 100644 --- a/src/ansible_navigator/utils/version_migration/settings_file.py +++ b/src/ansible_navigator/utils/version_migration/settings_file.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing import Any + from ansible_navigator.content_defs import ContentView from ansible_navigator.content_defs import SerializationFormat from ansible_navigator.utils.ansi import COLOR @@ -22,7 +24,7 @@ class SettingsFile(Migration): def __init__(self): """Initialize the settings file migration.""" super().__init__() - self.content: dict = {} + self.content: dict[Any, Any] = {} self._backup_suffix = ".v0" def run(self, *args, **kwargs) -> None: diff --git a/src/ansible_navigator/utils/version_migration/v1_v2_settings_file.py b/src/ansible_navigator/utils/version_migration/v1_v2_settings_file.py index 214fc3e1a..2cdbc3e05 100644 --- a/src/ansible_navigator/utils/version_migration/v1_v2_settings_file.py +++ b/src/ansible_navigator/utils/version_migration/v1_v2_settings_file.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing import Any + from ansible_navigator.utils.dot_paths import MergeBehaviors from ansible_navigator.utils.dot_paths import check_path from ansible_navigator.utils.dot_paths import get_with_path @@ -23,10 +25,10 @@ class V1V2SettingsFile(SettingsFile): name = "Version 1 to Version 2 settings file format migration" migration_type: MigrationType = MigrationType.SETTINGS_FILE - def __init__(self): + def __init__(self) -> None: """Initialize the v1 to v2 settings file migration.""" super().__init__() - self.content: dict = {} + self.content: dict[Any, Any] = {} self._backup_suffix = ".v1" @MigrationStep.register(MigrationStep(name="config path")) diff --git a/tests/integration/_common.py b/tests/integration/_common.py index 90d32684e..131a0a3c3 100644 --- a/tests/integration/_common.py +++ b/tests/integration/_common.py @@ -11,6 +11,7 @@ from collections.abc import Callable from dataclasses import dataclass from pathlib import Path +from typing import Any import pytest @@ -168,7 +169,7 @@ def copytree( src: str, dst: str, symlinks: bool = False, - ignore: Callable | None = None, + ignore: Callable[..., Any] | None = None, dirs_exist_ok: bool = False, ): """Recursively copy a directory tree using copy2(). @@ -247,4 +248,4 @@ class Parameter: """ name: str - value: bool | str | list | Path + value: bool | str | list[str] | Path diff --git a/tests/unit/configuration_subsystem/test_posix_message_queue.py b/tests/unit/configuration_subsystem/test_posix_message_queue.py index 0ba0623a8..95cb0124d 100644 --- a/tests/unit/configuration_subsystem/test_posix_message_queue.py +++ b/tests/unit/configuration_subsystem/test_posix_message_queue.py @@ -3,6 +3,7 @@ import pathlib from collections.abc import Callable +from typing import Any import pytest @@ -17,7 +18,7 @@ def test_posix_message_queue_ee( ee_support: bool, engine: str, platform: str, - generate_config: Callable, + generate_config: Callable[..., Any], ): """Confirm error messages related to missing ``/dev/mqueue/`` and ``podman``. diff --git a/tests/unit/utils/test_dot_paths.py b/tests/unit/utils/test_dot_paths.py index e26952b1e..6548ec1ee 100644 --- a/tests/unit/utils/test_dot_paths.py +++ b/tests/unit/utils/test_dot_paths.py @@ -86,8 +86,8 @@ class Scenario(BaseScenario): # pylint: disable=too-many-instance-attributes comment: str path: str expected: MutableMapping[Any, Any] | None - value: bool | int | list | float | str | dict = "" - content: dict = field(default_factory=lambda: base_dict) + value: bool | int | list[Any] | float | str | dict[Any, Any] = "" + content: dict[Any, Any] = field(default_factory=lambda: base_dict) new_path: str = "" def __str__(self): diff --git a/tests/unit/utils/test_functions.py b/tests/unit/utils/test_functions.py index 717610c56..0865a1085 100644 --- a/tests/unit/utils/test_functions.py +++ b/tests/unit/utils/test_functions.py @@ -116,7 +116,7 @@ def test_env_var_is_file_path( "list-detailed", ], ) -def test_flatten_list(value: list, anticipated_result: list) -> None: +def test_flatten_list(value: list[str], anticipated_result: list[str]) -> None: """Test for flatten list. :param value: List to be flattened diff --git a/tests/unit/utils/test_serialize_dataclass.py b/tests/unit/utils/test_serialize_dataclass.py index fc4b294a3..67fa1d4b0 100644 --- a/tests/unit/utils/test_serialize_dataclass.py +++ b/tests/unit/utils/test_serialize_dataclass.py @@ -23,16 +23,16 @@ class ParametrizeView(NamedTuple): """Keyword arguments for parametrization of view.""" argnames: str = "content_view" - argvalues: Iterable = (ContentView.NORMAL, ContentView.FULL) - ids: Callable = id_func + argvalues: Iterable[Any] = (ContentView.NORMAL, ContentView.FULL) + ids: Callable[..., Any] = id_func class ParametrizeFormat(NamedTuple): """Keyword arguments for parametrization of format.""" argnames: str = "serialization_tuple" - argvalues: Iterable = (("j", SerializationFormat.JSON), ("y", SerializationFormat.YAML)) - ids: Callable = id_func + argvalues: Iterable[Any] = (("j", SerializationFormat.JSON), ("y", SerializationFormat.YAML)) + ids: Callable[..., Any] = id_func SimpleDictValue = bool | str | int