From 4cb8babb81e526622d60eba6e3df3d92e42e3c88 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 17 Oct 2025 13:50:21 +0200 Subject: [PATCH] Make mypy pass. --- plugins/module_utils/_api/_import_helper.py | 21 +++++++++++-------- .../_api/transport/npipesocket.py | 1 + .../module_utils/_api/transport/sshconn.py | 1 + plugins/module_utils/_api/utils/fnmatch.py | 2 +- plugins/module_utils/_common.py | 16 +++++++------- plugins/module_utils/_common_api.py | 2 +- plugins/module_utils/_compose_v2.py | 7 ++++--- .../module_utils/_module_container/base.py | 15 +++++++++---- plugins/module_utils/_socket_helper.py | 6 +++--- plugins/module_utils/_util.py | 6 ++++-- .../_api/transport/test_ssladapter.py | 2 +- .../module_utils/_api/utils/test_config.py | 4 ++-- .../module_utils/compose_v2_test_cases.py | 2 +- 13 files changed, 51 insertions(+), 34 deletions(-) diff --git a/plugins/module_utils/_api/_import_helper.py b/plugins/module_utils/_api/_import_helper.py index 01f7f18e..b2f7bc38 100644 --- a/plugins/module_utils/_api/_import_helper.py +++ b/plugins/module_utils/_api/_import_helper.py @@ -12,8 +12,10 @@ from __future__ import annotations import traceback +import typing as t +REQUESTS_IMPORT_ERROR: str | None # pylint: disable=invalid-name try: from requests import Session # noqa: F401, pylint: disable=unused-import from requests.adapters import ( # noqa: F401, pylint: disable=unused-import @@ -26,28 +28,29 @@ try: except ImportError: REQUESTS_IMPORT_ERROR = traceback.format_exc() # pylint: disable=invalid-name - class Session: - __attrs__ = [] + class Session: # type: ignore + __attrs__: list[t.Never] = [] - class HTTPAdapter: - __attrs__ = [] + class HTTPAdapter: # type: ignore + __attrs__: list[t.Never] = [] - class HTTPError(Exception): + class HTTPError(Exception): # type: ignore pass - class InvalidSchema(Exception): + class InvalidSchema(Exception): # type: ignore pass else: REQUESTS_IMPORT_ERROR = None # pylint: disable=invalid-name -URLLIB3_IMPORT_ERROR = None # pylint: disable=invalid-name +URLLIB3_IMPORT_ERROR: str | None = None # pylint: disable=invalid-name try: from requests.packages import urllib3 # pylint: disable=unused-import - # pylint: disable-next=unused-import - from requests.packages.urllib3 import connection as urllib3_connection + from requests.packages.urllib3 import ( # type: ignore # pylint: disable=unused-import # isort: skip + connection as urllib3_connection, + ) except ImportError: try: import urllib3 # pylint: disable=unused-import diff --git a/plugins/module_utils/_api/transport/npipesocket.py b/plugins/module_utils/_api/transport/npipesocket.py index 1f5fcb50..23183c39 100644 --- a/plugins/module_utils/_api/transport/npipesocket.py +++ b/plugins/module_utils/_api/transport/npipesocket.py @@ -17,6 +17,7 @@ import time import traceback +PYWIN32_IMPORT_ERROR: str | None # pylint: disable=invalid-name try: import pywintypes import win32api diff --git a/plugins/module_utils/_api/transport/sshconn.py b/plugins/module_utils/_api/transport/sshconn.py index 028f8f16..40fbce4c 100644 --- a/plugins/module_utils/_api/transport/sshconn.py +++ b/plugins/module_utils/_api/transport/sshconn.py @@ -25,6 +25,7 @@ from .._import_helper import HTTPAdapter, urllib3, urllib3_connection from .basehttpadapter import BaseHTTPAdapter +PARAMIKO_IMPORT_ERROR: str | None # pylint: disable=invalid-name try: import paramiko except ImportError: diff --git a/plugins/module_utils/_api/utils/fnmatch.py b/plugins/module_utils/_api/utils/fnmatch.py index 7fefa4e7..234226c2 100644 --- a/plugins/module_utils/_api/utils/fnmatch.py +++ b/plugins/module_utils/_api/utils/fnmatch.py @@ -28,7 +28,7 @@ import re __all__ = ["fnmatch", "fnmatchcase", "translate"] -_cache = {} +_cache: dict[str, re.Pattern] = {} _MAXCACHE = 100 diff --git a/plugins/module_utils/_common.py b/plugins/module_utils/_common.py index 80fb4ab7..79076c90 100644 --- a/plugins/module_utils/_common.py +++ b/plugins/module_utils/_common.py @@ -36,6 +36,9 @@ from ansible_collections.community.docker.plugins.module_utils._version import ( HAS_DOCKER_PY_2 = False # pylint: disable=invalid-name HAS_DOCKER_PY_3 = False # pylint: disable=invalid-name +HAS_DOCKER_ERROR: None | str # pylint: disable=invalid-name +HAS_DOCKER_TRACEBACK: None | str # pylint: disable=invalid-name +docker_version: str | None # pylint: disable=invalid-name try: from docker import __version__ as docker_version @@ -51,12 +54,13 @@ try: HAS_DOCKER_PY_2 = True # pylint: disable=invalid-name from docker import APIClient as Client else: - from docker import Client + from docker import Client # type: ignore except ImportError as exc: HAS_DOCKER_ERROR = str(exc) # pylint: disable=invalid-name HAS_DOCKER_TRACEBACK = traceback.format_exc() # pylint: disable=invalid-name HAS_DOCKER_PY = False # pylint: disable=invalid-name + docker_version = None # pylint: disable=invalid-name else: HAS_DOCKER_PY = True # pylint: disable=invalid-name HAS_DOCKER_ERROR = None # pylint: disable=invalid-name @@ -71,7 +75,7 @@ except ImportError: # Either Docker SDK for Python is no longer using requests, or Docker SDK for Python is not around either, # or Docker SDK for Python's dependency requests is missing. In any case, define an exception # class RequestException so that our code does not break. - class RequestException(Exception): + class RequestException(Exception): # type: ignore pass @@ -79,18 +83,16 @@ MIN_DOCKER_VERSION = "2.0.0" if not HAS_DOCKER_PY: - docker_version = None # pylint: disable=invalid-name - # No Docker SDK for Python. Create a place holder client to allow # instantiation of AnsibleModule and proper error handing - class Client: # noqa: F811, pylint: disable=function-redefined + class Client: # type: ignore # noqa: F811, pylint: disable=function-redefined def __init__(self, **kwargs): pass - class APIError(Exception): # noqa: F811, pylint: disable=function-redefined + class APIError(Exception): # type: ignore # noqa: F811, pylint: disable=function-redefined pass - class NotFound(Exception): # noqa: F811, pylint: disable=function-redefined + class NotFound(Exception): # type: ignore # noqa: F811, pylint: disable=function-redefined pass diff --git a/plugins/module_utils/_common_api.py b/plugins/module_utils/_common_api.py index 067f1c84..d58cf65d 100644 --- a/plugins/module_utils/_common_api.py +++ b/plugins/module_utils/_common_api.py @@ -28,7 +28,7 @@ try: ) except ImportError: # Define an exception class RequestException so that our code does not break. - class RequestException(Exception): + class RequestException(Exception): # type: ignore pass diff --git a/plugins/module_utils/_compose_v2.py b/plugins/module_utils/_compose_v2.py index 6a37ec28..9bac4671 100644 --- a/plugins/module_utils/_compose_v2.py +++ b/plugins/module_utils/_compose_v2.py @@ -14,6 +14,7 @@ import re import shutil import tempfile import traceback +import typing as t from collections import namedtuple from shlex import quote @@ -34,6 +35,7 @@ from ansible_collections.community.docker.plugins.module_utils._version import ( ) +PYYAML_IMPORT_ERROR: None | str # pylint: disable=invalid-name try: import yaml @@ -41,7 +43,7 @@ try: # use C version if possible for speedup from yaml import CSafeDumper as _SafeDumper except ImportError: - from yaml import SafeDumper as _SafeDumper + from yaml import SafeDumper as _SafeDumper # type: ignore except ImportError: HAS_PYYAML = False PYYAML_IMPORT_ERROR = traceback.format_exc() # pylint: disable=invalid-name @@ -144,8 +146,7 @@ class ResourceType: SERVICE = "service" @classmethod - def from_docker_compose_event(cls, resource_type): - # type: (Type[ResourceType], Text) -> Any + def from_docker_compose_event(cls, resource_type: str) -> t.Any: return { "Network": cls.NETWORK, "Image": cls.IMAGE, diff --git a/plugins/module_utils/_module_container/base.py b/plugins/module_utils/_module_container/base.py index b68ebac1..e68072a8 100644 --- a/plugins/module_utils/_module_container/base.py +++ b/plugins/module_utils/_module_container/base.py @@ -12,6 +12,7 @@ import abc import os import re import shlex +import typing as t from functools import partial from ansible.module_utils.common.text.converters import to_text @@ -32,6 +33,12 @@ from ansible_collections.community.docker.plugins.module_utils._util import ( ) +if t.TYPE_CHECKING: + from ansible_collections.community.docker.plugins.module_utils._version import ( + LooseVersion, + ) + + _DEFAULT_IP_REPLACEMENT_STRING = ( "[[DEFAULT_IP:iewahhaeB4Sae6Aen8IeShairoh4zeph7xaekoh8Geingunaesaeweiy3ooleiwi]]" ) @@ -207,9 +214,9 @@ class OptionGroup: class Engine: - min_api_version = None # string or None - min_api_version_obj = None # LooseVersion object or None - extra_option_minimal_versions = None # dict[str, dict[str, Any]] or None + min_api_version: str | None = None + min_api_version_obj: LooseVersion | None = None + extra_option_minimal_versions: dict[str, dict[str, t.Any]] | None = None @abc.abstractmethod def get_value(self, module, container, api_version, options, image, host_info): @@ -268,7 +275,7 @@ class Engine: class EngineDriver: - name = None # string + name: str @abc.abstractmethod def setup( diff --git a/plugins/module_utils/_socket_helper.py b/plugins/module_utils/_socket_helper.py index 6158f4e5..20555510 100644 --- a/plugins/module_utils/_socket_helper.py +++ b/plugins/module_utils/_socket_helper.py @@ -11,7 +11,7 @@ import fcntl import os import os.path import socket as pysocket -import typing as t +from collections.abc import Callable def make_file_unblocking(file) -> None: @@ -43,7 +43,7 @@ def _empty_writer(msg: str) -> None: pass -def shutdown_writing(sock, log: t.Callable[[str], None] = _empty_writer) -> None: +def shutdown_writing(sock, log: Callable[[str], None] = _empty_writer) -> None: # FIXME: This does **not work with SSLSocket**! Apparently SSLSocket does not allow to send # a close_notify TLS alert without completely shutting down the connection. # Calling sock.shutdown(pysocket.SHUT_WR) simply turns of TLS encryption and from that @@ -63,7 +63,7 @@ def shutdown_writing(sock, log: t.Callable[[str], None] = _empty_writer) -> None log("No idea how to signal end of writing") -def write_to_socket(sock, data: bytes) -> None: +def write_to_socket(sock, data: bytes) -> int: if hasattr(sock, "_send_until_done"): # WrappedSocket (urllib3/contrib/pyopenssl) does not have `send`, but # only `sendall`, which uses `_send_until_done` under the hood. diff --git a/plugins/module_utils/_util.py b/plugins/module_utils/_util.py index 5022c582..5171fae6 100644 --- a/plugins/module_utils/_util.py +++ b/plugins/module_utils/_util.py @@ -69,9 +69,11 @@ DOCKER_COMMON_ARGS_VARS = { if option_name != "debug" } -DOCKER_MUTUALLY_EXCLUSIVE = [] +DOCKER_MUTUALLY_EXCLUSIVE: list[tuple[str, ...] | list[str]] = [] -DOCKER_REQUIRED_TOGETHER = [["client_cert", "client_key"]] +DOCKER_REQUIRED_TOGETHER: list[tuple[str, ...] | list[str]] = [ + ["client_cert", "client_key"] +] DEFAULT_DOCKER_REGISTRY = "https://index.docker.io/v1/" BYTE_SUFFIXES = ["B", "KB", "MB", "GB", "TB", "PB"] diff --git a/tests/unit/plugins/module_utils/_api/transport/test_ssladapter.py b/tests/unit/plugins/module_utils/_api/transport/test_ssladapter.py index e2b71763..f1ea023f 100644 --- a/tests/unit/plugins/module_utils/_api/transport/test_ssladapter.py +++ b/tests/unit/plugins/module_utils/_api/transport/test_ssladapter.py @@ -19,7 +19,7 @@ from ansible_collections.community.docker.plugins.module_utils._api.transport im try: - from ssl import CertificateError, match_hostname + from ssl import CertificateError, match_hostname # type: ignore except ImportError: HAS_MATCH_HOSTNAME = False # pylint: disable=invalid-name else: diff --git a/tests/unit/plugins/module_utils/_api/utils/test_config.py b/tests/unit/plugins/module_utils/_api/utils/test_config.py index 93378402..cbe8bf0d 100644 --- a/tests/unit/plugins/module_utils/_api/utils/test_config.py +++ b/tests/unit/plugins/module_utils/_api/utils/test_config.py @@ -12,8 +12,8 @@ import json import os import shutil import tempfile -import typing as t import unittest +from collections.abc import Callable from unittest import mock from pytest import fixture, mark @@ -22,7 +22,7 @@ from ansible_collections.community.docker.plugins.module_utils._api.utils import class FindConfigFileTest(unittest.TestCase): - mkdir: t.Callable[[str], os.PathLike[str]] + mkdir: Callable[[str], os.PathLike[str]] @fixture(autouse=True) def tmpdir(self, tmpdir): diff --git a/tests/unit/plugins/module_utils/compose_v2_test_cases.py b/tests/unit/plugins/module_utils/compose_v2_test_cases.py index c9da99a6..be41ebd9 100644 --- a/tests/unit/plugins/module_utils/compose_v2_test_cases.py +++ b/tests/unit/plugins/module_utils/compose_v2_test_cases.py @@ -11,7 +11,7 @@ from ansible_collections.community.docker.plugins.module_utils._compose_v2 impor ) -EVENT_TEST_CASES = [ +EVENT_TEST_CASES: list[tuple[str, str, bool, bool, str, list[Event], list[Event]]] = [ # ####################################################################################################################### # ## Docker Compose 2.18.1 ############################################################################################## # #######################################################################################################################