Skip to content

Commit

Permalink
Docstrings for private methods (#1469)
Browse files Browse the repository at this point in the history
  • Loading branch information
cidrblock committed Mar 28, 2023
1 parent 46cafcc commit d60324c
Show file tree
Hide file tree
Showing 15 changed files with 151 additions and 0 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ ignore = [
# pylint defaults + fh for with open .. as (f|fh)
good-names = "i,j,k,ex,Run,_,f,fh"
jobs = 0
no-docstring-rgx = "__.*__"

[tool.pylint.messages_control]
disable = [
Expand Down
19 changes: 19 additions & 0 deletions src/ansible_navigator/configuration_subsystem/configurator.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ def __init__(
self._unaltered_entries = deepcopy(self._config.entries)

def _sanity_check(self) -> None:
"""Sanity check the configuration.
:raises ValueError: If apply_previous_cli is used while initializing
"""
if self._apply_previous_cli_entries is not C.NONE:
if self._config.internals.initializing:
raise ValueError("'apply_previous_cli' cannot be used while initializing")
Expand Down Expand Up @@ -140,6 +144,7 @@ def _restore_original(self) -> None:
self._messages.append(LogMessage(level=logging.INFO, message=message))

def _apply_defaults(self) -> None:
"""Apply the default values."""
for entry in self._config.entries:
if self._config.internals.initializing or entry.change_after_initial:
if entry.value.default is not C.NOT_SET:
Expand All @@ -152,6 +157,10 @@ def _apply_defaults(self) -> None:
def _apply_settings_file(self) -> None:
# pylint: disable=too-many-locals
# pylint: disable=too-many-statements
"""Apply the settings file.
:raises ValueError: If the settings file is empty
"""
settings_filesystem_path = self._config.internals.settings_file_path

if not isinstance(settings_filesystem_path, str):
Expand Down Expand Up @@ -249,6 +258,7 @@ def _apply_settings_file(self) -> None:
self._messages.append(LogMessage(level=logging.DEBUG, message=message))

def _apply_environment_variables(self) -> None:
"""Apply the environment variables."""
for entry in self._config.entries:
set_env_var = os.environ.get(entry.environment_variable(self._config.application_name))
if set_env_var is not None:
Expand All @@ -269,6 +279,7 @@ def _apply_environment_variables(self) -> None:
self._messages.append(LogMessage(level=logging.INFO, message=message))

def _apply_cli_params(self) -> None:
"""Apply the cli params."""
parser = Parser(self._config).parser
setattr(parser, "error", self._argparse_error_handler)
parser_response = parser.parse_known_args(self._params)
Expand All @@ -292,6 +303,7 @@ def _apply_cli_params(self) -> None:
self._messages.append(LogMessage(level=logging.INFO, message=message))

def _post_process(self) -> None:
"""Post process the settings entries."""
delayed = []
normal = []

Expand All @@ -314,6 +326,7 @@ def _post_process(self) -> None:
self._messages.append(LogMessage(level=logging.INFO, message=message))

def _check_choices(self) -> None:
"""Check the choices for each settings entry."""
for entry in self._config.entries:
if entry.cli_parameters and entry.choices:
if isinstance(entry.value.current, list):
Expand All @@ -325,6 +338,12 @@ def _check_choices(self) -> None:
self._check_choice(entry=entry, value=entry.value.current)

def _check_choice(self, entry: SettingsEntry, value: bool | str):
"""Check the choice for a single settings entry.
:param entry: The settings entry to check.
:param value: The value to check.
:return: True if the value is invalid and an error message was logged.
"""
if entry.cli_parameters and entry.choices:
if value not in entry.choices:
self._exit_messages.append(ExitMessage(message=entry.invalid_choice))
Expand Down
7 changes: 7 additions & 0 deletions src/ansible_navigator/configuration_subsystem/definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,13 @@ def application_name_dashed(self) -> str:
return self.application_name.replace("_", "-")

def _get_by_name(self, name, kind):
"""Retrieve a settings entry by name.
:param name: The name of the entry
:param kind: The kind of entry to retrieve
:returns: The settings entry
:raises KeyError: If the entry is not found
"""
try:
return next(entry for entry in super().__getattribute__(kind) if entry.name == name)
except StopIteration as exc:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@


def _post_processor(func):
"""Decorate a post processing function.
:param func: The function to wrap
:returns: The wrapped function
"""

def wrapper(*args, **kwargs):
name = kwargs["entry"].name
before = str(kwargs["entry"].value.current)
Expand Down Expand Up @@ -80,6 +86,12 @@ def _true_or_false(
config: ApplicationConfiguration,
) -> PostProcessorReturn:
# pylint: disable=unused-argument
"""Post process a boolean value.
:param entry: The current settings entry
:param config: The full application configuration
:returns: An instance of the standard post process return object
"""
messages: list[LogMessage] = []
exit_messages: list[ExitMessage] = []
try:
Expand Down
9 changes: 9 additions & 0 deletions src/ansible_navigator/image_manager/puller.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ def assessment(self):
return self._assessment

def _check_for_image(self):
"""Check for the image."""
try:
cmd_parts = [self._container_engine, "image", "inspect", self._image]
self._log_message(level=logging.DEBUG, message=f"Command: {shlex_join(cmd_parts)}")
Expand All @@ -115,6 +116,7 @@ def _check_for_image(self):
self._log_message(level=logging.WARNING, message=f"stderr: {stderr}")

def _determine_pull(self):
"""Determine if a pull is required."""
if self._pull_policy == "missing" and self._image_present is False:
pull = True
elif self._pull_policy == "always":
Expand All @@ -129,6 +131,7 @@ def _determine_pull(self):
self._assessment.pull_required = pull

def _extract_tag(self):
"""Extract the tag from the image name."""
image_pieces = self._image.split(":")
self._image_tag = "latest"
if len(image_pieces) > 1:
Expand All @@ -145,6 +148,12 @@ def _extract_tag(self):
self._log_message(level=logging.INFO, message=message)

def _log_message(self, message: str, level: int, hint=False):
"""Log a message.
:param message: The message to log
:param level: The logging level
:param hint: Whether or not the message is a hint
"""
if level == logging.ERROR:
self._exit_messages.append(ExitMessage(message=message))
elif hint:
Expand Down
1 change: 1 addition & 0 deletions src/ansible_navigator/runner/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ def runner_finished_callback(self, runner: Runner):
self.finished = True

def _add_env_vars_to_args(self):
"""Add environment variables to runner args."""
self._runner_args["envvars"] = {
k: v for k, v in os.environ.items() if k.startswith("ANSIBLE_")
}
Expand Down
5 changes: 5 additions & 0 deletions src/ansible_navigator/runner/command_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ def __init__(self, executable_cmd: str, queue: Queue, write_job_events: bool, **
super().__init__(executable_cmd, **kwargs)

def _event_handler(self, event):
"""Handle the event from ansible-runner.
:param event: The event from ansible-runner
:returns: The value of ``self._write_job_events``, a boolean
"""
self._logger.debug("ansible-runner event handle: %s", event)
new_event = deepcopy(event)
self._queue.put(new_event)
Expand Down
5 changes: 5 additions & 0 deletions src/ansible_navigator/ui_framework/field_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ def validator(self) -> Callable:
)

def _validate(self, response: FieldChecks) -> Validation:
"""Validate this FieldChecks instance.
:param response: The form response from the user
:returns: Validation of the response
"""
validation = self.validator(choices=response.options)
if validation.error_msg:
self.valid = False
Expand Down
5 changes: 5 additions & 0 deletions src/ansible_navigator/ui_framework/field_radio.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ def validator(self) -> Callable:
return partial(FieldValidators.some_of_or_none, max_selected=1, min_selected=1)

def _validate(self, response: FieldRadio) -> Validation:
"""Validate this FieldRadio instance.
:param response: The form response from the user
:returns: Validation of the response
"""
validation = self.validator(choices=response.options)
if validation.error_msg:
self.valid = False
Expand Down
55 changes: 55 additions & 0 deletions src/ansible_navigator/ui_framework/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,22 @@ def __init__(self, form, screen, ui_config):

@property
def _field_win_start(self):
"""The window start of a field.
:returns: The window start of a field
"""
return self._input_start + self._pad_left

@property
def _field_win_width(self):
"""The window width of a field.
:returns: The window width of a field
"""
return self._screen_width - self._field_win_start

def _dimensions(self):
"""Calculate the dimensions of the form."""
self._prompt_end = max(len(form_field.full_prompt) for form_field in self._form.fields)
self._input_start = self._prompt_end + len(self._separator)

Expand Down Expand Up @@ -155,6 +164,10 @@ def _dimensions(self):
self._pad_left = max(int((self._screen_width - self._form_width) * LEFT_PAD_RATIO), 0)

def _generate_form(self) -> tuple[tuple[int, CursesLine], ...]:
"""Generate the form.
:returns: A tuple of tuples containing the line numbers and the lines
"""
lines = []
lines.append((self._line_number, self._generate_title()))
self._line_number += 1
Expand Down Expand Up @@ -217,6 +230,10 @@ def _generate_form(self) -> tuple[tuple[int, CursesLine], ...]:
return tuple(lines)

def _generate_buttons(self) -> CursesLine:
"""Generate the buttons.
:returns: A CursesLine containing the buttons
"""
line_parts = []
far_right = self._form_width
footer_fields = [field for field in self._form.fields if field.name in ["submit", "cancel"]]
Expand All @@ -240,12 +257,22 @@ def _generate_buttons(self) -> CursesLine:
return CursesLine(tuple(line_parts))

def _generate_error(self, form_field) -> CursesLine | None:
"""Generate the error for a field.
:param form_field: The field to generate the error for
:returns: A CursesLine containing the error
"""
if form_field.current_error:
line_part = CursesLinePart(self._input_start, form_field.current_error, 9, 0)
return CursesLine((line_part,))
return None

def _generate_field_options(self, form_field) -> CursesLines:
"""Generate the options for a field.
:param form_field: The field to generate the options for
:returns: A CursesLines containing the options
"""
window = curses.newwin(
len(form_field.options),
self._field_win_width,
Expand All @@ -264,6 +291,11 @@ def _generate_field_options(self, form_field) -> CursesLines:
return CursesLines(tuple(lines))

def _generate_field_text(self, form_field) -> CursesLinePart:
"""Generate the text for a field.
:param form_field: The field to generate the text for
:returns: A CursesLinePart containing the text
"""
window = curses.newwin(1, self._field_win_width, self._line_number, self._field_win_start)
window.keypad(True)
form_field.win = window
Expand All @@ -277,22 +309,41 @@ def _generate_field_text(self, form_field) -> CursesLinePart:
return CursesLinePart(self._input_start, text, color, 0)

def _generate_horizontal_line(self) -> CursesLine:
"""Generate a horizontal line.
:returns: A CursesLine containing the horizontal line
"""
line_part = CursesLinePart(0, "\u2500" * self._form_width, 8, 0)
return CursesLine((line_part,))

@staticmethod
def _generate_information(form_field) -> CursesLines:
"""Generate an information field.
:param form_field: The field to generate the information for
:returns: A CursesLines containing the information
"""
lines = tuple(
CursesLine((CursesLinePart(0, line, 0, 0),)) for line in form_field.information
)
return CursesLines(lines)

@staticmethod
def _generate_messages(form_field) -> CursesLines:
"""Generate a messages field.
:param form_field: The field to generate the messages for
:returns: A CursesLines containing the messages
"""
lines = tuple(CursesLine((CursesLinePart(0, line, 0, 0),)) for line in form_field.messages)
return CursesLines(lines)

def _generate_prompt(self, form_field) -> list[CursesLinePart]:
"""Generate the prompt for a field.
:param form_field: The field to generate the prompt for
:returns: A list of CursesLinePart containing the prompt
"""
prompt_start = self._prompt_end - len(form_field.full_prompt)
if form_field.valid is True:
color = 10
Expand All @@ -310,6 +361,10 @@ def _generate_prompt(self, form_field) -> list[CursesLinePart]:
return [cl_prompt, cl_default, cl_separator]

def _generate_title(self) -> CursesLine:
"""Generate the title for the form.
:returns: A CursesLine containing the title
"""
title = self._form.title
if title.isupper() or not title[0].isupper():
title = title.capitalize()
Expand Down
7 changes: 7 additions & 0 deletions src/ansible_navigator/ui_framework/form_handler_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ def _adjust_line_pointer(self, amount: int) -> None:
self.input_line_pointer = (self.input_line_pointer + amount) % len(self.input_line_cache)

def _do_command(self, char: int) -> int:
"""Handle the input from the user.
:param char: The character input from the user
:returns: 0 if the window needs to be resized
1 if the window should be repainted
-1 if the window should be closed
"""
# pylint: disable=too-many-branches

# in the case the term returns 127 instead of 263
Expand Down
5 changes: 5 additions & 0 deletions src/ansible_navigator/ui_framework/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,11 @@ def _filter_and_serialize(self, obj: Any) -> tuple[CursesLines | None, CursesLin
return heading, lines

def _show_form(self, obj: Form) -> Form:
"""Show a form on the display.
:param obj: The form to show
:returns: The form
"""
res = obj.present(screen=self._screen, ui_config=self._ui_config)
return res

Expand Down
7 changes: 7 additions & 0 deletions src/ansible_navigator/utils/serialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ def _prepare_content(
content_view: ContentView,
serialization_format: SerializationFormat,
) -> ContentType:
"""Prepare content for serialization.
:param content: The content to prepare
:param content_view: The content view
:param serialization_format: The serialization format
:returns: The prepared content
"""
if isinstance(content, (tuple, list)):
if all(is_dataclass(c) for c in content):
return [
Expand Down
8 changes: 8 additions & 0 deletions tests/unit/configuration_subsystem/test_presentable.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@

@pytest.fixture(name="sample_settings")
def _sample_settings():
"""Provide sample settings.
:return: A sample settings instance
"""
return ApplicationConfiguration(
application_name="app",
application_version="1.0",
Expand All @@ -41,6 +45,10 @@ def _sample_settings():

@pytest.fixture(name="settings_file_dict")
def _settings_file_dict():
"""Provide a sample settings file as a dictionary.
:return: A sample settings file as a dictionary
"""
return {
"choices": [],
"current_settings_file": "/test/path",
Expand Down
Loading

0 comments on commit d60324c

Please sign in to comment.