Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce strict mypy checks #5370

Merged
merged 43 commits into from
Jan 21, 2021
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
fd8317e
Run mypy --strict
derlih Dec 23, 2020
0047ccd
fix resolver
derlih Dec 23, 2020
9d8f691
fix helpers
derlih Dec 23, 2020
6dff8bf
fix payload
derlih Dec 23, 2020
ef0ecaf
fix http_websocket
derlih Dec 23, 2020
7f57094
fix http_parser.py
derlih Dec 23, 2020
1b3e577
fix worker.py
derlih Dec 23, 2020
4772e9f
fix web_urldispatcher.py
derlih Dec 23, 2020
04d63b2
typing.Awaitable (deprecated since 3.9) -> collections.abc.Awaitable
derlih Dec 23, 2020
6727aef
fix web_response.py
derlih Dec 23, 2020
312a85f
fix web_app.py
derlih Dec 24, 2020
4097515
Fix multipart.py
derlih Dec 24, 2020
8358217
Fix web_request.py + additions to http_parser.py
derlih Dec 24, 2020
ba2b92b
Add some typing to helpers.py
derlih Dec 24, 2020
4828a5e
fix connector.py
derlih Dec 24, 2020
0e77857
fix client_ws.py
derlih Dec 24, 2020
2ef66e6
fix web_ws.py
derlih Dec 24, 2020
6c7b91d
fix web_protocol.py
derlih Dec 24, 2020
cf137b9
fix test_utils.py
derlih Dec 24, 2020
b874ce0
fix pytest_plugin.py
derlih Dec 24, 2020
fe6606d
fix helpers.py run
derlih Dec 24, 2020
0491354
Revert "typing.Awaitable (deprecated since 3.9) -> collections.abc.Aw…
derlih Dec 24, 2020
918efc1
run type fixes
derlih Dec 24, 2020
f104311
add chages file
derlih Dec 24, 2020
91747a3
Run mypy --strict only for aiohttp
derlih Dec 26, 2020
7bd6271
Move strict option into mypy config
derlih Dec 27, 2020
403ebb6
add pytest to lint.txt
derlih Dec 27, 2020
dc73132
Simplify config
derlih Dec 27, 2020
78dc696
move strict flag to mypy.ini
derlih Dec 27, 2020
d81f5b2
changes file
derlih Jan 17, 2021
11e7f5d
mypy shows error code
derlih Jan 17, 2021
60447aa
add asynctest to mypy ignore imports
derlih Jan 17, 2021
d559a39
mypy specific ignores
derlih Jan 18, 2021
ac6c7f4
fix test_client_session.py
derlih Jan 18, 2021
52db00f
fix web_ws.py
derlih Jan 18, 2021
7a8b193
fix WebSocketResponse._compress typing
derlih Jan 18, 2021
68905c1
restore client_reqrep body logic
derlih Jan 19, 2021
9bcca14
Revert "restore client_reqrep body logic"
derlih Jan 20, 2021
34a46c9
Revert "fix WebSocketResponse._compress typing"
derlih Jan 20, 2021
246990d
Revert "fix web_ws.py"
derlih Jan 20, 2021
1cfac3c
Revert "fix test_client_session.py"
derlih Jan 20, 2021
e465642
Revert "mypy specific ignores"
derlih Jan 20, 2021
eaee5aa
Specify mypy errors for ignore only
derlih Jan 20, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 tests
mypy --show-error-codes aiohttp tests

.develop: .install-deps $(call to-hash,$(PYS) $(CYS) $(CS))
pip install -e .
Expand Down
17 changes: 9 additions & 8 deletions aiohttp/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
Type,
TypeVar,
Union,
cast,
)

from multidict import CIMultiDict, MultiDict, MultiDictProxy, istr
Expand Down Expand Up @@ -133,7 +134,7 @@
try:
from ssl import SSLContext
except ImportError: # pragma: no cover
SSLContext = object # type: ignore
SSLContext = object # type: ignore[assignment,misc]


@dataclasses.dataclass(frozen=True)
Expand Down Expand Up @@ -245,10 +246,10 @@ def __init__(
self._default_auth = auth
self._version = version
self._json_serialize = json_serialize
if timeout is sentinel:
self._timeout = DEFAULT_TIMEOUT
if isinstance(timeout, ClientTimeout):
self._timeout = timeout
else:
self._timeout = timeout # type: ignore
self._timeout = DEFAULT_TIMEOUT
self._raise_for_status = raise_for_status
self._auto_decompress = auto_decompress
self._trust_env = trust_env
Expand Down Expand Up @@ -378,10 +379,10 @@ async def _request(
raise InvalidURL(proxy) from e

if timeout is sentinel:
real_timeout = self._timeout # type: ClientTimeout
real_timeout: ClientTimeout = self._timeout
else:
if not isinstance(timeout, ClientTimeout):
real_timeout = ClientTimeout(total=timeout) # type: ignore
real_timeout = ClientTimeout(total=cast(float, timeout))
else:
real_timeout = timeout
# timeout is cumulative for all request operations
Expand Down Expand Up @@ -690,7 +691,7 @@ async def _ws_connect(
DeprecationWarning,
stacklevel=2,
)
ws_timeout = ClientWSTimeout(ws_close=timeout) # type: ignore
ws_timeout = ClientWSTimeout(ws_close=cast(float, timeout))
else:
ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT
if receive_timeout is not None:
Expand Down Expand Up @@ -1053,7 +1054,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[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 @@ -11,7 +11,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 @@ -270,11 +270,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
35 changes: 20 additions & 15 deletions aiohttp/client_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,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[assignment,misc]

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 @@ -333,9 +333,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 @@ -347,7 +347,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 @@ -369,15 +369,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 @@ -519,10 +519,12 @@ async def write_bytes(
await self.body.write(writer)
else:
if isinstance(self.body, (bytes, bytearray)):
self.body = (self.body,) # type: ignore
body = (self.body,)
else:
body = self.body
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a logic change unrelated to typing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've restored the logic


for chunk in self.body:
await writer.write(chunk) # type: ignore
for chunk in body:
await writer.write(chunk)

await writer.write_eof()
except OSError as exc:
Expand Down Expand Up @@ -806,7 +808,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 @@ -818,13 +820,14 @@ async def start(self, connection: "Connection") -> "ClientResponse":
"""Start response processing."""
self._closed = False
self._protocol = connection.protocol
assert self._protocol is not None
self._connection = connection

with self._timer:
while True:
# read response
try:
message, payload = await self._protocol.read() # type: ignore
message, payload = await self._protocol.read()
except http.HttpProcessingError as exc:
raise ClientResponseError(
self.request_info,
Expand Down Expand Up @@ -1007,11 +1010,12 @@ async def text(self, encoding: Optional[str] = None, errors: str = "strict") ->
"""Read response payload and decode."""
if self._body is None:
await self.read()
assert self._body is not None

if encoding is None:
encoding = self.get_encoding()

return self._body.decode(encoding, errors=errors) # type: ignore
return self._body.decode(encoding, errors=errors)

async def json(
self,
Expand All @@ -1023,6 +1027,7 @@ async def json(
"""Read and decodes JSON response."""
if self._body is None:
await self.read()
assert self._body is not None

if content_type:
ctype = self.headers.get(hdrs.CONTENT_TYPE, "").lower()
Expand All @@ -1039,7 +1044,7 @@ async def json(
if encoding is None:
encoding = self.get_encoding()

return loads(self._body.decode(encoding)) # type: ignore
return loads(self._body.decode(encoding))

async def __aenter__(self) -> "ClientResponse":
return self
Expand Down
10 changes: 5 additions & 5 deletions aiohttp/client_ws.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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

import async_timeout
from typing_extensions import Final
Expand Down Expand Up @@ -68,10 +68,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 @@ -286,13 +286,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
27 changes: 17 additions & 10 deletions aiohttp/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,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[assignment,misc]


__all__ = ("BaseConnector", "TCPConnector", "UnixConnector", "NamedPipeConnector")
Expand Down Expand Up @@ -218,18 +218,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 @@ -744,7 +744,7 @@ def __init__(
self._ssl = ssl
if resolver is None:
resolver = DefaultResolver()
self._resolver = resolver
self._resolver: AbstractResolver = resolver

self._use_dns_cache = use_dns_cache
self._cached_hosts = _DNSCacheTable(ttl=ttl_dns_cache)
Expand Down Expand Up @@ -943,7 +943,12 @@ 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
transport, handler = await self._loop.create_connection(*args, **kwargs)
return (
cast(asyncio.Transport, transport),
cast(ResponseHandler, handler),
)

except cert_errors as exc:
raise ClientConnectorCertificateError(req.connection_key, exc) from exc
except ssl_errors as exc:
Expand Down Expand Up @@ -1031,7 +1036,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 @@ -1202,7 +1207,9 @@ def __init__(
limit=limit,
limit_per_host=limit_per_host,
)
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 @@ -1218,7 +1225,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 @@ -147,7 +147,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)

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)

else:
raise TypeError(
Expand Down
Loading