Skip to content

Commit eed4172

Browse files
algolia-botFluf22millotp
committed
chore(python): proper type hinting (generated)
algolia/api-clients-automation#3839 Co-authored-by: Thomas Raffray <[email protected]> Co-authored-by: Pierre Millot <[email protected]>
1 parent 601ffa5 commit eed4172

13 files changed

+110
-91
lines changed

algoliasearch/http/api_response.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class ApiResponse(Generic[T]):
2121
def __init__(
2222
self,
2323
verb: Verb,
24-
data: T = None,
24+
data: Optional[T] = None,
2525
error_message: str = "",
2626
headers: Optional[Dict[str, str]] = None,
2727
host: str = "",
@@ -94,6 +94,6 @@ def deserialize(klass: Any = None, data: Any = None) -> Any:
9494
return data
9595

9696
if isinstance(data, str):
97-
return klass.from_json(data)
97+
return klass.from_json(data) # pyright: ignore
9898

99-
return klass.from_dict(data)
99+
return klass.from_dict(data) # pyright: ignore

algoliasearch/http/base_config.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,6 @@
55

66

77
class BaseConfig:
8-
app_id: Optional[str]
9-
api_key: Optional[str]
10-
11-
read_timeout: int
12-
write_timeout: int
13-
connect_timeout: int
14-
15-
wait_task_time_before_retry: Optional[int]
16-
17-
headers: Dict[str, str]
18-
proxies: Dict[str, str]
19-
20-
hosts: HostsCollection
21-
228
def __init__(self, app_id: Optional[str] = None, api_key: Optional[str] = None):
239
app_id = environ.get("ALGOLIA_APP_ID") if app_id is None else app_id
2410

@@ -36,12 +22,14 @@ def __init__(self, app_id: Optional[str] = None, api_key: Optional[str] = None):
3622
self.write_timeout = 30000
3723
self.connect_timeout = 2000
3824

39-
self.wait_task_time_before_retry = None
40-
self.headers = None
41-
self.proxies = None
42-
self.hosts = None
25+
self.wait_task_time_before_retry: Optional[int] = None
26+
self.headers: Optional[Dict[str, str]] = None
27+
self.proxies: Optional[Dict[str, str]] = None
28+
self.hosts: Optional[HostsCollection] = None
4329

4430
def set_client_api_key(self, api_key: str) -> None:
4531
"""Sets a new API key to authenticate requests."""
4632
self.api_key = api_key
33+
if self.headers is None:
34+
self.headers = {}
4735
self.headers["x-algolia-api-key"] = api_key

algoliasearch/http/base_transporter.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77

88

99
class BaseTransporter:
10-
_config: BaseConfig
11-
_retry_strategy: RetryStrategy
12-
_hosts: List[Host]
13-
1410
def __init__(self, config: BaseConfig) -> None:
1511
self._config = config
1612
self._retry_strategy = RetryStrategy()
17-
self._hosts = []
13+
self._hosts: List[Host] = []
14+
self._timeout = 5000
15+
16+
@property
17+
def config(self) -> BaseConfig:
18+
return self._config
1819

1920
def prepare(
2021
self,
@@ -25,13 +26,18 @@ def prepare(
2526

2627
if use_read_transporter:
2728
self._timeout = request_options.timeouts["read"]
28-
self._hosts = self._config.hosts.read()
29+
self._hosts = (
30+
self._config.hosts.read() if self._config.hosts is not None else []
31+
)
2932
if isinstance(request_options.data, dict):
3033
query_parameters.update(request_options.data)
31-
return query_parameters
34+
else:
35+
self._timeout = request_options.timeouts["write"]
36+
self._hosts = (
37+
self._config.hosts.write() if self._config.hosts is not None else []
38+
)
3239

33-
self._timeout = request_options.timeouts["write"]
34-
self._hosts = self._config.hosts.write()
40+
return query_parameters
3541

3642
def build_path(self, path, query_parameters):
3743
if query_parameters is not None and len(query_parameters) > 0:
@@ -54,9 +60,21 @@ def build_url(self, host, path):
5460
)
5561

5662
def get_proxy(self, url):
63+
if self._config.proxies is None:
64+
return None
65+
5766
if url.startswith("https"):
5867
return self._config.proxies.get("https")
5968
elif url.startswith("http"):
6069
return self._config.proxies.get("http")
6170
else:
6271
return None
72+
73+
def get_proxies(self, url):
74+
if self._config.proxies is None:
75+
return None
76+
77+
if url.startswith("http"):
78+
return self._config.proxies
79+
else:
80+
return None

algoliasearch/http/exceptions.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,12 @@ def __init__(self, msg, path_to_item=None) -> None:
127127

128128

129129
class ApiException(AlgoliaException):
130-
def __init__(self, status_code=None, error_message=None, raw_data=None) -> None:
130+
def __init__(
131+
self,
132+
status_code: int = -1,
133+
error_message: str = "Unknown error",
134+
raw_data: bytes = b"",
135+
) -> None:
131136
self.status_code = status_code
132137
self.error_message = error_message
133138
self.body = raw_data.decode("utf-8")

algoliasearch/http/helpers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ def __call__(self, retry_count: int = 0) -> int:
2323
async def create_iterable(
2424
func: Callable[[Optional[T]], Awaitable[T]],
2525
validate: Callable[[T], bool],
26-
aggregator: Callable[[T], None],
27-
timeout: Timeout = Timeout(),
26+
aggregator: Optional[Callable[[T], None]],
27+
timeout: Callable[[], int] = Timeout(),
2828
error_validate: Optional[Callable[[T], bool]] = None,
2929
error_message: Optional[Callable[[T], str]] = None,
3030
) -> T:
@@ -55,8 +55,8 @@ async def retry(prev: Optional[T] = None) -> T:
5555
def create_iterable_sync(
5656
func: Callable[[Optional[T]], T],
5757
validate: Callable[[T], bool],
58-
aggregator: Callable[[T], None],
59-
timeout: Timeout = Timeout(),
58+
aggregator: Optional[Callable[[T], None]],
59+
timeout: Callable[[], int] = Timeout(),
6060
error_validate: Optional[Callable[[T], bool]] = None,
6161
error_message: Optional[Callable[[T], str]] = None,
6262
) -> T:

algoliasearch/http/hosts.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ def __init__(
1818
self.port = port
1919
self.priority = cast(int, priority)
2020
self.accept = (CallType.WRITE | CallType.READ) if accept is None else accept
21-
22-
self.reset()
21+
self.last_use = 0.0
22+
self.retry_count = 0
23+
self.up = True
2324

2425
def reset(self) -> None:
2526
self.last_use = 0.0

algoliasearch/http/request_options.py

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from copy import deepcopy
22
from sys import version_info
3-
from typing import Any, Dict, List, Optional, Tuple, Union
3+
from typing import Any, Dict, Optional, Union
44
from urllib.parse import quote
55

66
from algoliasearch.http.base_config import BaseConfig
@@ -13,20 +13,20 @@
1313

1414

1515
class RequestOptions:
16-
_config: BaseConfig
17-
headers: Dict[str, str]
18-
query_parameters: Dict[str, Any]
19-
timeouts: Dict[str, int]
20-
data: Dict[str, Any]
21-
2216
def __init__(
2317
self,
2418
config: BaseConfig,
25-
headers: Dict[str, str] = {},
26-
query_parameters: Dict[str, Any] = {},
27-
timeouts: Dict[str, int] = {},
28-
data: Dict[str, Any] = {},
19+
headers: Optional[Dict[str, str]] = None,
20+
query_parameters: Optional[Dict[str, Any]] = None,
21+
timeouts: Optional[Dict[str, int]] = None,
22+
data: Optional[Dict[str, Any]] = None,
2923
) -> None:
24+
if headers is None:
25+
headers = {}
26+
if query_parameters is None:
27+
query_parameters = {}
28+
if timeouts is None:
29+
timeouts = {}
3030
self._config = config
3131
self.headers = headers
3232
self.query_parameters = {
@@ -51,25 +51,28 @@ def from_dict(self, data: Dict[str, Dict[str, Any]]) -> Self:
5151
query_parameters=data.get("query_parameters", {}),
5252
timeouts=data.get("timeouts", {}),
5353
data=data.get("data", {}),
54-
)
54+
) # pyright: ignore
5555

5656
def merge(
5757
self,
58-
query_parameters: List[Tuple[str, str]] = [],
59-
headers: Dict[str, Optional[str]] = {},
60-
_: Dict[str, int] = {},
58+
query_parameters: Optional[Dict[str, Any]] = None,
59+
headers: Optional[Dict[str, str]] = None,
6160
data: Optional[str] = None,
6261
user_request_options: Optional[Union[Self, Dict[str, Any]]] = None,
6362
) -> Self:
6463
"""
6564
Merges the default config values with the user given request options if it exists.
6665
"""
6766

68-
headers.update(self._config.headers)
67+
if query_parameters is None:
68+
query_parameters = {}
69+
if headers is None:
70+
headers = {}
71+
headers.update(self._config.headers or {})
6972

7073
request_options = {
7174
"headers": headers,
72-
"query_parameters": {k: v for k, v in query_parameters},
75+
"query_parameters": query_parameters,
7376
"timeouts": {
7477
"read": self._config.read_timeout,
7578
"write": self._config.write_timeout,

algoliasearch/http/retry.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class RetryOutcome:
1414
class RetryStrategy:
1515
def valid_hosts(self, hosts: List[Host]) -> List[Host]:
1616
for host in hosts:
17-
if not host.up and self._now() - host.last_use > Host.TTL:
17+
if not host.up and time.time() - host.last_use > Host.TTL:
1818
host.up = True
1919

2020
return [host for host in hosts if host.up]

algoliasearch/http/serializer.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,16 @@ class QueryParametersSerializer:
1010
Parses the given 'query_parameters' values of each keys into their string value.
1111
"""
1212

13-
query_parameters: Dict[str, Any] = {}
13+
def __init__(self, query_parameters: Optional[Dict[str, Any]]) -> None:
14+
self.query_parameters: Dict[str, Any] = {}
15+
if query_parameters is None:
16+
return
17+
for key, value in query_parameters.items():
18+
if isinstance(value, dict):
19+
for dkey, dvalue in value.items():
20+
self.query_parameters[dkey] = self.parse(dvalue)
21+
else:
22+
self.query_parameters[key] = self.parse(value)
1423

1524
def parse(self, value) -> Any:
1625
if isinstance(value, list):
@@ -27,19 +36,8 @@ def encoded(self) -> str:
2736
dict(sorted(self.query_parameters.items(), key=lambda val: val[0]))
2837
).replace("+", "%20")
2938

30-
def __init__(self, query_parameters: Optional[Dict[str, Any]]) -> None:
31-
self.query_parameters = {}
32-
if query_parameters is None:
33-
return
34-
for key, value in query_parameters.items():
35-
if isinstance(value, dict):
36-
for dkey, dvalue in value.items():
37-
self.query_parameters[dkey] = self.parse(dvalue)
38-
else:
39-
self.query_parameters[key] = self.parse(value)
40-
4139

42-
def bodySerializer(obj: Any) -> Any:
40+
def body_serializer(obj: Any) -> Any:
4341
"""Builds a JSON POST object.
4442
4543
If obj is None, return None.
@@ -57,14 +55,14 @@ def bodySerializer(obj: Any) -> Any:
5755
elif isinstance(obj, PRIMITIVE_TYPES):
5856
return obj
5957
elif isinstance(obj, list):
60-
return [bodySerializer(sub_obj) for sub_obj in obj]
58+
return [body_serializer(sub_obj) for sub_obj in obj]
6159
elif isinstance(obj, tuple):
62-
return tuple(bodySerializer(sub_obj) for sub_obj in obj)
60+
return tuple(body_serializer(sub_obj) for sub_obj in obj)
6361
elif isinstance(obj, dict):
6462
obj_dict = obj
6563
else:
6664
obj_dict = obj.to_dict()
6765
if obj_dict is None:
6866
return None
6967

70-
return {key: bodySerializer(val) for key, val in obj_dict.items()}
68+
return {key: body_serializer(val) for key, val in obj_dict.items()}

algoliasearch/http/transporter.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from asyncio import TimeoutError
22
from json import loads
3+
from typing import List, Optional
34

45
from aiohttp import ClientSession, TCPConnector
56
from async_timeout import timeout
@@ -11,19 +12,19 @@
1112
AlgoliaUnreachableHostException,
1213
RequestException,
1314
)
15+
from algoliasearch.http.hosts import Host
1416
from algoliasearch.http.request_options import RequestOptions
1517
from algoliasearch.http.retry import RetryOutcome, RetryStrategy
1618
from algoliasearch.http.verb import Verb
1719

1820

1921
class Transporter(BaseTransporter):
20-
_session: ClientSession
21-
2222
def __init__(self, config: BaseConfig) -> None:
23-
self._session = None
23+
super().__init__(config)
24+
self._session: Optional[ClientSession] = None
2425
self._config = config
2526
self._retry_strategy = RetryStrategy()
26-
self._hosts = []
27+
self._hosts: List[Host] = []
2728

2829
async def close(self) -> None:
2930
if self._session is not None:
@@ -71,7 +72,7 @@ async def request(
7172
url=url,
7273
host=host.url,
7374
status_code=resp.status,
74-
headers=resp.headers,
75+
headers=resp.headers, # pyright: ignore # insensitive dict is still a dict
7576
data=_raw_data,
7677
raw_data=_raw_data,
7778
error_message=str(resp.reason),
@@ -103,6 +104,7 @@ async def request(
103104

104105
class EchoTransporter(Transporter):
105106
def __init__(self, config: BaseConfig) -> None:
107+
super().__init__(config)
106108
self._config = config
107109
self._retry_strategy = RetryStrategy()
108110

0 commit comments

Comments
 (0)