Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/aiohttp/abc.py: 87%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import asyncio
2import logging
3import socket
4from abc import ABC, abstractmethod
5from collections.abc import Sized
6from http.cookies import BaseCookie, Morsel
7from typing import (
8 TYPE_CHECKING,
9 Any,
10 Awaitable,
11 Callable,
12 Dict,
13 Generator,
14 Iterable,
15 List,
16 Optional,
17 Sequence,
18 Tuple,
19 TypedDict,
20 Union,
21)
23from multidict import CIMultiDict
24from yarl import URL
26from ._cookie_helpers import parse_set_cookie_headers
27from .typedefs import LooseCookies
29if TYPE_CHECKING:
30 from .web_app import Application
31 from .web_exceptions import HTTPException
32 from .web_request import BaseRequest, Request
33 from .web_response import StreamResponse
34else:
35 BaseRequest = Request = Application = StreamResponse = None
36 HTTPException = None
39class AbstractRouter(ABC):
40 def __init__(self) -> None:
41 self._frozen = False
43 def post_init(self, app: Application) -> None:
44 """Post init stage.
46 Not an abstract method for sake of backward compatibility,
47 but if the router wants to be aware of the application
48 it can override this.
49 """
51 @property
52 def frozen(self) -> bool:
53 return self._frozen
55 def freeze(self) -> None:
56 """Freeze router."""
57 self._frozen = True
59 @abstractmethod
60 async def resolve(self, request: Request) -> "AbstractMatchInfo":
61 """Return MATCH_INFO for given request"""
64class AbstractMatchInfo(ABC):
66 __slots__ = ()
68 @property # pragma: no branch
69 @abstractmethod
70 def handler(self) -> Callable[[Request], Awaitable[StreamResponse]]:
71 """Execute matched request handler"""
73 @property
74 @abstractmethod
75 def expect_handler(
76 self,
77 ) -> Callable[[Request], Awaitable[Optional[StreamResponse]]]:
78 """Expect handler for 100-continue processing"""
80 @property # pragma: no branch
81 @abstractmethod
82 def http_exception(self) -> Optional[HTTPException]:
83 """HTTPException instance raised on router's resolving, or None"""
85 @abstractmethod # pragma: no branch
86 def get_info(self) -> Dict[str, Any]:
87 """Return a dict with additional info useful for introspection"""
89 @property # pragma: no branch
90 @abstractmethod
91 def apps(self) -> Tuple[Application, ...]:
92 """Stack of nested applications.
94 Top level application is left-most element.
96 """
98 @abstractmethod
99 def add_app(self, app: Application) -> None:
100 """Add application to the nested apps stack."""
102 @abstractmethod
103 def freeze(self) -> None:
104 """Freeze the match info.
106 The method is called after route resolution.
108 After the call .add_app() is forbidden.
110 """
113class AbstractView(ABC):
114 """Abstract class based view."""
116 def __init__(self, request: Request) -> None:
117 self._request = request
119 @property
120 def request(self) -> Request:
121 """Request instance."""
122 return self._request
124 @abstractmethod
125 def __await__(self) -> Generator[Any, None, StreamResponse]:
126 """Execute the view handler."""
129class ResolveResult(TypedDict):
130 """Resolve result.
132 This is the result returned from an AbstractResolver's
133 resolve method.
135 :param hostname: The hostname that was provided.
136 :param host: The IP address that was resolved.
137 :param port: The port that was resolved.
138 :param family: The address family that was resolved.
139 :param proto: The protocol that was resolved.
140 :param flags: The flags that were resolved.
141 """
143 hostname: str
144 host: str
145 port: int
146 family: int
147 proto: int
148 flags: int
151class AbstractResolver(ABC):
152 """Abstract DNS resolver."""
154 @abstractmethod
155 async def resolve(
156 self, host: str, port: int = 0, family: socket.AddressFamily = socket.AF_INET
157 ) -> List[ResolveResult]:
158 """Return IP address for given hostname"""
160 @abstractmethod
161 async def close(self) -> None:
162 """Release resolver"""
165if TYPE_CHECKING:
166 IterableBase = Iterable[Morsel[str]]
167else:
168 IterableBase = Iterable
171ClearCookiePredicate = Callable[["Morsel[str]"], bool]
174class AbstractCookieJar(Sized, IterableBase):
175 """Abstract Cookie Jar."""
177 def __init__(self, *, loop: Optional[asyncio.AbstractEventLoop] = None) -> None:
178 self._loop = loop or asyncio.get_running_loop()
180 @property
181 @abstractmethod
182 def quote_cookie(self) -> bool:
183 """Return True if cookies should be quoted."""
185 @abstractmethod
186 def clear(self, predicate: Optional[ClearCookiePredicate] = None) -> None:
187 """Clear all cookies if no predicate is passed."""
189 @abstractmethod
190 def clear_domain(self, domain: str) -> None:
191 """Clear all cookies for domain and all subdomains."""
193 @abstractmethod
194 def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:
195 """Update cookies."""
197 def update_cookies_from_headers(
198 self, headers: Sequence[str], response_url: URL
199 ) -> None:
200 """Update cookies from raw Set-Cookie headers."""
201 if headers and (cookies_to_update := parse_set_cookie_headers(headers)):
202 self.update_cookies(cookies_to_update, response_url)
204 @abstractmethod
205 def filter_cookies(self, request_url: URL) -> "BaseCookie[str]":
206 """Return the jar's cookies filtered by their attributes."""
209class AbstractStreamWriter(ABC):
210 """Abstract stream writer."""
212 buffer_size: int = 0
213 output_size: int = 0
214 length: Optional[int] = 0
216 @abstractmethod
217 async def write(self, chunk: Union[bytes, bytearray, memoryview]) -> None:
218 """Write chunk into stream."""
220 @abstractmethod
221 async def write_eof(self, chunk: bytes = b"") -> None:
222 """Write last chunk."""
224 @abstractmethod
225 async def drain(self) -> None:
226 """Flush the write buffer."""
228 @abstractmethod
229 def enable_compression(
230 self, encoding: str = "deflate", strategy: Optional[int] = None
231 ) -> None:
232 """Enable HTTP body compression"""
234 @abstractmethod
235 def enable_chunking(self) -> None:
236 """Enable HTTP chunked mode"""
238 @abstractmethod
239 async def write_headers(
240 self, status_line: str, headers: "CIMultiDict[str]"
241 ) -> None:
242 """Write HTTP headers"""
244 def send_headers(self) -> None:
245 """Force sending buffered headers if not already sent.
247 Required only if write_headers() buffers headers instead of sending immediately.
248 For backwards compatibility, this method does nothing by default.
249 """
252class AbstractAccessLogger(ABC):
253 """Abstract writer to access log."""
255 __slots__ = ("logger", "log_format")
257 def __init__(self, logger: logging.Logger, log_format: str) -> None:
258 self.logger = logger
259 self.log_format = log_format
261 @abstractmethod
262 def log(self, request: BaseRequest, response: StreamResponse, time: float) -> None:
263 """Emit log to logger."""
265 @property
266 def enabled(self) -> bool:
267 """Check if logger is enabled."""
268 return True