From e57de70c2a93872779d0c3b20fce6bdaf918b167 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 21 Nov 2025 18:19:36 +0100 Subject: [PATCH] Address UP014: use NamedTuple class syntax (#11168) * Address UP014: use NamedTuple class syntax. * Convert type comments to type hints. --- .../fragments/11168-homebrew_service.yml | 2 + plugins/modules/homebrew_services.py | 39 ++++++++++--------- ruff.toml | 1 - 3 files changed, 23 insertions(+), 19 deletions(-) create mode 100644 changelogs/fragments/11168-homebrew_service.yml diff --git a/changelogs/fragments/11168-homebrew_service.yml b/changelogs/fragments/11168-homebrew_service.yml new file mode 100644 index 0000000000..7b038fae82 --- /dev/null +++ b/changelogs/fragments/11168-homebrew_service.yml @@ -0,0 +1,2 @@ +bugfixes: + - "homebrew_service - slightly refactor code (https://github.com/ansible-collections/community.general/pull/11168)." diff --git a/plugins/modules/homebrew_services.py b/plugins/modules/homebrew_services.py index d474a2fb41..562cc477a0 100644 --- a/plugins/modules/homebrew_services.py +++ b/plugins/modules/homebrew_services.py @@ -87,7 +87,7 @@ running: """ import json -from typing import NamedTuple, Optional +import typing as t from ansible.module_utils.basic import AnsibleModule from ansible_collections.community.general.plugins.module_utils.homebrew import ( @@ -95,16 +95,22 @@ from ansible_collections.community.general.plugins.module_utils.homebrew import parse_brew_path, ) + # Stores validated arguments for an instance of an action. # See DOCUMENTATION string for argument-specific information. -HomebrewServiceArgs = NamedTuple("HomebrewServiceArgs", [("name", str), ("state", str), ("brew_path", str)]) +class HomebrewServiceArgs(t.NamedTuple): + name: str + state: str + brew_path: str + # Stores the state of a Homebrew service. -HomebrewServiceState = NamedTuple("HomebrewServiceState", [("running", bool), ("pid", Optional[int])]) +class HomebrewServiceState(t.NamedTuple): + running: bool + pid: int | None -def _brew_service_state(args, module): - # type: (HomebrewServiceArgs, AnsibleModule) -> HomebrewServiceState +def _brew_service_state(args: HomebrewServiceArgs, module: AnsibleModule) -> HomebrewServiceState: cmd = [args.brew_path, "services", "info", args.name, "--json"] rc, stdout, stderr = module.run_command(cmd, check_rc=True) @@ -116,22 +122,22 @@ def _brew_service_state(args, module): return HomebrewServiceState(running=data["status"] == "started", pid=data["pid"]) -def _exit_with_state(args, module, changed=False, message=None): - # type: (HomebrewServiceArgs, AnsibleModule, bool, Optional[str]) -> None +def _exit_with_state( + args: HomebrewServiceArgs, module: AnsibleModule, changed: bool = False, message: str | None = None +) -> None: state = _brew_service_state(args, module) if message is None: message = f"Running: {state.running}, Changed: {changed}, PID: {state.pid}" module.exit_json(msg=message, pid=state.pid, running=state.running, changed=changed) -def validate_and_load_arguments(module): - # type: (AnsibleModule) -> HomebrewServiceArgs +def validate_and_load_arguments(module: AnsibleModule) -> HomebrewServiceArgs: """Reuse the Homebrew module's validation logic to validate these arguments.""" - package = module.params["name"] # type: ignore + package: str = module.params["name"] if not HomebrewValidate.valid_package(package): module.fail_json(msg=f"Invalid package name: {package}") - state = module.params["state"] # type: ignore + state: t.Literal["present", "absent", "restarted"] = module.params["state"] if state not in ["present", "absent", "restarted"]: module.fail_json(msg=f"Invalid state: {state}") @@ -140,8 +146,7 @@ def validate_and_load_arguments(module): return HomebrewServiceArgs(name=package, state=state, brew_path=brew_path) -def start_service(args, module): - # type: (HomebrewServiceArgs, AnsibleModule) -> None +def start_service(args: HomebrewServiceArgs, module: AnsibleModule) -> None: """Start the requested brew service if it is not already running.""" state = _brew_service_state(args, module) if state.running: @@ -157,8 +162,7 @@ def start_service(args, module): _exit_with_state(args, module, changed=True) -def stop_service(args, module): - # type: (HomebrewServiceArgs, AnsibleModule) -> None +def stop_service(args: HomebrewServiceArgs, module: AnsibleModule) -> None: """Stop the requested brew service if it is running.""" state = _brew_service_state(args, module) if not state.running: @@ -174,8 +178,7 @@ def stop_service(args, module): _exit_with_state(args, module, changed=True) -def restart_service(args, module): - # type: (HomebrewServiceArgs, AnsibleModule) -> None +def restart_service(args: HomebrewServiceArgs, module: AnsibleModule) -> None: """Restart the requested brew service. This always results in a change.""" if module.check_mode: _exit_with_state(args, module, changed=True, message="Service would be restarted") @@ -186,7 +189,7 @@ def restart_service(args, module): _exit_with_state(args, module, changed=True) -def main(): +def main() -> None: module = AnsibleModule( argument_spec=dict( name=dict( diff --git a/ruff.toml b/ruff.toml index 03324b31e8..093f5a2ecc 100644 --- a/ruff.toml +++ b/ruff.toml @@ -21,7 +21,6 @@ ignore = [ "B905", # zip-without-explicit-strict - needs Python 3.10+ "UP045", # Use `X | None` for type annotations - needs Python 3.10+ # To fix: - "UP014", # Convert `xxx` from `NamedTuple` functional to class syntax "UP024", # Replace aliased errors with `OSError` "UP030", # Use implicit references for positional format fields "UP031", # Use format specifiers instead of percent format