Skip to content

Commit bf83dbe

Browse files
[PR #8634/c7293e19 backport][3.10] Backport #8620 as improvements to various type annotations (#8635)
**This is a backport of PR #8634 as merged into 3.11 (c7293e1).** Co-authored-by: Sam Bull <[email protected]>
1 parent 4815765 commit bf83dbe

14 files changed

+188
-76
lines changed

.coveragerc

+3
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ omit = site-packages
66
[report]
77
exclude_also =
88
if TYPE_CHECKING
9+
assert False
10+
: \.\.\.(\s*#.*)?$
11+
^ +\.\.\.$

.github/workflows/ci-cd.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
- name: Setup Python
4646
uses: actions/setup-python@v5
4747
with:
48-
python-version: 3.9
48+
python-version: 3.11
4949
- name: Cache PyPI
5050
uses: actions/[email protected]
5151
with:

CHANGES/8634.misc.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Minor improvements to various type annotations -- by :user:`Dreamsorcerer`.

aiohttp/client.py

+20-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import traceback
1010
import warnings
1111
from contextlib import suppress
12-
from types import SimpleNamespace, TracebackType
12+
from types import TracebackType
1313
from typing import (
1414
TYPE_CHECKING,
1515
Any,
@@ -155,7 +155,7 @@
155155

156156

157157
class _RequestOptions(TypedDict, total=False):
158-
params: Union[Mapping[str, str], None]
158+
params: Union[Mapping[str, Union[str, int]], str, None]
159159
data: Any
160160
json: Any
161161
cookies: Union[LooseCookies, None]
@@ -175,7 +175,7 @@ class _RequestOptions(TypedDict, total=False):
175175
ssl: Union[SSLContext, bool, Fingerprint]
176176
server_hostname: Union[str, None]
177177
proxy_headers: Union[LooseHeaders, None]
178-
trace_request_ctx: Union[SimpleNamespace, None]
178+
trace_request_ctx: Union[Mapping[str, str], None]
179179
read_bufsize: Union[int, None]
180180
auto_decompress: Union[bool, None]
181181
max_line_size: Union[int, None]
@@ -422,11 +422,22 @@ def __del__(self, _warnings: Any = warnings) -> None:
422422
context["source_traceback"] = self._source_traceback
423423
self._loop.call_exception_handler(context)
424424

425-
def request(
426-
self, method: str, url: StrOrURL, **kwargs: Any
427-
) -> "_RequestContextManager":
428-
"""Perform HTTP request."""
429-
return _RequestContextManager(self._request(method, url, **kwargs))
425+
if sys.version_info >= (3, 11) and TYPE_CHECKING:
426+
427+
def request(
428+
self,
429+
method: str,
430+
url: StrOrURL,
431+
**kwargs: Unpack[_RequestOptions],
432+
) -> "_RequestContextManager": ...
433+
434+
else:
435+
436+
def request(
437+
self, method: str, url: StrOrURL, **kwargs: Any
438+
) -> "_RequestContextManager":
439+
"""Perform HTTP request."""
440+
return _RequestContextManager(self._request(method, url, **kwargs))
430441

431442
def _build_url(self, str_or_url: StrOrURL) -> URL:
432443
url = URL(str_or_url)
@@ -466,7 +477,7 @@ async def _request(
466477
ssl: Union[SSLContext, bool, Fingerprint] = True,
467478
server_hostname: Optional[str] = None,
468479
proxy_headers: Optional[LooseHeaders] = None,
469-
trace_request_ctx: Optional[SimpleNamespace] = None,
480+
trace_request_ctx: Optional[Mapping[str, str]] = None,
470481
read_bufsize: Optional[int] = None,
471482
auto_decompress: Optional[bool] = None,
472483
max_line_size: Optional[int] = None,

aiohttp/client_exceptions.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def __str__(self) -> str:
100100
return "{}, message={!r}, url={!r}".format(
101101
self.status,
102102
self.message,
103-
self.request_info.real_url,
103+
str(self.request_info.real_url),
104104
)
105105

106106
def __repr__(self) -> str:

aiohttp/client_reqrep.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ class ClientRequest:
245245
hdrs.ACCEPT_ENCODING: _gen_default_accept_encoding(),
246246
}
247247

248-
body = b""
248+
# Type of body depends on PAYLOAD_REGISTRY, which is dynamic.
249+
body: Any = b""
249250
auth = None
250251
response = None
251252

@@ -441,7 +442,7 @@ def update_headers(self, headers: Optional[LooseHeaders]) -> None:
441442

442443
if headers:
443444
if isinstance(headers, (dict, MultiDictProxy, MultiDict)):
444-
headers = headers.items() # type: ignore[assignment]
445+
headers = headers.items()
445446

446447
for key, value in headers: # type: ignore[misc]
447448
# A special case for Host header
@@ -597,6 +598,10 @@ def update_proxy(
597598
raise ValueError("proxy_auth must be None or BasicAuth() tuple")
598599
self.proxy = proxy
599600
self.proxy_auth = proxy_auth
601+
if proxy_headers is not None and not isinstance(
602+
proxy_headers, (MultiDict, MultiDictProxy)
603+
):
604+
proxy_headers = CIMultiDict(proxy_headers)
600605
self.proxy_headers = proxy_headers
601606

602607
def keep_alive(self) -> bool:
@@ -632,10 +637,10 @@ async def write_bytes(
632637
await self.body.write(writer)
633638
else:
634639
if isinstance(self.body, (bytes, bytearray)):
635-
self.body = (self.body,) # type: ignore[assignment]
640+
self.body = (self.body,)
636641

637642
for chunk in self.body:
638-
await writer.write(chunk) # type: ignore[arg-type]
643+
await writer.write(chunk)
639644
except OSError as underlying_exc:
640645
reraised_exc = underlying_exc
641646

aiohttp/connector.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
List,
2424
Literal,
2525
Optional,
26+
Sequence,
2627
Set,
2728
Tuple,
2829
Type,
@@ -833,7 +834,7 @@ def clear_dns_cache(
833834
self._cached_hosts.clear()
834835

835836
async def _resolve_host(
836-
self, host: str, port: int, traces: Optional[List["Trace"]] = None
837+
self, host: str, port: int, traces: Optional[Sequence["Trace"]] = None
837838
) -> List[ResolveResult]:
838839
"""Resolve host and return list of addresses."""
839840
if is_ip_address(host):
@@ -902,7 +903,7 @@ async def _resolve_host_with_throttle(
902903
key: Tuple[str, int],
903904
host: str,
904905
port: int,
905-
traces: Optional[List["Trace"]],
906+
traces: Optional[Sequence["Trace"]],
906907
) -> List[ResolveResult]:
907908
"""Resolve host with a dns events throttle."""
908909
if key in self._throttle_dns_events:

aiohttp/pytest_plugin.py

+30-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,17 @@
22
import contextlib
33
import inspect
44
import warnings
5-
from typing import Any, Awaitable, Callable, Dict, Iterator, Optional, Type, Union
5+
from typing import (
6+
Any,
7+
Awaitable,
8+
Callable,
9+
Dict,
10+
Iterator,
11+
Optional,
12+
Protocol,
13+
Type,
14+
Union,
15+
)
616

717
import pytest
818

@@ -24,9 +34,23 @@
2434
except ImportError: # pragma: no cover
2535
uvloop = None # type: ignore[assignment]
2636

27-
AiohttpClient = Callable[[Union[Application, BaseTestServer]], Awaitable[TestClient]]
2837
AiohttpRawServer = Callable[[Application], Awaitable[RawTestServer]]
29-
AiohttpServer = Callable[[Application], Awaitable[TestServer]]
38+
39+
40+
class AiohttpClient(Protocol):
41+
def __call__(
42+
self,
43+
__param: Union[Application, BaseTestServer],
44+
*,
45+
server_kwargs: Optional[Dict[str, Any]] = None,
46+
**kwargs: Any
47+
) -> Awaitable[TestClient]: ...
48+
49+
50+
class AiohttpServer(Protocol):
51+
def __call__(
52+
self, app: Application, *, port: Optional[int] = None, **kwargs: Any
53+
) -> Awaitable[TestServer]: ...
3054

3155

3256
def pytest_addoption(parser): # type: ignore[no-untyped-def]
@@ -262,7 +286,9 @@ def aiohttp_server(loop: asyncio.AbstractEventLoop) -> Iterator[AiohttpServer]:
262286
"""
263287
servers = []
264288

265-
async def go(app, *, port=None, **kwargs): # type: ignore[no-untyped-def]
289+
async def go(
290+
app: Application, *, port: Optional[int] = None, **kwargs: Any
291+
) -> TestServer:
266292
server = TestServer(app, port=port)
267293
await server.start_server(loop=loop, **kwargs)
268294
servers.append(server)

0 commit comments

Comments
 (0)