Coverage for /pythoncovmergedfiles/medio/medio/src/aiohttp/aiohttp/abc.py: 88%
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 logging
2import socket
3from abc import ABC, abstractmethod
4from collections.abc import Awaitable, Callable, Generator, Iterable, Sequence, Sized
5from http.cookies import BaseCookie, Morsel
6from typing import TYPE_CHECKING, Any, TypedDict
8from multidict import CIMultiDict
9from yarl import URL
11from ._cookie_helpers import parse_set_cookie_headers
12from .typedefs import LooseCookies
14if TYPE_CHECKING:
15 from .web_app import Application
16 from .web_exceptions import HTTPException
17 from .web_request import BaseRequest, Request
18 from .web_response import StreamResponse
19else:
20 BaseRequest = Request = Application = StreamResponse = Any
21 HTTPException = Any
24class AbstractRouter(ABC):
25 def __init__(self) -> None:
26 self._frozen = False
28 def post_init(self, app: Application) -> None:
29 """Post init stage.
31 Not an abstract method for sake of backward compatibility,
32 but if the router wants to be aware of the application
33 it can override this.
34 """
36 @property
37 def frozen(self) -> bool:
38 return self._frozen
40 def freeze(self) -> None:
41 """Freeze router."""
42 self._frozen = True
44 @abstractmethod
45 async def resolve(self, request: Request) -> "AbstractMatchInfo":
46 """Return MATCH_INFO for given request"""
49class AbstractMatchInfo(ABC):
51 __slots__ = ()
53 @property # pragma: no branch
54 @abstractmethod
55 def handler(self) -> Callable[[Request], Awaitable[StreamResponse]]:
56 """Execute matched request handler"""
58 @property
59 @abstractmethod
60 def expect_handler(
61 self,
62 ) -> Callable[[Request], Awaitable[StreamResponse | None]]:
63 """Expect handler for 100-continue processing"""
65 @property # pragma: no branch
66 @abstractmethod
67 def http_exception(self) -> HTTPException | None:
68 """HTTPException instance raised on router's resolving, or None"""
70 @abstractmethod # pragma: no branch
71 def get_info(self) -> dict[str, Any]:
72 """Return a dict with additional info useful for introspection"""
74 @property # pragma: no branch
75 @abstractmethod
76 def apps(self) -> tuple[Application, ...]:
77 """Stack of nested applications.
79 Top level application is left-most element.
81 """
83 @abstractmethod
84 def add_app(self, app: Application) -> None:
85 """Add application to the nested apps stack."""
87 @abstractmethod
88 def freeze(self) -> None:
89 """Freeze the match info.
91 The method is called after route resolution.
93 After the call .add_app() is forbidden.
95 """
98class AbstractView(ABC):
99 """Abstract class based view."""
101 def __init__(self, request: Request) -> None:
102 self._request = request
104 @property
105 def request(self) -> Request:
106 """Request instance."""
107 return self._request
109 @abstractmethod
110 def __await__(self) -> Generator[None, None, StreamResponse]:
111 """Execute the view handler."""
114class ResolveResult(TypedDict):
115 """Resolve result.
117 This is the result returned from an AbstractResolver's
118 resolve method.
120 :param hostname: The hostname that was provided.
121 :param host: The IP address that was resolved.
122 :param port: The port that was resolved.
123 :param family: The address family that was resolved.
124 :param proto: The protocol that was resolved.
125 :param flags: The flags that were resolved.
126 """
128 hostname: str
129 host: str
130 port: int
131 family: int
132 proto: int
133 flags: int
136class AbstractResolver(ABC):
137 """Abstract DNS resolver."""
139 @abstractmethod
140 async def resolve(
141 self, host: str, port: int = 0, family: socket.AddressFamily = socket.AF_INET
142 ) -> list[ResolveResult]:
143 """Return IP address for given hostname"""
145 @abstractmethod
146 async def close(self) -> None:
147 """Release resolver"""
150ClearCookiePredicate = Callable[[Morsel[str]], bool]
153class AbstractCookieJar(Sized, Iterable[Morsel[str]]):
154 """Abstract Cookie Jar."""
156 @property
157 @abstractmethod
158 def unsafe(self) -> bool:
159 """Return True if cookies can be used with IP addresses."""
161 @property
162 @abstractmethod
163 def quote_cookie(self) -> bool:
164 """Return True if cookies should be quoted."""
166 @abstractmethod
167 def clear(self, predicate: ClearCookiePredicate | None = None) -> None:
168 """Clear all cookies if no predicate is passed."""
170 @abstractmethod
171 def clear_domain(self, domain: str) -> None:
172 """Clear all cookies for domain and all subdomains."""
174 @abstractmethod
175 def update_cookies(self, cookies: LooseCookies, response_url: URL = URL()) -> None:
176 """Update cookies."""
178 def update_cookies_from_headers(
179 self, headers: Sequence[str], response_url: URL
180 ) -> None:
181 """Update cookies from raw Set-Cookie headers."""
182 if headers and (cookies_to_update := parse_set_cookie_headers(headers)):
183 self.update_cookies(cookies_to_update, response_url)
185 @abstractmethod
186 def filter_cookies(self, request_url: URL) -> BaseCookie[str]:
187 """Return the jar's cookies filtered by their attributes."""
190class AbstractStreamWriter(ABC):
191 """Abstract stream writer."""
193 buffer_size: int = 0
194 output_size: int = 0
195 length: int | None = 0
197 @abstractmethod
198 async def write(
199 self, chunk: "bytes | bytearray | memoryview[int] | memoryview[bytes]"
200 ) -> None:
201 """Write chunk into stream."""
203 @abstractmethod
204 async def write_eof(self, chunk: bytes = b"") -> None:
205 """Write last chunk."""
207 @abstractmethod
208 async def drain(self) -> None:
209 """Flush the write buffer."""
211 @abstractmethod
212 def enable_compression(
213 self, encoding: str = "deflate", strategy: int | None = None
214 ) -> None:
215 """Enable HTTP body compression"""
217 @abstractmethod
218 def enable_chunking(self) -> None:
219 """Enable HTTP chunked mode"""
221 @abstractmethod
222 async def write_headers(self, status_line: str, headers: CIMultiDict[str]) -> None:
223 """Write HTTP headers"""
225 def send_headers(self) -> None:
226 """Force sending buffered headers if not already sent.
228 Required only if write_headers() buffers headers instead of sending immediately.
229 For backwards compatibility, this method does nothing by default.
230 """
233class AbstractAccessLogger(ABC):
234 """Abstract writer to access log."""
236 __slots__ = ("logger", "log_format")
238 def __init__(self, logger: logging.Logger, log_format: str) -> None:
239 self.logger = logger
240 self.log_format = log_format
242 @abstractmethod
243 def log(self, request: BaseRequest, response: StreamResponse, time: float) -> None:
244 """Emit log to logger."""
246 @property
247 def enabled(self) -> bool:
248 """Check if logger is enabled."""
249 return True
252class AbstractAsyncAccessLogger(ABC):
253 """Abstract asynchronous writer to access log."""
255 __slots__ = ()
257 @abstractmethod
258 async def log(
259 self, request: BaseRequest, response: StreamResponse, request_start: float
260 ) -> None:
261 """Emit log to logger."""
263 @property
264 def enabled(self) -> bool:
265 """Check if logger is enabled."""
266 return True