Skip to content

Commit

Permalink
More types
Browse files Browse the repository at this point in the history
  • Loading branch information
ssbarnea committed Feb 29, 2024
1 parent 1e73132 commit ac630ba
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 29 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ color_output = true
error_summary = true
check_untyped_defs = true
# disallow_untyped_calls = true
# disallow_untyped_defs = true
disallow_untyped_defs = true
disallow_any_generics = true
incremental = false

Expand Down
11 changes: 8 additions & 3 deletions src/ansible_navigator/content_defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

from collections.abc import Callable
from collections.abc import ItemsView
from collections.abc import Sequence
from dataclasses import asdict
Expand Down Expand Up @@ -57,23 +58,27 @@ def asdict(obj: Any, \*, dict_factory: Callable[[list[tuple[str, Any]]], _T]) ->
def asdict(
self,
content_view: ContentView,
serialization_format: SerializationFormat,
serialization_format: SerializationFormat | None,
) -> DictType[Any]:
"""Convert thy self into a dictionary.
:param content_view: The content view
:param serialization_format: The serialization format
:returns: A dictionary created from self
"""
converter_map = {
converter_map: dict[
tuple[ContentView, SerializationFormat], Callable[[], dict[str, Any]]
] = {
(ContentView.FULL, SerializationFormat.JSON): self.serialize_json_full,
(ContentView.FULL, SerializationFormat.YAML): self.serialize_yaml_full,
(ContentView.NORMAL, SerializationFormat.JSON): self.serialize_json_normal,
(ContentView.NORMAL, SerializationFormat.YAML): self.serialize_yaml_normal,
}

if serialization_format is None:
raise RuntimeError
try:
dump_self_as_dict = converter_map[content_view, serialization_format]
dump_self_as_dict = converter_map[(content_view, serialization_format)]
except KeyError:
return asdict(self)
return dump_self_as_dict()
Expand Down
5 changes: 3 additions & 2 deletions src/ansible_navigator/initialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def _diagnose(
exit_messages: list[ExitMessage],
messages: list[LogMessage],
should_diagnose: bool,
):
) -> tuple[list[LogMessage], list[ExitMessage]]:
"""Direct to the diagnostic information writer or return.
:param args: Application configuration
Expand All @@ -159,13 +159,14 @@ def _diagnose(
DiagnosticsCollector(args=args, messages=messages, exit_messages=exit_messages).run()
else:
return messages, exit_messages
return ([], [])


def parse_and_update(
params: list[str],
args: ApplicationConfiguration,
apply_previous_cli_entries: C | list[str] = C.NONE,
attach_cdc=False,
attach_cdc: bool = False,
) -> tuple[list[LogMessage], list[ExitMessage]]:
"""Build a configuration.
Expand Down
17 changes: 10 additions & 7 deletions src/ansible_navigator/ui_framework/form_handler_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@

from curses import ascii as curses_ascii
from typing import TYPE_CHECKING
from typing import Any

from .curses_defs import CursesLine
from .curses_defs import CursesLinePart
from .curses_window import CursesWindow


if TYPE_CHECKING:
from .field_checks import FieldChecks
from .field_radio import FieldRadio
from ansible_navigator.action_runner import Window
from ansible_navigator.ui_framework.field_text import FieldText
from ansible_navigator.ui_framework.ui_config import UIConfig


class FormHandlerOptions(CursesWindow):
"""Handle form checkbox field."""

def __init__(self, screen, ui_config):
def __init__(self, screen: Window, ui_config: UIConfig) -> None:
"""Initialize the handler for either form checkboxes or radio buttons.
:param screen: A curses window
Expand All @@ -30,13 +30,14 @@ def __init__(self, screen, ui_config):
super().__init__(ui_config=ui_config)
self._screen = screen

def populate(self, form_field, active):
def populate(self, form_field: FieldText, active: int) -> None:
"""Populate the window with the checkboxes.
:param form_field: Field from a form
:param active: Track active checkbox/option
"""
for idx, option in enumerate(form_field.options):
options = getattr(form_field, "options", [])
for idx, option in enumerate(options):
option_code = option.ansi_code(form_field)
color = 8 if option.disabled else 0
decoration = curses.A_STANDOUT if idx == active else 0
Expand All @@ -52,7 +53,7 @@ def populate(self, form_field, active):
window=self.win, lineno=idx, line=CursesLine((clp_option_code, clp_text))
)

def handle(self, idx, form_fields: list[Any]) -> tuple[FieldChecks | FieldRadio, int]:
def handle(self, idx: int, form_fields: list[FieldText]) -> tuple[FieldText, int]:
# pylint: disable=too-many-nested-blocks
"""Handle the check box field.
Expand All @@ -63,6 +64,8 @@ def handle(self, idx, form_fields: list[Any]) -> tuple[FieldChecks | FieldRadio,
form_field = form_fields[idx]
active = 0

if not hasattr(form_field, "options"):
raise RuntimeError
while True:
active = active % len(form_field.options)
self.populate(form_field, active)
Expand Down
7 changes: 5 additions & 2 deletions src/ansible_navigator/ui_framework/form_handler_working.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

from typing import TYPE_CHECKING

from ansible_navigator.ui_framework.ui_config import UIConfig

from .curses_window import CursesWindow
from .curses_window import Window


if TYPE_CHECKING:
Expand All @@ -14,7 +17,7 @@
class FormHandlerWorking(CursesWindow):
"""Handle form button."""

def __init__(self, screen, ui_config):
def __init__(self, screen: Window, ui_config: UIConfig) -> None:
"""Initialize the handler for a form working notification.
:param screen: A curses window
Expand All @@ -24,7 +27,7 @@ def __init__(self, screen, ui_config):
self._screen = screen

@staticmethod
def handle(idx, form_fields: list[str]) -> tuple[FieldWorking, int]:
def handle(idx: int, form_fields: list[FieldWorking]) -> tuple[FieldWorking, int]:
"""Handle the information field, immediate return.
:param idx: Index to retrieve specific field
Expand Down
2 changes: 1 addition & 1 deletion src/ansible_navigator/ui_framework/form_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def form_to_dict(form: Form, key_on_name: bool = False) -> dict[str, Any]:
return res


def break_long_lines(messages):
def break_long_lines(messages: list[str]) -> list[str]:
"""Break lines such that the form width !> 80%.
:param messages: Lines of the form
Expand Down
5 changes: 2 additions & 3 deletions src/ansible_navigator/ui_framework/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def is_percent(string: str) -> bool:
return False


def distribute(available, weights):
def distribute(available: int, weights: list[int]) -> list[int]:
"""Distribute some available fairly across a list of numbers.
:param available: the total
Expand All @@ -82,8 +82,7 @@ def distribute(available, weights):
distributed_amounts = []
total_weights = sum(weights)
for weight in weights:
weight = float(weight)
percent_of_total = weight / total_weights
percent_of_total = float(weight) / total_weights
distributed_amount = round(percent_of_total * available)
distributed_amounts.append(distributed_amount)
total_weights -= weight
Expand Down
14 changes: 10 additions & 4 deletions src/ansible_navigator/utils/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def console_width() -> int:


# TODO: Replace this with something type-safe.
def dispatch(obj, replacements):
def dispatch(obj: object, replacements: tuple[tuple[str, str], ...]) -> object:
"""Make the replacement based on type.
:param obj: An obj in which replacements will be made
Expand All @@ -154,7 +154,10 @@ def escape_moustaches(obj: Mapping[Any, Any]) -> Mapping[Any, Any]:
:returns: The obj with replacements made
"""
replacements = (("{", "U+007B"), ("}", "U+007D"))
return dispatch(obj, replacements)
result = dispatch(obj, replacements)
if not isinstance(result, dict):
raise RuntimeError
return result


def environment_variable_is_file_path(
Expand Down Expand Up @@ -321,7 +324,7 @@ def now_iso(time_zone: str) -> str:
PASCAL_REGEX = re.compile("((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))")


def pascal_to_snake(obj) -> list[Any] | dict[Any, Any]:
def pascal_to_snake(obj: object) -> object:
"""Convert a pascal cased object into a snake cased object recursively.
:param obj: Pascal cased object
Expand Down Expand Up @@ -529,4 +532,7 @@ def unescape_moustaches(obj: Any) -> Mapping[Any, Any]:
:returns: The obj with replacements made
"""
replacements = (("U+007B", "{"), ("U+007D", "}"))
return dispatch(obj, replacements)
result = dispatch(obj, replacements)
if not isinstance(result, dict):
raise RuntimeError
return result
12 changes: 6 additions & 6 deletions src/ansible_navigator/utils/version_migration/definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,14 @@ def register(cls: T, migration_step: MigrationStep[Any]) -> Callable[..., Any]:
:return: The registered migration step
"""

def wrapper(func):
def wrapper(func: Callable[..., Any]) -> Callable[..., Any]:
"""Add the dunder collector to the func.
:param func: The function to decorate
:returns: The decorated function
"""
migration_step.function_name = func.__name__
func.__migration_step__ = migration_step
func.__migration_step__ = migration_step # type: ignore[attr-defined]
return func

return wrapper
Expand All @@ -105,7 +105,7 @@ def __init__(self) -> None:
self.was_needed: bool = False
"""Whether the migration was needed."""

def __init_subclass__(cls, *args, **kwargs) -> None:
def __init_subclass__(cls, *args: Any, **kwargs: Any) -> None:
"""Register the migration steps.
:param args: Positional arguments
Expand Down Expand Up @@ -137,14 +137,14 @@ def needed_now(self) -> bool:
"""
return any(step.needed for step in self.migration_steps)

def run(self, *args, **kwargs) -> None:
def run(self, *args: Any, **kwargs: Any) -> None:
"""Run the migration.
:param args: The positional arguments
:param kwargs: The keyword arguments
"""

def run_step(self, step: MigrationStep[Any], *args, **kwargs) -> None:
def run_step(self, step: MigrationStep[Any], *args: Any, **kwargs: Any) -> None:
"""Run the migration step.
:param step: The migration step to run
Expand Down Expand Up @@ -175,7 +175,7 @@ def run_step(self, step: MigrationStep[Any], *args, **kwargs) -> None:
step.print_updated()
return

def run_steps(self, *args, **kwargs) -> None:
def run_steps(self, *args: Any, **kwargs: Any) -> None:
"""Run all registered migration steps.
:param args: The positional arguments
Expand Down

0 comments on commit ac630ba

Please sign in to comment.