Add typing information, 2/n (#1178)

* Add typing to Docker Stack modules. Clean modules up.

* Add typing to Docker Swarm modules.

* Add typing to unit tests.

* Add more typing.

* Add ignore.txt entries.
This commit is contained in:
Felix Fontein
2025-10-25 01:16:04 +02:00
committed by GitHub
parent 3350283bcc
commit 6ad4bfcd40
84 changed files with 1496 additions and 1161 deletions
@@ -11,6 +11,7 @@
from __future__ import annotations
import typing as t
from queue import Empty
from .. import constants
@@ -19,6 +20,12 @@ from .basehttpadapter import BaseHTTPAdapter
from .npipesocket import NpipeSocket
if t.TYPE_CHECKING:
from collections.abc import Mapping
from requests import PreparedRequest
RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer
@@ -91,7 +98,9 @@ class NpipeHTTPAdapter(BaseHTTPAdapter):
)
super().__init__()
def get_connection(self, url: str | bytes, proxies=None) -> NpipeHTTPConnectionPool:
def get_connection(
self, url: str | bytes, proxies: Mapping[str, str] | None = None
) -> NpipeHTTPConnectionPool:
with self.pools.lock:
pool = self.pools.get(url)
if pool:
@@ -104,7 +113,9 @@ class NpipeHTTPAdapter(BaseHTTPAdapter):
return pool
def request_url(self, request, proxies) -> str:
def request_url(
self, request: PreparedRequest, proxies: Mapping[str, str] | None
) -> str:
# The select_proxy utility in requests errors out when the provided URL
# does not have a hostname, like is the case when using a UNIX socket.
# Since proxies are an irrelevant notion in the case of UNIX sockets
@@ -64,7 +64,7 @@ class NpipeSocket:
implemented.
"""
def __init__(self, handle=None) -> None:
def __init__(self, handle: t.Any | None = None) -> None:
self._timeout = win32pipe.NMPWAIT_USE_DEFAULT_WAIT
self._handle = handle
self._address: str | None = None
@@ -74,15 +74,17 @@ class NpipeSocket:
def accept(self) -> t.NoReturn:
raise NotImplementedError()
def bind(self, address) -> t.NoReturn:
def bind(self, address: t.Any) -> t.NoReturn:
raise NotImplementedError()
def close(self) -> None:
if self._handle is None:
raise ValueError("Handle not present")
self._handle.Close()
self._closed = True
@check_closed
def connect(self, address, retry_count: int = 0) -> None:
def connect(self, address: str, retry_count: int = 0) -> None:
try:
handle = win32file.CreateFile(
address,
@@ -116,11 +118,11 @@ class NpipeSocket:
self._address = address
@check_closed
def connect_ex(self, address) -> None:
def connect_ex(self, address: str) -> None:
self.connect(address)
@check_closed
def detach(self):
def detach(self) -> t.Any:
self._closed = True
return self._handle
@@ -134,16 +136,18 @@ class NpipeSocket:
def getsockname(self) -> str | None:
return self._address
def getsockopt(self, level, optname, buflen=None) -> t.NoReturn:
def getsockopt(
self, level: t.Any, optname: t.Any, buflen: t.Any = None
) -> t.NoReturn:
raise NotImplementedError()
def ioctl(self, control, option) -> t.NoReturn:
def ioctl(self, control: t.Any, option: t.Any) -> t.NoReturn:
raise NotImplementedError()
def listen(self, backlog) -> t.NoReturn:
def listen(self, backlog: t.Any) -> t.NoReturn:
raise NotImplementedError()
def makefile(self, mode: str, bufsize: int | None = None):
def makefile(self, mode: str, bufsize: int | None = None) -> t.IO[bytes]:
if mode.strip("b") != "r":
raise NotImplementedError()
rawio = NpipeFileIOBase(self)
@@ -153,6 +157,8 @@ class NpipeSocket:
@check_closed
def recv(self, bufsize: int, flags: int = 0) -> str:
if self._handle is None:
raise ValueError("Handle not present")
dummy_err, data = win32file.ReadFile(self._handle, bufsize)
return data
@@ -169,6 +175,8 @@ class NpipeSocket:
@check_closed
def recv_into(self, buf: Buffer, nbytes: int = 0) -> int:
if self._handle is None:
raise ValueError("Handle not present")
readbuf = buf if isinstance(buf, memoryview) else memoryview(buf)
event = win32event.CreateEvent(None, True, True, None)
@@ -188,6 +196,8 @@ class NpipeSocket:
@check_closed
def send(self, string: Buffer, flags: int = 0) -> int:
if self._handle is None:
raise ValueError("Handle not present")
event = win32event.CreateEvent(None, True, True, None)
try:
overlapped = pywintypes.OVERLAPPED()
@@ -210,7 +220,7 @@ class NpipeSocket:
self.connect(address)
return self.send(string)
def setblocking(self, flag: bool):
def setblocking(self, flag: bool) -> None:
if flag:
return self.settimeout(None)
return self.settimeout(0)
@@ -228,16 +238,16 @@ class NpipeSocket:
def gettimeout(self) -> int | float | None:
return self._timeout
def setsockopt(self, level, optname, value) -> t.NoReturn:
def setsockopt(self, level: t.Any, optname: t.Any, value: t.Any) -> t.NoReturn:
raise NotImplementedError()
@check_closed
def shutdown(self, how) -> None:
def shutdown(self, how: t.Any) -> None:
return self.close()
class NpipeFileIOBase(io.RawIOBase):
def __init__(self, npipe_socket) -> None:
def __init__(self, npipe_socket: NpipeSocket | None) -> None:
self.sock = npipe_socket
def close(self) -> None:
@@ -245,7 +255,10 @@ class NpipeFileIOBase(io.RawIOBase):
self.sock = None
def fileno(self) -> int:
return self.sock.fileno()
if self.sock is None:
raise RuntimeError("socket is closed")
# TODO: This is definitely a bug, NpipeSocket.fileno() does not exist!
return self.sock.fileno() # type: ignore
def isatty(self) -> bool:
return False
@@ -254,6 +267,8 @@ class NpipeFileIOBase(io.RawIOBase):
return True
def readinto(self, buf: Buffer) -> int:
if self.sock is None:
raise RuntimeError("socket is closed")
return self.sock.recv_into(buf)
def seekable(self) -> bool:
+17 -14
View File
@@ -35,7 +35,7 @@ else:
PARAMIKO_IMPORT_ERROR = None # pylint: disable=invalid-name
if t.TYPE_CHECKING:
from collections.abc import Buffer
from collections.abc import Buffer, Mapping
RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer
@@ -67,7 +67,7 @@ class SSHSocket(socket.socket):
preexec_func = None
if not constants.IS_WINDOWS_PLATFORM:
def f():
def f() -> None:
signal.signal(signal.SIGINT, signal.SIG_IGN)
preexec_func = f
@@ -100,13 +100,13 @@ class SSHSocket(socket.socket):
self.proc.stdin.flush()
return written
def sendall(self, data: Buffer, *args, **kwargs) -> None:
def sendall(self, data: Buffer, *args: t.Any, **kwargs: t.Any) -> None:
self._write(data)
def send(self, data: Buffer, *args, **kwargs) -> int:
def send(self, data: Buffer, *args: t.Any, **kwargs: t.Any) -> int:
return self._write(data)
def recv(self, n: int, *args, **kwargs) -> bytes:
def recv(self, n: int, *args: t.Any, **kwargs: t.Any) -> bytes:
if not self.proc:
raise RuntimeError(
"SSH subprocess not initiated. connect() must be called first."
@@ -114,7 +114,7 @@ class SSHSocket(socket.socket):
assert self.proc.stdout is not None
return self.proc.stdout.read(n)
def makefile(self, mode: str, *args, **kwargs) -> t.IO: # type: ignore
def makefile(self, mode: str, *args: t.Any, **kwargs: t.Any) -> t.IO: # type: ignore
if not self.proc:
self.connect()
assert self.proc is not None
@@ -138,7 +138,7 @@ class SSHConnection(urllib3_connection.HTTPConnection):
def __init__(
self,
*,
ssh_transport=None,
ssh_transport: paramiko.Transport | None = None,
timeout: int | float = 60,
host: str,
) -> None:
@@ -146,18 +146,19 @@ class SSHConnection(urllib3_connection.HTTPConnection):
self.ssh_transport = ssh_transport
self.timeout = timeout
self.ssh_host = host
self.sock: paramiko.Channel | SSHSocket | None = None
def connect(self) -> None:
if self.ssh_transport:
sock = self.ssh_transport.open_session()
sock.settimeout(self.timeout)
sock.exec_command("docker system dial-stdio")
channel = self.ssh_transport.open_session()
channel.settimeout(self.timeout)
channel.exec_command("docker system dial-stdio")
self.sock = channel
else:
sock = SSHSocket(self.ssh_host)
sock.settimeout(self.timeout)
sock.connect()
self.sock = sock
self.sock = sock
class SSHConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
@@ -172,7 +173,7 @@ class SSHConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
host: str,
) -> None:
super().__init__("localhost", timeout=timeout, maxsize=maxsize)
self.ssh_transport = None
self.ssh_transport: paramiko.Transport | None = None
self.timeout = timeout
if ssh_client:
self.ssh_transport = ssh_client.get_transport()
@@ -276,7 +277,9 @@ class SSHHTTPAdapter(BaseHTTPAdapter):
if self.ssh_client:
self.ssh_client.connect(**self.ssh_params)
def get_connection(self, url: str | bytes, proxies=None) -> SSHConnectionPool:
def get_connection(
self, url: str | bytes, proxies: Mapping[str, str] | None = None
) -> SSHConnectionPool:
if not self.ssh_client:
return SSHConnectionPool(
ssh_client=self.ssh_client,
@@ -33,7 +33,7 @@ class SSLHTTPAdapter(BaseHTTPAdapter):
def __init__(
self,
assert_hostname: bool | None = None,
**kwargs,
**kwargs: t.Any,
) -> None:
self.assert_hostname = assert_hostname
super().__init__(**kwargs)
@@ -51,7 +51,7 @@ class SSLHTTPAdapter(BaseHTTPAdapter):
self.poolmanager = PoolManager(**kwargs)
def get_connection(self, *args, **kwargs) -> urllib3.ConnectionPool:
def get_connection(self, *args: t.Any, **kwargs: t.Any) -> urllib3.ConnectionPool:
"""
Ensure assert_hostname is set correctly on our pool
@@ -19,12 +19,20 @@ from .._import_helper import HTTPAdapter, urllib3, urllib3_connection
from .basehttpadapter import BaseHTTPAdapter
if t.TYPE_CHECKING:
from collections.abc import Mapping
from requests import PreparedRequest
from ..._socket_helper import SocketLike
RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer
class UnixHTTPConnection(urllib3_connection.HTTPConnection):
def __init__(
self, base_url: str | bytes, unix_socket, timeout: int | float = 60
self, base_url: str | bytes, unix_socket: str, timeout: int | float = 60
) -> None:
super().__init__("localhost", timeout=timeout)
self.base_url = base_url
@@ -43,7 +51,7 @@ class UnixHTTPConnection(urllib3_connection.HTTPConnection):
if header == "Connection" and "Upgrade" in values:
self.disable_buffering = True
def response_class(self, sock, *args, **kwargs) -> t.Any:
def response_class(self, sock: SocketLike, *args: t.Any, **kwargs: t.Any) -> t.Any:
# FIXME: We may need to disable buffering on Py3,
# but there's no clear way to do it at the moment. See:
# https://github.com/docker/docker-py/issues/1799
@@ -88,12 +96,16 @@ class UnixHTTPAdapter(BaseHTTPAdapter):
self.socket_path = socket_path
self.timeout = timeout
self.max_pool_size = max_pool_size
self.pools = RecentlyUsedContainer(
pool_connections, dispose_func=lambda p: p.close()
)
def f(p: t.Any) -> None:
p.close()
self.pools = RecentlyUsedContainer(pool_connections, dispose_func=f)
super().__init__()
def get_connection(self, url: str | bytes, proxies=None) -> UnixHTTPConnectionPool:
def get_connection(
self, url: str | bytes, proxies: Mapping[str, str] | None = None
) -> UnixHTTPConnectionPool:
with self.pools.lock:
pool = self.pools.get(url)
if pool:
@@ -106,7 +118,7 @@ class UnixHTTPAdapter(BaseHTTPAdapter):
return pool
def request_url(self, request, proxies) -> str:
def request_url(self, request: PreparedRequest, proxies: Mapping[str, str]) -> str:
# The select_proxy utility in requests errors out when the provided URL
# does not have a hostname, like is the case when using a UNIX socket.
# Since proxies are an irrelevant notion in the case of UNIX sockets