mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-05-07 13:52:54 +00:00
CI: add type checking (#10997)
* Set up type checking with mypy. * Make mypy pass. * Use list() instead of sorted().
This commit is contained in:
@@ -485,4 +485,4 @@ class CallbackModule(CallbackModule_default):
|
||||
|
||||
# When using -vv or higher, simply do the default action
|
||||
if display.verbosity >= 2 or not HAS_OD:
|
||||
CallbackModule = CallbackModule_default
|
||||
CallbackModule = CallbackModule_default # type: ignore
|
||||
|
||||
@@ -90,6 +90,7 @@ from ansible.errors import AnsibleError, AnsibleRuntimeError
|
||||
from ansible.module_utils.ansible_release import __version__ as ansible_version
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
ELASTIC_LIBRARY_IMPORT_ERROR: ImportError | None
|
||||
try:
|
||||
from elasticapm import Client, capture_span, trace_parent_from_string, instrument, label
|
||||
except ImportError as imp_exc:
|
||||
|
||||
@@ -206,7 +206,7 @@ else:
|
||||
sock.connect((self.LE_API, self.LE_TLS_PORT))
|
||||
self._conn = sock
|
||||
|
||||
SocketAppender = TLSSocketAppender
|
||||
SocketAppender = TLSSocketAppender # type: ignore
|
||||
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
|
||||
@@ -145,6 +145,7 @@ from ansible.errors import AnsibleError
|
||||
from ansible.module_utils.ansible_release import __version__ as ansible_version
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
OTEL_LIBRARY_IMPORT_ERROR: ImportError | None
|
||||
try:
|
||||
from opentelemetry import trace
|
||||
from opentelemetry.trace import SpanKind
|
||||
|
||||
@@ -28,7 +28,7 @@ try:
|
||||
from yaml import CSafeDumper as SafeDumper
|
||||
from yaml import CSafeLoader as SafeLoader
|
||||
except ImportError:
|
||||
from yaml import SafeDumper, SafeLoader
|
||||
from yaml import SafeDumper, SafeLoader # type: ignore
|
||||
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
|
||||
@@ -46,13 +46,13 @@ from ansible.module_utils.common.text.converters import to_text
|
||||
DONT_COLORIZE = False
|
||||
COLORS = {
|
||||
'normal': '\033[0m',
|
||||
'ok': f'\x1b[{C.COLOR_CODES[C.COLOR_OK]}m',
|
||||
'ok': f'\x1b[{C.COLOR_CODES[C.COLOR_OK]}m', # type: ignore
|
||||
'bold': '\033[1m',
|
||||
'not_so_bold': '\033[1m\033[34m',
|
||||
'changed': f'\x1b[{C.COLOR_CODES[C.COLOR_CHANGED]}m',
|
||||
'failed': f'\x1b[{C.COLOR_CODES[C.COLOR_ERROR]}m',
|
||||
'changed': f'\x1b[{C.COLOR_CODES[C.COLOR_CHANGED]}m', # type: ignore
|
||||
'failed': f'\x1b[{C.COLOR_CODES[C.COLOR_ERROR]}m', # type: ignore
|
||||
'endc': '\033[0m',
|
||||
'skipped': f'\x1b[{C.COLOR_CODES[C.COLOR_SKIP]}m',
|
||||
'skipped': f'\x1b[{C.COLOR_CODES[C.COLOR_SKIP]}m', # type: ignore
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -106,10 +106,10 @@ class Connection(ConnectionBase):
|
||||
host=self._instance())
|
||||
self._connected = True
|
||||
|
||||
def _build_command(self, cmd) -> str:
|
||||
def _build_command(self, cmd) -> list[str]:
|
||||
"""build the command to execute on the incus host"""
|
||||
|
||||
exec_cmd = [
|
||||
exec_cmd: list[str] = [
|
||||
self._incus_cmd,
|
||||
"--project", self.get_option("project"),
|
||||
"exec",
|
||||
|
||||
@@ -108,10 +108,10 @@ class Connection(ConnectionBase):
|
||||
self._display.vvv(f"ESTABLISH LXD CONNECTION FOR USER: {self.get_option('remote_user')}", host=self._host())
|
||||
self._connected = True
|
||||
|
||||
def _build_command(self, cmd) -> str:
|
||||
def _build_command(self, cmd) -> list[str]:
|
||||
"""build the command to execute on the lxd host"""
|
||||
|
||||
exec_cmd = [self._lxc_cmd]
|
||||
exec_cmd: list[str] = [self._lxc_cmd]
|
||||
|
||||
if self.get_option("project"):
|
||||
exec_cmd.extend(["--project", self.get_option("project")])
|
||||
|
||||
@@ -106,7 +106,7 @@ class Connection(ConnectionBase):
|
||||
super(Connection, self)._connect()
|
||||
self._connected = True
|
||||
|
||||
@ensure_connect
|
||||
@ensure_connect # type: ignore # TODO: for some reason, the type infos for ensure_connect suck...
|
||||
def exec_command(self, cmd, in_data=None, sudoable=False):
|
||||
"""Run specified command in a running QubesVM """
|
||||
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
||||
|
||||
@@ -332,31 +332,23 @@ from ansible.utils.path import makedirs_safe
|
||||
from binascii import hexlify
|
||||
from subprocess import list2cmdline
|
||||
|
||||
PARAMIKO_IMPORT_ERR: str | None
|
||||
try:
|
||||
import paramiko
|
||||
from paramiko import MissingHostKeyPolicy
|
||||
PARAMIKO_IMPORT_ERR = None
|
||||
except ImportError:
|
||||
paramiko = None
|
||||
PARAMIKO_IMPORT_ERR = traceback.format_exc()
|
||||
|
||||
|
||||
if t.TYPE_CHECKING and PARAMIKO_IMPORT_ERR is None:
|
||||
from paramiko import MissingHostKeyPolicy
|
||||
from paramiko.client import SSHClient
|
||||
from paramiko.pkey import PKey
|
||||
else:
|
||||
MissingHostKeyPolicy: type = object
|
||||
SSHClient: type = object
|
||||
PKey: type = object
|
||||
MissingHostKeyPolicy = object # type: ignore
|
||||
|
||||
|
||||
display = Display()
|
||||
|
||||
|
||||
def authenticity_msg(hostname: str, ktype: str, fingerprint: str) -> str:
|
||||
def authenticity_msg(hostname: str, ktype: str, fingerprint: bytes) -> str:
|
||||
msg = f"""
|
||||
paramiko: The authenticity of host '{hostname}' can't be established.
|
||||
The {ktype} key fingerprint is {fingerprint}.
|
||||
The {ktype} key fingerprint is {to_text(fingerprint)}.
|
||||
Are you sure you want to continue connecting (yes/no)?
|
||||
"""
|
||||
return msg
|
||||
@@ -376,7 +368,7 @@ class MyAddPolicy(MissingHostKeyPolicy):
|
||||
self.connection = connection
|
||||
self._options = connection._options
|
||||
|
||||
def missing_host_key(self, client: SSHClient, hostname: str, key: PKey) -> None:
|
||||
def missing_host_key(self, client: paramiko.SSHClient, hostname: str, key: paramiko.PKey) -> None:
|
||||
|
||||
if all((self.connection.get_option('host_key_checking'), not self.connection.get_option('host_key_auto_add'))):
|
||||
|
||||
@@ -396,10 +388,10 @@ class MyAddPolicy(MissingHostKeyPolicy):
|
||||
if inp.lower() not in ['yes', 'y', '']:
|
||||
raise AnsibleError('host connection rejected by user')
|
||||
|
||||
key._added_by_ansible_this_time = True
|
||||
key._added_by_ansible_this_time = True # type: ignore
|
||||
|
||||
# existing implementation below:
|
||||
client._host_keys.add(hostname, key.get_name(), key)
|
||||
client._host_keys.add(hostname, key.get_name(), key) # type: ignore[attr-defined] # TODO: figure out what _host_keys is!
|
||||
|
||||
# host keys are actually saved in close() function below
|
||||
# in order to control ordering.
|
||||
@@ -540,7 +532,7 @@ class Connection(ConnectionBase):
|
||||
return self
|
||||
|
||||
def _any_keys_added(self) -> bool:
|
||||
for hostname, keys in self.ssh._host_keys.items():
|
||||
for hostname, keys in self.ssh._host_keys.items(): # type: ignore[attr-defined] # TODO: figure out what _host_keys is!
|
||||
for keytype, key in keys.items():
|
||||
added_this_time = getattr(key, '_added_by_ansible_this_time', False)
|
||||
if added_this_time:
|
||||
@@ -560,14 +552,14 @@ class Connection(ConnectionBase):
|
||||
makedirs_safe(path)
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
for hostname, keys in self.ssh._host_keys.items():
|
||||
for hostname, keys in self.ssh._host_keys.items(): # type: ignore[attr-defined] # TODO: figure out what _host_keys is!
|
||||
for keytype, key in keys.items():
|
||||
# was f.write
|
||||
added_this_time = getattr(key, '_added_by_ansible_this_time', False)
|
||||
if not added_this_time:
|
||||
f.write(f'{hostname} {keytype} {key.get_base64()}\n')
|
||||
|
||||
for hostname, keys in self.ssh._host_keys.items():
|
||||
for hostname, keys in self.ssh._host_keys.items(): # type: ignore[attr-defined] # TODO: figure out what _host_keys is!
|
||||
for keytype, key in keys.items():
|
||||
added_this_time = getattr(key, '_added_by_ansible_this_time', False)
|
||||
if added_this_time:
|
||||
@@ -595,13 +587,16 @@ class Connection(ConnectionBase):
|
||||
|
||||
cmd = self._build_wsl_command(cmd)
|
||||
|
||||
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
||||
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable) # type: ignore[safe-super]
|
||||
|
||||
bufsize = 4096
|
||||
|
||||
try:
|
||||
self.ssh.get_transport().set_keepalive(5)
|
||||
chan = self.ssh.get_transport().open_session()
|
||||
transport = self.ssh.get_transport()
|
||||
if transport is None:
|
||||
raise ValueError("Transport not available")
|
||||
transport.set_keepalive(5)
|
||||
chan = transport.open_session()
|
||||
except Exception as e:
|
||||
text_e = to_text(e)
|
||||
msg = 'Failed to open session'
|
||||
@@ -745,7 +740,7 @@ class Connection(ConnectionBase):
|
||||
# just in case any were added recently
|
||||
|
||||
self.ssh.load_system_host_keys()
|
||||
self.ssh._host_keys.update(self.ssh._system_host_keys)
|
||||
self.ssh._host_keys.update(self.ssh._system_host_keys) # type: ignore[attr-defined] # TODO this is a HACK!
|
||||
|
||||
# gather information about the current key file, so
|
||||
# we can ensure the new file has the correct mode/owner
|
||||
|
||||
@@ -16,7 +16,7 @@ from ansible.module_utils.common.collections import is_sequence
|
||||
try:
|
||||
from ansible.errors import AnsibleTypeError
|
||||
except ImportError:
|
||||
from ansible.errors import AnsibleFilterTypeError as AnsibleTypeError
|
||||
from ansible.errors import AnsibleFilterTypeError as AnsibleTypeError # type: ignore
|
||||
|
||||
try:
|
||||
from hashids import Hashids
|
||||
|
||||
@@ -3,17 +3,18 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typing as t
|
||||
from json import loads
|
||||
from typing import TYPE_CHECKING
|
||||
from ansible.errors import AnsibleFilterError
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
if t.TYPE_CHECKING:
|
||||
from typing import Any, Callable, Union
|
||||
|
||||
JSONPATCH_IMPORT_ERROR: ImportError | None
|
||||
try:
|
||||
import jsonpatch
|
||||
|
||||
except ImportError as exc:
|
||||
HAS_LIB = False
|
||||
JSONPATCH_IMPORT_ERROR = exc
|
||||
@@ -82,7 +83,7 @@ class FilterModule:
|
||||
"You need to install 'jsonpatch' package prior to running 'json_patch' filter"
|
||||
) from JSONPATCH_IMPORT_ERROR
|
||||
|
||||
args = {"op": op, "path": path}
|
||||
args: dict[str, t.Any] = {"op": op, "path": path}
|
||||
from_arg = kwargs.pop("from", None)
|
||||
fail_test = kwargs.pop("fail_test", False)
|
||||
|
||||
|
||||
@@ -11,15 +11,16 @@ from yaml import dump
|
||||
try:
|
||||
from yaml.cyaml import CSafeDumper as SafeDumper
|
||||
except ImportError:
|
||||
from yaml import SafeDumper
|
||||
from yaml import SafeDumper # type: ignore
|
||||
|
||||
from ansible.module_utils.common.collections import is_sequence
|
||||
try:
|
||||
# This is ansible-core 2.19+
|
||||
from ansible.utils.vars import transform_to_native_types
|
||||
from ansible.parsing.vault import VaultHelper, VaultLib
|
||||
HAS_TRANSFORM_TO_NATIVE_TYPES = True
|
||||
except ImportError:
|
||||
transform_to_native_types = None
|
||||
HAS_TRANSFORM_TO_NATIVE_TYPES = False
|
||||
|
||||
from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
|
||||
from ansible.utils.unsafe_proxy import AnsibleUnsafe
|
||||
@@ -31,7 +32,7 @@ def _to_native_types_compat(value: t.Any, *, redact_value: str | None) -> t.Any:
|
||||
return value
|
||||
if isinstance(value, AnsibleUnsafe):
|
||||
# This only works up to ansible-core 2.18:
|
||||
return _to_native_types_compat(value._strip_unsafe(), redact_value=redact_value)
|
||||
return _to_native_types_compat(value._strip_unsafe(), redact_value=redact_value) # type: ignore
|
||||
# But that's fine, since this code path isn't taken on ansible-core 2.19+ anyway.
|
||||
if isinstance(value, Mapping):
|
||||
return {
|
||||
@@ -74,10 +75,10 @@ def remove_all_tags(value: t.Any, *, redact_sensitive_values: bool = False) -> t
|
||||
|
||||
If ``redact_sensitive_values`` is ``True``, all sensitive values will be redacted.
|
||||
"""
|
||||
if transform_to_native_types is not None:
|
||||
if HAS_TRANSFORM_TO_NATIVE_TYPES:
|
||||
return _to_native_types(value, redact=redact_sensitive_values)
|
||||
|
||||
return _to_native_types_compat(
|
||||
return _to_native_types_compat( # type: ignore[unreachable]
|
||||
value,
|
||||
redact_value="<redacted>" if redact_sensitive_values else None, # same string as in ansible-core 2.19 by transform_to_native_types()
|
||||
)
|
||||
|
||||
@@ -52,7 +52,7 @@ from ansible.errors import AnsibleFilterError
|
||||
try:
|
||||
from ansible.errors import AnsibleTypeError
|
||||
except ImportError:
|
||||
from ansible.errors import AnsibleFilterTypeError as AnsibleTypeError
|
||||
from ansible.errors import AnsibleFilterTypeError as AnsibleTypeError # type: ignore
|
||||
|
||||
|
||||
def unicode_normalize(data, form='NFC'):
|
||||
|
||||
@@ -179,6 +179,7 @@ from ansible.errors import AnsibleError, AnsibleParserError
|
||||
from ansible_collections.community.general.plugins.module_utils.lxd import LXDClient, LXDClientException
|
||||
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||
|
||||
IPADDRESS_IMPORT_ERROR: ImportError | None
|
||||
try:
|
||||
import ipaddress
|
||||
except ImportError as exc:
|
||||
|
||||
@@ -118,6 +118,7 @@ variables:
|
||||
import os
|
||||
import json
|
||||
|
||||
YAML_IMPORT_ERROR: ImportError | None
|
||||
try:
|
||||
import yaml
|
||||
except ImportError as exc:
|
||||
|
||||
@@ -244,7 +244,7 @@ class Bitwarden(object):
|
||||
out, err = self._run(params)
|
||||
|
||||
# This includes things that matched in different fields.
|
||||
initial_matches = AnsibleJSONDecoder().raw_decode(out)[0]
|
||||
initial_matches = AnsibleJSONDecoder().raw_decode(out)[0] # type: ignore[operator]
|
||||
|
||||
# Filter to only return the ID of a collections with exactly matching name
|
||||
return [item['id'] for item in initial_matches
|
||||
|
||||
@@ -82,7 +82,7 @@ except ImportError:
|
||||
HAS_PYTHON_JWT = False # vs pyjwt
|
||||
if HAS_JWT and hasattr(jwt, 'JWT'):
|
||||
HAS_PYTHON_JWT = True
|
||||
from jwt import jwk_from_pem, JWT
|
||||
from jwt import jwk_from_pem, JWT # type: ignore[attr-defined]
|
||||
jwt_instance = JWT()
|
||||
|
||||
try:
|
||||
|
||||
@@ -65,6 +65,7 @@ from ansible.plugins.lookup import LookupBase
|
||||
from ansible.utils.display import Display
|
||||
from ansible.errors import AnsibleError
|
||||
|
||||
ANOTHER_LIBRARY_IMPORT_ERROR: ImportError | None
|
||||
try:
|
||||
from pam.revbits_ansible.server import SecretServer
|
||||
except ImportError as imp_exc:
|
||||
|
||||
@@ -11,10 +11,11 @@ import traceback
|
||||
from operator import itemgetter
|
||||
|
||||
|
||||
PARAMIKO_IMPORT_ERROR: str | None
|
||||
try:
|
||||
from paramiko.config import SSHConfig
|
||||
except ImportError:
|
||||
SSHConfig = object
|
||||
SSHConfig = object # type: ignore
|
||||
HAS_PARAMIKO = False
|
||||
PARAMIKO_IMPORT_ERROR = traceback.format_exc()
|
||||
else:
|
||||
|
||||
@@ -4,10 +4,17 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typing as t
|
||||
|
||||
from functools import wraps
|
||||
|
||||
from ansible.module_utils.common.collections import is_sequence
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from collections.abc import Callable
|
||||
|
||||
ArgFormatType = Callable[[t.Any], list[str]]
|
||||
|
||||
|
||||
def _ensure_list(value):
|
||||
return list(value) if is_sequence(value) else [value]
|
||||
|
||||
@@ -9,6 +9,7 @@ from __future__ import annotations
|
||||
import copy
|
||||
import json
|
||||
import re
|
||||
import typing as t
|
||||
from urllib import error as urllib_error
|
||||
from urllib.parse import urlencode
|
||||
|
||||
@@ -118,12 +119,12 @@ class _ConsulModule:
|
||||
As such backwards incompatible changes can occur even in bugfix releases.
|
||||
"""
|
||||
|
||||
api_endpoint = None # type: str
|
||||
unique_identifiers = None # type: list
|
||||
result_key = None # type: str
|
||||
create_only_fields = set()
|
||||
operational_attributes = set()
|
||||
params = {}
|
||||
api_endpoint: str | None = None
|
||||
unique_identifiers: list | None = None
|
||||
result_key: str | None = None
|
||||
create_only_fields: set[str] = set()
|
||||
operational_attributes: set[str] = set()
|
||||
params: dict[str, t.Any] = {}
|
||||
|
||||
def __init__(self, module):
|
||||
self._module = module
|
||||
|
||||
@@ -4,12 +4,16 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.module_utils.common.dict_transformations import dict_merge
|
||||
from ansible_collections.community.general.plugins.module_utils import cmd_runner_fmt
|
||||
from ansible_collections.community.general.plugins.module_utils.python_runner import PythonRunner
|
||||
from ansible_collections.community.general.plugins.module_utils.module_helper import ModuleHelper
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from .cmd_runner_fmt import ArgFormatType
|
||||
|
||||
|
||||
django_std_args = dict(
|
||||
# environmental options
|
||||
@@ -32,7 +36,7 @@ _pks = dict(
|
||||
primary_keys=dict(type="list", elements="str"),
|
||||
)
|
||||
|
||||
_django_std_arg_fmts = dict(
|
||||
_django_std_arg_fmts: dict[str, ArgFormatType] = dict(
|
||||
all=cmd_runner_fmt.as_bool("--all"),
|
||||
app=cmd_runner_fmt.as_opt_val("--app"),
|
||||
apps=cmd_runner_fmt.as_list(),
|
||||
@@ -95,11 +99,11 @@ class _DjangoRunner(PythonRunner):
|
||||
|
||||
class DjangoModuleHelper(ModuleHelper):
|
||||
module = {}
|
||||
django_admin_cmd = None
|
||||
arg_formats = {}
|
||||
django_admin_arg_order = ()
|
||||
_django_args = []
|
||||
_check_mode_arg = ""
|
||||
django_admin_cmd: str | None = None
|
||||
arg_formats: dict[str, ArgFormatType] = {}
|
||||
django_admin_arg_order: tuple[str, ...] | str = ()
|
||||
_django_args: list[str] = []
|
||||
_check_mode_arg: str = ""
|
||||
|
||||
def __init__(self):
|
||||
self.module["argument_spec"], self.arg_formats = self._build_args(self.module.get("argument_spec", {}),
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.module_utils.basic import missing_required_lib
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
||||
@@ -15,7 +17,7 @@ from urllib.parse import urljoin
|
||||
import traceback
|
||||
|
||||
|
||||
def _determine_list_all_kwargs(version):
|
||||
def _determine_list_all_kwargs(version) -> dict[str, t.Any]:
|
||||
gitlab_version = LooseVersion(version)
|
||||
if gitlab_version >= LooseVersion('4.0.0'):
|
||||
# 4.0.0 removed 'as_list'
|
||||
@@ -27,14 +29,14 @@ def _determine_list_all_kwargs(version):
|
||||
return {'as_list': False, 'all': True, 'per_page': 100}
|
||||
|
||||
|
||||
GITLAB_IMP_ERR = None
|
||||
GITLAB_IMP_ERR: str | None = None
|
||||
try:
|
||||
import gitlab
|
||||
import requests
|
||||
HAS_GITLAB_PACKAGE = True
|
||||
list_all_kwargs = _determine_list_all_kwargs(gitlab.__version__)
|
||||
except Exception:
|
||||
gitlab = None
|
||||
gitlab = None # type: ignore
|
||||
GITLAB_IMP_ERR = traceback.format_exc()
|
||||
HAS_GITLAB_PACKAGE = False
|
||||
list_all_kwargs = {}
|
||||
|
||||
@@ -20,7 +20,7 @@ from urllib.parse import urlparse
|
||||
try:
|
||||
from hashlib import sha1
|
||||
except ImportError:
|
||||
import sha as sha1
|
||||
import sha as sha1 # type: ignore[no-redef]
|
||||
|
||||
HASHED_KEY_MAGIC = "|1|"
|
||||
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.community.general.plugins.module_utils.mh.exceptions import ModuleHelperException as _MHE
|
||||
from ansible_collections.community.general.plugins.module_utils.mh.deco import module_fails_on_exception
|
||||
|
||||
|
||||
class ModuleHelperBase(object):
|
||||
module = None
|
||||
module: dict[str, t.Any] | None = None # TODO: better spec using t.TypedDict
|
||||
ModuleHelperException = _MHE
|
||||
_delegated_to_module = (
|
||||
_delegated_to_module: tuple[str, ...] = (
|
||||
'check_mode', 'get_bin_path', 'warn', 'deprecate', 'debug',
|
||||
)
|
||||
|
||||
|
||||
@@ -5,13 +5,15 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
|
||||
|
||||
class ModuleHelperException(Exception):
|
||||
def __init__(self, msg, update_output=None, *args, **kwargs):
|
||||
self.msg = to_native(msg or f"Module failed with exception: {self}")
|
||||
def __init__(self, msg: str, update_output: dict[str, t.Any] | None = None, *args, **kwargs):
|
||||
self.msg: str = to_native(msg or f"Module failed with exception: {self}")
|
||||
if update_output is None:
|
||||
update_output = {}
|
||||
self.update_output = update_output
|
||||
self.update_output: dict[str, t.Any] = update_output
|
||||
super(ModuleHelperException, self).__init__(*args)
|
||||
|
||||
@@ -7,8 +7,8 @@ from __future__ import annotations
|
||||
|
||||
|
||||
class StateMixin(object):
|
||||
state_param = 'state'
|
||||
default_state = None
|
||||
state_param: str = 'state'
|
||||
default_state: str | None = None
|
||||
|
||||
def _state(self):
|
||||
state = self.module.params.get(self.state_param)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typing as t
|
||||
|
||||
from ansible.module_utils.common.dict_transformations import dict_merge
|
||||
|
||||
@@ -13,13 +14,16 @@ from ansible_collections.community.general.plugins.module_utils.mh.base import M
|
||||
from ansible_collections.community.general.plugins.module_utils.mh.mixins.state import StateMixin
|
||||
from ansible_collections.community.general.plugins.module_utils.mh.mixins.deprecate_attrs import DeprecateAttrsMixin
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from collections.abc import Sequence
|
||||
|
||||
|
||||
class ModuleHelper(DeprecateAttrsMixin, ModuleHelperBase):
|
||||
facts_name = None
|
||||
output_params = ()
|
||||
diff_params = ()
|
||||
change_params = ()
|
||||
facts_params = ()
|
||||
facts_name: str | None = None
|
||||
output_params: Sequence[str] = ()
|
||||
diff_params: Sequence[str] = ()
|
||||
change_params: Sequence[str] = ()
|
||||
facts_params: Sequence[str] = ()
|
||||
|
||||
def __init__(self, module=None):
|
||||
super(ModuleHelper, self).__init__(module)
|
||||
|
||||
@@ -19,12 +19,11 @@ from ansible_collections.community.general.plugins.module_utils.datetime import
|
||||
now,
|
||||
)
|
||||
|
||||
SCALEWAY_SECRET_IMP_ERR = None
|
||||
SCALEWAY_SECRET_IMP_ERR: str | None = None
|
||||
try:
|
||||
from passlib.hash import argon2
|
||||
HAS_SCALEWAY_SECRET_PACKAGE = True
|
||||
except Exception:
|
||||
argon2 = None
|
||||
SCALEWAY_SECRET_IMP_ERR = traceback.format_exc()
|
||||
HAS_SCALEWAY_SECRET_PACKAGE = False
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ __all__ = [
|
||||
]
|
||||
|
||||
|
||||
_singletons = {}
|
||||
_singletons: dict[str, object] = {}
|
||||
|
||||
|
||||
def ldap_module():
|
||||
@@ -61,7 +61,7 @@ def ldap_module():
|
||||
return orig_ldap
|
||||
|
||||
|
||||
def _singleton(name, constructor):
|
||||
def _singleton(name: str, constructor):
|
||||
if name in _singletons:
|
||||
return _singletons[name]
|
||||
_singletons[name] = constructor()
|
||||
|
||||
@@ -129,6 +129,7 @@ from ansible.module_utils.basic import (
|
||||
)
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
|
||||
RPM_PYTHON_IMPORT_ERROR: str | None
|
||||
try:
|
||||
import rpm
|
||||
except ImportError:
|
||||
|
||||
@@ -114,14 +114,7 @@ EXAMPLES = r"""
|
||||
msg: Task completed ... with feeling.
|
||||
"""
|
||||
|
||||
try:
|
||||
from html import escape as html_escape
|
||||
except ImportError:
|
||||
# Python-3.2 or later
|
||||
import cgi
|
||||
|
||||
def html_escape(text, quote=True):
|
||||
return cgi.escape(text, quote)
|
||||
from html import escape as html_escape
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.urls import fetch_url
|
||||
|
||||
@@ -166,10 +166,11 @@ def main():
|
||||
|
||||
|
||||
class Crypttab(object):
|
||||
_lines = []
|
||||
_lines: list[str]
|
||||
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self._lines = []
|
||||
if not os.path.exists(path):
|
||||
if not os.path.exists(os.path.dirname(path)):
|
||||
os.makedirs(os.path.dirname(path))
|
||||
|
||||
@@ -201,16 +201,16 @@ class Device(object):
|
||||
|
||||
class Filesystem(object):
|
||||
|
||||
MKFS = None
|
||||
MKFS_FORCE_FLAGS = []
|
||||
MKFS_SET_UUID_OPTIONS = None
|
||||
MKFS_SET_UUID_EXTRA_OPTIONS = []
|
||||
INFO = None
|
||||
GROW = None
|
||||
GROW_MAX_SPACE_FLAGS = []
|
||||
MKFS: str | None = None
|
||||
MKFS_FORCE_FLAGS: list[str] | None = []
|
||||
MKFS_SET_UUID_OPTIONS: list[str] | None = None
|
||||
MKFS_SET_UUID_EXTRA_OPTIONS: list[str] | None = []
|
||||
INFO: str | None = None
|
||||
GROW: str | None = None
|
||||
GROW_MAX_SPACE_FLAGS: list[str] | None = []
|
||||
GROW_MOUNTPOINT_ONLY = False
|
||||
CHANGE_UUID = None
|
||||
CHANGE_UUID_OPTION = None
|
||||
CHANGE_UUID: str | None = None
|
||||
CHANGE_UUID_OPTION: str | None = None
|
||||
CHANGE_UUID_OPTION_HAS_ARG = True
|
||||
|
||||
LANG_ENV = {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}
|
||||
|
||||
@@ -273,6 +273,7 @@ from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible.module_utils.basic import jsonify
|
||||
from ansible.module_utils.common.text.formatters import human_to_bytes
|
||||
|
||||
CRYPT_IMPORT_ERROR: str | None
|
||||
try:
|
||||
import crypt
|
||||
except ImportError:
|
||||
@@ -282,6 +283,7 @@ else:
|
||||
HAS_CRYPT = True
|
||||
CRYPT_IMPORT_ERROR = None
|
||||
|
||||
LEGACYCRYPT_IMPORT_ERROR: str | None
|
||||
try:
|
||||
import legacycrypt
|
||||
if not HAS_CRYPT:
|
||||
|
||||
@@ -112,7 +112,9 @@ from ansible.module_utils.common.text.converters import to_native
|
||||
|
||||
|
||||
with deps.declare("passlib"):
|
||||
from passlib.apache import HtpasswdFile, htpasswd_context
|
||||
# Apparently the type infos don't know htpasswd_context, which *does* exist
|
||||
# (but isn't mentioned in the documentation for some reason)
|
||||
from passlib.apache import HtpasswdFile, htpasswd_context # type: ignore[attr-defined]
|
||||
from passlib.context import CryptContext
|
||||
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ IS_PYTHON_2 = sys.version_info[0] <= 2
|
||||
|
||||
|
||||
class JenkinsNode:
|
||||
def __init__(self, module):
|
||||
def __init__(self, module: AnsibleModule) -> None:
|
||||
self.module = module
|
||||
|
||||
self.name = module.params['name']
|
||||
@@ -174,7 +174,7 @@ class JenkinsNode:
|
||||
self.url = module.params['url']
|
||||
self.num_executors = module.params['num_executors']
|
||||
self.labels = module.params['labels']
|
||||
self.offline_message = module.params['offline_message'] # type: str | None
|
||||
self.offline_message: str | None = module.params['offline_message']
|
||||
|
||||
if self.offline_message is not None:
|
||||
self.offline_message = self.offline_message.strip()
|
||||
|
||||
@@ -74,7 +74,7 @@ class PacemakerInfo(ModuleHelper):
|
||||
"constraint_info": "constraint",
|
||||
"property_info": "property"
|
||||
}
|
||||
output_params = info_vars.keys()
|
||||
output_params = list(info_vars.keys())
|
||||
|
||||
def __init_module__(self):
|
||||
self.runner = pacemaker_runner(self.module)
|
||||
|
||||
@@ -209,6 +209,7 @@ import re
|
||||
import traceback
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib, human_to_bytes
|
||||
|
||||
XMLTODICT_LIBRARY_IMPORT_ERROR: str | None
|
||||
try:
|
||||
import xmltodict
|
||||
except ImportError:
|
||||
|
||||
@@ -347,7 +347,7 @@ RHEV_UNAVAILABLE = 2
|
||||
RHEV_TYPE_OPTS = ['desktop', 'host', 'server']
|
||||
STATE_OPTS = ['absent', 'cd', 'down', 'info', 'ping', 'present', 'restart', 'up']
|
||||
|
||||
msg = []
|
||||
msg: list[str] = []
|
||||
changed = False
|
||||
failed = False
|
||||
|
||||
@@ -1258,7 +1258,7 @@ def setChanged():
|
||||
changed = True
|
||||
|
||||
|
||||
def setMsg(message):
|
||||
def setMsg(message: str) -> None:
|
||||
msg.append(message)
|
||||
|
||||
|
||||
|
||||
@@ -328,6 +328,7 @@ from ansible_collections.community.general.plugins.module_utils.univention_umc i
|
||||
base_dn,
|
||||
)
|
||||
|
||||
CRYPT_IMPORT_ERROR: str | None
|
||||
try:
|
||||
import crypt
|
||||
except ImportError:
|
||||
@@ -337,6 +338,7 @@ else:
|
||||
HAS_CRYPT = True
|
||||
CRYPT_IMPORT_ERROR = None
|
||||
|
||||
LEGACYCRYPT_IMPORT_ERROR: str | None
|
||||
try:
|
||||
import legacycrypt
|
||||
if not HAS_CRYPT:
|
||||
|
||||
@@ -10,8 +10,9 @@ from collections.abc import Mapping
|
||||
try:
|
||||
# Introduced with Data Tagging (https://github.com/ansible/ansible/pull/84621):
|
||||
from ansible.module_utils.datatag import native_type_name as _native_type_name
|
||||
HAS_NATIVE_TYPE_NAME = True
|
||||
except ImportError:
|
||||
_native_type_name = None
|
||||
HAS_NATIVE_TYPE_NAME = False
|
||||
|
||||
|
||||
def _atype(data, alias, *, use_native_type: bool = False):
|
||||
@@ -19,7 +20,7 @@ def _atype(data, alias, *, use_native_type: bool = False):
|
||||
Returns the name of the type class.
|
||||
"""
|
||||
|
||||
if use_native_type and _native_type_name:
|
||||
if use_native_type and HAS_NATIVE_TYPE_NAME:
|
||||
data_type = _native_type_name(data)
|
||||
else:
|
||||
data_type = type(data).__name__
|
||||
|
||||
@@ -43,7 +43,7 @@ from ansible.plugins.loader import action_loader, module_loader
|
||||
try:
|
||||
from ansible.errors import AnsiblePluginRemovedError
|
||||
except ImportError:
|
||||
AnsiblePluginRemovedError = Exception
|
||||
AnsiblePluginRemovedError = Exception # type: ignore
|
||||
|
||||
|
||||
def a_module(term):
|
||||
|
||||
@@ -65,6 +65,7 @@ _value:
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
|
||||
ANOTHER_LIBRARY_IMPORT_ERROR: ImportError | None
|
||||
try:
|
||||
from fqdn import FQDN
|
||||
except ImportError as imp_exc:
|
||||
|
||||
Reference in New Issue
Block a user