Home Assistant Unofficial Reference 2024.12.1
aiohttp.py
Go to the documentation of this file.
1 """Utilities to help with aiohttp."""
2 
3 from __future__ import annotations
4 
5 from http import HTTPStatus
6 import io
7 from typing import Any
8 from urllib.parse import parse_qsl
9 
10 from aiohttp import payload, web
11 from aiohttp.typedefs import JSONDecoder
12 from multidict import CIMultiDict, MultiDict
13 
14 from .json import json_loads
15 
16 
18  """Small mock to imitate stream reader."""
19 
20  def __init__(self, content: bytes) -> None:
21  """Initialize mock stream reader."""
22  self._content_content = io.BytesIO(content)
23 
24  async def read(self, byte_count: int = -1) -> bytes:
25  """Read bytes."""
26  if byte_count == -1:
27  return self._content_content.read()
28  return self._content_content.read(byte_count)
29 
30 
32  """Small mock to imitate payload writer."""
33 
34  def enable_chunking(self) -> None:
35  """Enable chunking."""
36 
37  async def write_headers(self, *args: Any, **kwargs: Any) -> None:
38  """Write headers."""
39 
40 
41 _MOCK_PAYLOAD_WRITER = MockPayloadWriter()
42 
43 
45  """Mock an aiohttp request."""
46 
47  mock_source: str | None = None
48 
49  def __init__(
50  self,
51  content: bytes,
52  mock_source: str,
53  method: str = "GET",
54  status: int = HTTPStatus.OK,
55  headers: dict[str, str] | None = None,
56  query_string: str | None = None,
57  url: str = "",
58  ) -> None:
59  """Initialize a request."""
60  self.methodmethod = method
61  self.urlurl = url
62  self.statusstatus = status
63  self.headers: CIMultiDict[str] = CIMultiDict(headers or {})
64  self.query_stringquery_string = query_string or ""
65  self.keep_alivekeep_alive = False
66  self.versionversion = (1, 1)
67  self._content_content = content
68  self.mock_sourcemock_source = mock_source
69  self._payload_writer_payload_writer = _MOCK_PAYLOAD_WRITER
70 
71  async def _prepare_hook(self, response: Any) -> None:
72  """Prepare hook."""
73 
74  @property
75  def query(self) -> MultiDict[str]:
76  """Return a dictionary with the query variables."""
77  return MultiDict(parse_qsl(self.query_stringquery_string, keep_blank_values=True))
78 
79  @property
80  def _text(self) -> str:
81  """Return the body as text."""
82  return self._content_content.decode("utf-8")
83 
84  @property
85  def content(self) -> MockStreamReader:
86  """Return the body as text."""
87  return MockStreamReader(self._content_content)
88 
89  @property
90  def body_exists(self) -> bool:
91  """Return True if request has HTTP BODY, False otherwise."""
92  return bool(self._text_text)
93 
94  async def json(self, loads: JSONDecoder = json_loads) -> Any:
95  """Return the body as JSON."""
96  return loads(self._text_text)
97 
98  async def post(self) -> MultiDict[str]:
99  """Return POST parameters."""
100  return MultiDict(parse_qsl(self._text_text, keep_blank_values=True))
101 
102  async def text(self) -> str:
103  """Return the body as text."""
104  return self._text_text
105 
106 
107 def serialize_response(response: web.Response) -> dict[str, Any]:
108  """Serialize an aiohttp response to a dictionary."""
109  if (body := response.body) is None:
110  body_decoded = None
111  elif isinstance(body, payload.StringPayload):
112  body_decoded = body._value.decode(body.encoding or "utf-8") # noqa: SLF001
113  elif isinstance(body, bytes):
114  body_decoded = body.decode(response.charset or "utf-8")
115  else:
116  raise TypeError("Unknown payload encoding")
117 
118  return {
119  "status": response.status,
120  "body": body_decoded,
121  "headers": dict(response.headers),
122  }
None write_headers(self, *Any args, **Any kwargs)
Definition: aiohttp.py:37
MultiDict[str] query(self)
Definition: aiohttp.py:75
MockStreamReader content(self)
Definition: aiohttp.py:85
Any json(self, JSONDecoder loads=json_loads)
Definition: aiohttp.py:94
None _prepare_hook(self, Any response)
Definition: aiohttp.py:71
None __init__(self, bytes content, str mock_source, str method="GET", int status=HTTPStatus.OK, dict[str, str]|None headers=None, str|None query_string=None, str url="")
Definition: aiohttp.py:58
bytes read(self, int byte_count=-1)
Definition: aiohttp.py:24
None __init__(self, bytes content)
Definition: aiohttp.py:20
dict[str, Any] serialize_response(web.Response response)
Definition: aiohttp.py:107