Skip to content

Commit

Permalink
[3.8] Enforce strict mypy checks
Browse files Browse the repository at this point in the history
This change covers the entire codebase with strict typings
and makes the ignores granular.

PR aio-libs#5370 by @derlih.
(cherry picked from commit 742a8b6)

Co-authored-by: Dmitry Erlikh <derlih@gmail.com>
  • Loading branch information
derlih committed Jan 21, 2021
1 parent f086e92 commit 9e3a28a
Show file tree
Hide file tree
Showing 37 changed files with 307 additions and 200 deletions.
24 changes: 24 additions & 0 deletions .mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[mypy]
warn_unused_configs = True
strict = True

[mypy-aiodns]
ignore_missing_imports = True

[mypy-brotli]
ignore_missing_imports = True

[mypy-gunicorn.*]
ignore_missing_imports = True

[mypy-uvloop]
ignore_missing_imports = True

[mypy-cchardet]
ignore_missing_imports = True

[mypy-tokio]
ignore_missing_imports = True

[mypy-asynctest]
ignore_missing_imports = True
1 change: 1 addition & 0 deletions CHANGES/3927.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Use ``mypy --strict``
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fmt format:

.PHONY: mypy
mypy:
mypy aiohttp
mypy --show-error-codes aiohttp

.develop: .install-deps $(call to-hash,$(PYS) $(CYS) $(CS))
pip install -e .
Expand Down
8 changes: 4 additions & 4 deletions aiohttp/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
try:
from ssl import SSLContext
except ImportError: # pragma: no cover
SSLContext = object # type: ignore
SSLContext = object # type: ignore[misc,assignment]


@attr.s(auto_attribs=True, frozen=True, slots=True)
Expand Down Expand Up @@ -265,7 +265,7 @@ def __init__(
stacklevel=2,
)
else:
self._timeout = timeout # type: ignore
self._timeout = timeout # type: ignore[assignment]
if read_timeout is not sentinel:
raise ValueError(
"read_timeout and timeout parameters "
Expand Down Expand Up @@ -421,7 +421,7 @@ async def _request(
real_timeout = self._timeout # type: ClientTimeout
else:
if not isinstance(timeout, ClientTimeout):
real_timeout = ClientTimeout(total=timeout) # type: ignore
real_timeout = ClientTimeout(total=timeout) # type: ignore[arg-type]
else:
real_timeout = timeout
# timeout is cumulative for all request operations
Expand Down Expand Up @@ -1101,7 +1101,7 @@ def __init__(self, coro: Coroutine["asyncio.Future[Any]", None, _RetType]) -> No
def send(self, arg: None) -> "asyncio.Future[Any]":
return self._coro.send(arg)

def throw(self, arg: BaseException) -> None: # type: ignore
def throw(self, arg: BaseException) -> None: # type: ignore[arg-type,override]
self._coro.throw(arg)

def close(self) -> None:
Expand Down
6 changes: 3 additions & 3 deletions aiohttp/client_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

SSLContext = ssl.SSLContext
except ImportError: # pragma: no cover
ssl = SSLContext = None # type: ignore
ssl = SSLContext = None # type: ignore[assignment]


if TYPE_CHECKING: # pragma: no cover
Expand Down Expand Up @@ -303,11 +303,11 @@ class ClientSSLError(ClientConnectorError):
ssl_error_bases = (ClientSSLError,)


class ClientConnectorSSLError(*ssl_error_bases): # type: ignore
class ClientConnectorSSLError(*ssl_error_bases): # type: ignore[misc]
"""Response ssl error."""


class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore
class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore[misc]
"""Response certificate error."""

def __init__(
Expand Down
33 changes: 18 additions & 15 deletions aiohttp/client_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@
import ssl
from ssl import SSLContext
except ImportError: # pragma: no cover
ssl = None # type: ignore
SSLContext = object # type: ignore
ssl = None # type: ignore[assignment]
SSLContext = object # type: ignore[misc,assignment]

try:
import cchardet as chardet
except ImportError: # pragma: no cover
import chardet # type: ignore
import chardet # type: ignore[no-redef]


__all__ = ("ClientRequest", "ClientResponse", "RequestInfo", "Fingerprint")
Expand Down Expand Up @@ -399,9 +399,9 @@ def update_headers(self, headers: Optional[LooseHeaders]) -> None:

if headers:
if isinstance(headers, (dict, MultiDictProxy, MultiDict)):
headers = headers.items() # type: ignore
headers = headers.items() # type: ignore[assignment]

for key, value in headers: # type: ignore
for key, value in headers: # type: ignore[misc]
# A special case for Host header
if key.lower() == "host":
self.headers[key] = value
Expand All @@ -413,7 +413,7 @@ def update_auto_headers(self, skip_auto_headers: Iterable[str]) -> None:
(hdr, None) for hdr in sorted(skip_auto_headers)
)
used_headers = self.headers.copy()
used_headers.extend(self.skip_auto_headers) # type: ignore
used_headers.extend(self.skip_auto_headers) # type: ignore[arg-type]

for hdr, val in self.DEFAULT_HEADERS.items():
if hdr not in used_headers:
Expand All @@ -435,15 +435,15 @@ def update_cookies(self, cookies: Optional[LooseCookies]) -> None:
if isinstance(cookies, Mapping):
iter_cookies = cookies.items()
else:
iter_cookies = cookies # type: ignore
iter_cookies = cookies # type: ignore[assignment]
for name, value in iter_cookies:
if isinstance(value, Morsel):
# Preserve coded_value
mrsl_val = value.get(value.key, Morsel())
mrsl_val.set(value.key, value.value, value.coded_value)
c[name] = mrsl_val
else:
c[name] = value # type: ignore
c[name] = value # type: ignore[assignment]

self.headers[hdrs.COOKIE] = c.output(header="", sep=";").strip()

Expand Down Expand Up @@ -585,10 +585,10 @@ async def write_bytes(
await self.body.write(writer)
else:
if isinstance(self.body, (bytes, bytearray)):
self.body = (self.body,) # type: ignore
self.body = (self.body,) # type: ignore[assignment]

for chunk in self.body:
await writer.write(chunk) # type: ignore
await writer.write(chunk) # type: ignore[arg-type]

await writer.write_eof()
except OSError as exc:
Expand Down Expand Up @@ -878,7 +878,7 @@ def links(self) -> "MultiDictProxy[MultiDictProxy[Union[str, URL]]]":

link.add(key, value)

key = link.get("rel", url) # type: ignore
key = link.get("rel", url) # type: ignore[assignment]

link.add("url", self.url.join(URL(url)))

Expand All @@ -896,7 +896,8 @@ async def start(self, connection: "Connection") -> "ClientResponse":
while True:
# read response
try:
message, payload = await self._protocol.read() # type: ignore
protocol = self._protocol
message, payload = await protocol.read() # type: ignore[union-attr]
except http.HttpProcessingError as exc:
raise ClientResponseError(
self.request_info,
Expand Down Expand Up @@ -1049,7 +1050,7 @@ async def read(self) -> bytes:
elif self._released:
raise ClientConnectionError("Connection closed")

return self._body
return self._body # type: ignore[no-any-return]

def get_encoding(self) -> str:
ctype = self.headers.get(hdrs.CONTENT_TYPE, "").lower()
Expand Down Expand Up @@ -1087,7 +1088,9 @@ async def text(self, encoding: Optional[str] = None, errors: str = "strict") ->
if encoding is None:
encoding = self.get_encoding()

return self._body.decode(encoding, errors=errors) # type: ignore
return self._body.decode( # type: ignore[no-any-return,union-attr]
encoding, errors=errors
)

async def json(
self,
Expand All @@ -1112,7 +1115,7 @@ async def json(
headers=self.headers,
)

stripped = self._body.strip() # type: ignore
stripped = self._body.strip() # type: ignore[union-attr]
if not stripped:
return None

Expand Down
10 changes: 5 additions & 5 deletions aiohttp/client_ws.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""WebSocket client for asyncio."""

import asyncio
from typing import Any, Optional
from typing import Any, Optional, cast

import async_timeout

Expand Down Expand Up @@ -57,10 +57,10 @@ def __init__(
self._autoclose = autoclose
self._autoping = autoping
self._heartbeat = heartbeat
self._heartbeat_cb = None
self._heartbeat_cb: Optional[asyncio.TimerHandle] = None
if heartbeat is not None:
self._pong_heartbeat = heartbeat / 2.0
self._pong_response_cb = None
self._pong_response_cb: Optional[asyncio.TimerHandle] = None
self._loop = loop
self._waiting = None # type: Optional[asyncio.Future[bool]]
self._exception = None # type: Optional[BaseException]
Expand Down Expand Up @@ -273,13 +273,13 @@ async def receive_str(self, *, timeout: Optional[float] = None) -> str:
msg = await self.receive(timeout)
if msg.type != WSMsgType.TEXT:
raise TypeError(f"Received message {msg.type}:{msg.data!r} is not str")
return msg.data
return cast(str, msg.data)

async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:
msg = await self.receive(timeout)
if msg.type != WSMsgType.BINARY:
raise TypeError(f"Received message {msg.type}:{msg.data!r} is not bytes")
return msg.data
return cast(bytes, msg.data)

async def receive_json(
self,
Expand Down
22 changes: 12 additions & 10 deletions aiohttp/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@

SSLContext = ssl.SSLContext
except ImportError: # pragma: no cover
ssl = None # type: ignore
SSLContext = object # type: ignore
ssl = None # type: ignore[assignment]
SSLContext = object # type: ignore[misc,assignment]


__all__ = ("BaseConnector", "TCPConnector", "UnixConnector", "NamedPipeConnector")
Expand Down Expand Up @@ -250,18 +250,18 @@ def __init__(
self._force_close = force_close

# {host_key: FIFO list of waiters}
self._waiters = defaultdict(deque) # type: ignore
self._waiters = defaultdict(deque) # type: ignore[var-annotated]

self._loop = loop
self._factory = functools.partial(ResponseHandler, loop=loop)

self.cookies = SimpleCookie() # type: SimpleCookie[str]

# start keep-alive connection cleanup task
self._cleanup_handle = None
self._cleanup_handle: Optional[asyncio.TimerHandle] = None

# start cleanup closed transports task
self._cleanup_closed_handle = None
self._cleanup_closed_handle: Optional[asyncio.TimerHandle] = None
self._cleanup_closed_disabled = not enable_cleanup_closed
self._cleanup_closed_transports = [] # type: List[Optional[asyncio.Transport]]
self._cleanup_closed()
Expand Down Expand Up @@ -844,7 +844,7 @@ async def _resolve_host(
for trace in traces:
await trace.send_dns_resolvehost_end(host)

return res
return res # type: ignore[no-any-return]

key = (host, port)

Expand Down Expand Up @@ -980,7 +980,7 @@ async def _wrap_create_connection(
) -> Tuple[asyncio.Transport, ResponseHandler]:
try:
async with ceil_timeout(timeout.sock_connect):
return await self._loop.create_connection(*args, **kwargs) # type: ignore # noqa
return await self._loop.create_connection(*args, **kwargs) # type: ignore[return-value] # noqa
except cert_errors as exc:
raise ClientConnectorCertificateError(req.connection_key, exc) from exc
except ssl_errors as exc:
Expand Down Expand Up @@ -1069,7 +1069,7 @@ async def _create_proxy_connection(
) -> Tuple[asyncio.Transport, ResponseHandler]:
headers = {} # type: Dict[str, str]
if req.proxy_headers is not None:
headers = req.proxy_headers # type: ignore
headers = req.proxy_headers # type: ignore[assignment]
headers[hdrs.HOST] = req.headers[hdrs.HOST]

url = req.proxy
Expand Down Expand Up @@ -1244,7 +1244,9 @@ def __init__(
limit_per_host=limit_per_host,
loop=loop,
)
if not isinstance(self._loop, asyncio.ProactorEventLoop): # type: ignore
if not isinstance(
self._loop, asyncio.ProactorEventLoop # type: ignore[attr-defined]
):
raise RuntimeError(
"Named Pipes only available in proactor " "loop under windows"
)
Expand All @@ -1260,7 +1262,7 @@ async def _create_connection(
) -> ResponseHandler:
try:
async with ceil_timeout(timeout.sock_connect):
_, proto = await self._loop.create_pipe_connection( # type: ignore
_, proto = await self._loop.create_pipe_connection( # type: ignore[attr-defined] # noqa: E501
self._factory, self._path
)
# the drain is required so that the connection_made is called
Expand Down
2 changes: 1 addition & 1 deletion aiohttp/cookiejar.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> No
for name, cookie in cookies:
if not isinstance(cookie, Morsel):
tmp = SimpleCookie() # type: SimpleCookie[str]
tmp[name] = cookie # type: ignore
tmp[name] = cookie # type: ignore[assignment]
cookie = tmp[name]

domain = cookie["domain"]
Expand Down
4 changes: 2 additions & 2 deletions aiohttp/formdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,14 @@ def add_fields(self, *fields: Any) -> None:

if isinstance(rec, io.IOBase):
k = guess_filename(rec, "unknown")
self.add_field(k, rec) # type: ignore
self.add_field(k, rec) # type: ignore[arg-type]

elif isinstance(rec, (MultiDictProxy, MultiDict)):
to_add.extend(rec.items())

elif isinstance(rec, (list, tuple)) and len(rec) == 2:
k, fp = rec
self.add_field(k, fp) # type: ignore
self.add_field(k, fp) # type: ignore[arg-type]

else:
raise TypeError(
Expand Down
Loading

0 comments on commit 9e3a28a

Please sign in to comment.