Skip to content

Commit 32d023a

Browse files
committed
modify linting in http_client
1 parent 7fcf28e commit 32d023a

File tree

8 files changed

+117
-98
lines changed

8 files changed

+117
-98
lines changed

eventsourcingdb/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ async def __aexit__(
4141
exc_val: BaseException | None = None,
4242
exc_tb: TracebackType | None = None,
4343
) -> None:
44-
await self.__http_client.__aexit__(exc_tb=exc_tb, exc_val=exc_val, exc_type=exc_type)
44+
await self.__http_client.__aexit__(exc_type, exc_val, exc_tb)
4545

4646
async def initialize(self) -> None:
4747
await self.__http_client.initialize()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from collections.abc import Callable, Coroutine
2+
from typing import Any
3+
4+
import aiohttp
5+
6+
from ..errors.custom_error import CustomError
7+
from ..errors.internal_error import InternalError
8+
from ..errors.server_error import ServerError
9+
from .response import Response
10+
11+
12+
async def execute_request(
13+
func: Callable[[], Coroutine[Any, Any, Response]]
14+
) -> Response:
15+
try:
16+
return await func()
17+
except CustomError as custom_error:
18+
raise custom_error
19+
except aiohttp.ClientError as request_error:
20+
raise ServerError(str(request_error)) from request_error
21+
except Exception as other_error:
22+
raise InternalError(str(other_error)) from other_error
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import aiohttp
2+
3+
from .response import Response
4+
5+
async def get_error_message(response: Response) -> str:
6+
"""Extrahiert Fehlermeldung aus der Response."""
7+
error_message = f'Request failed with status code \'{response.status_code}\''
8+
9+
try:
10+
encoded_error_reason = await response.body.read()
11+
except (aiohttp.ClientError, IOError): # Use specific exception types instead of Exception
12+
pass
13+
else:
14+
try:
15+
error_reason = encoded_error_reason.decode('utf-8')
16+
except UnicodeDecodeError: # Use specific exception type instead of Exception
17+
pass
18+
else:
19+
error_message += f" {error_reason}"
20+
21+
error_message += '.'
22+
return error_message
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def get_get_headers(api_token: str, with_authorization: bool) -> dict[str, str]:
2+
headers = {}
3+
if with_authorization:
4+
headers['Authorization'] = f'Bearer {api_token}'
5+
return headers
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def get_post_headers(api_token: str) -> dict[str, str]:
2+
return {
3+
'Authorization': f'Bearer {api_token}',
4+
'Content-Type': 'application/json'
5+
}
Lines changed: 41 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
1-
from collections import namedtuple
2-
from collections.abc import Callable, Coroutine
31
from types import TracebackType
4-
from typing import Any, Optional, Type
52

63
import aiohttp
74
from aiohttp import ClientSession
85

9-
from .response import Response
10-
from ..errors.client_error import ClientError
116
from ..errors.custom_error import CustomError
12-
from ..errors.internal_error import InternalError
13-
from ..errors.server_error import ServerError
147
from ..util import url
158

16-
Range = namedtuple('Range', 'lower, upper')
17-
18-
19-
class UninitializedError(CustomError):
20-
pass
9+
from .execute_request import execute_request
10+
from .get_get_headers import get_get_headers
11+
from .get_post_headers import get_post_headers
12+
from .response import Response
13+
from .validate_response import validate_response
2114

2215

2316
class HttpClient:
@@ -36,9 +29,9 @@ async def __aenter__(self):
3629

3730
async def __aexit__(
3831
self,
39-
exc_type: Optional[Type[BaseException]],
40-
exc_val: Optional[BaseException],
41-
exc_tb: Optional[TracebackType]
32+
exc_type: BaseException | None = None,
33+
exc_val: BaseException | None = None,
34+
exc_tb: TracebackType | None = None,
4235
) -> None:
4336
await self.close()
4437

@@ -53,114 +46,67 @@ async def close(self):
5346
self.__session = None
5447
return None
5548

56-
async def __execute_request(
57-
self,
58-
execute_request: Callable[[], Coroutine[Any, Any, Response]]
59-
) -> Response:
60-
try:
61-
result = await execute_request()
62-
return result
63-
except CustomError as custom_error:
64-
raise custom_error
65-
except aiohttp.ClientError as request_error:
66-
raise ServerError(str(request_error)) from request_error
67-
except Exception as other_error:
68-
raise InternalError(str(other_error)) from other_error
69-
70-
@staticmethod
71-
async def __get_error_message(response: Response):
72-
error_message = f'Request failed with status code \'{response.status_code}\''
73-
74-
# We want to purposefully ignore all errors here, as we're already error handling,
75-
# and this function just tries to get more information on a best-effort basis.
76-
try:
77-
encoded_error_reason = await response.body.read()
78-
error_reason = encoded_error_reason.decode('utf-8')
79-
error_message += f" {error_reason}"
80-
finally:
81-
pass
82-
83-
error_message += '.'
84-
85-
return error_message
86-
87-
async def __validate_response(
88-
self,
89-
response: Response
90-
) -> Response:
91-
server_failure_range = Range(500, 600)
92-
if server_failure_range.lower <= response.status_code < server_failure_range.upper:
93-
raise ServerError(await self.__get_error_message(response))
94-
95-
client_failure_range = Range(400, 500)
96-
if client_failure_range.lower <= response.status_code < client_failure_range.upper:
97-
raise ClientError(await self.__get_error_message(response))
98-
99-
return response
100-
101-
def __get_post_request_headers(self) -> dict[str, str]:
102-
headers = {
103-
'Authorization': f'Bearer {self.__api_token}',
104-
'Content-Type': 'application/json'
105-
}
106-
107-
return headers
108-
10949
async def post(self, path: str, request_body: str) -> Response:
11050
if self.__session is None:
111-
raise UninitializedError()
51+
raise CustomError()
11252

113-
async def execute_request() -> Response:
53+
async def request_executor() -> Response:
54+
# Vorbereitung
55+
url_path = url.join_segments(self.__base_url, path)
56+
headers = get_post_headers(self.__api_token)
57+
58+
# Request ausführen
11459
async_response = await self.__session.post( # type: ignore
115-
url.join_segments(
116-
self.__base_url,
117-
path
118-
),
60+
url_path,
11961
data=request_body,
120-
headers=self.__get_post_request_headers(),
62+
headers=headers,
12163
)
12264

65+
# Response erstellen
12366
response = Response(async_response)
67+
68+
# Split try block to have only one statement
69+
validated_response = None
12470
try:
125-
result = await self.__validate_response(response)
126-
return result
71+
validated_response = await validate_response(response)
12772
except Exception as error:
12873
response.close()
12974
raise error
13075

131-
return await self.__execute_request(execute_request)
76+
return validated_response
13277

133-
def __get_get_request_headers(self, with_authorization: bool) -> dict[str, str]:
134-
headers = {}
135-
136-
if with_authorization:
137-
headers['Authorization'] = f'Bearer {self.__api_token}'
138-
139-
return headers
78+
return await execute_request(request_executor)
14079

14180
async def get(
14281
self,
14382
path: str,
14483
with_authorization: bool = True,
14584
) -> Response:
14685
if self.__session is None:
147-
raise UninitializedError()
86+
raise CustomError()
87+
88+
async def request_executor() -> Response:
89+
# Vorbereitung
90+
url_path = url.join_segments(self.__base_url, path)
91+
headers = get_get_headers(self.__api_token, with_authorization)
14892

149-
async def execute_request() -> Response:
93+
# Request ausführen
15094
async_response = await self.__session.get( # type: ignore
151-
url.join_segments(
152-
self.__base_url,
153-
path
154-
),
155-
headers=self.__get_get_request_headers(with_authorization),
95+
url_path,
96+
headers=headers,
15697
)
15798

99+
# Response erstellen
158100
response = Response(async_response)
101+
102+
# Split try block to have only one statement
103+
validated_response = None
159104
try:
160-
result = await self.__validate_response(response)
161-
return result
105+
validated_response = await validate_response(response)
162106
except Exception as error:
163107
response.close()
164108
raise error
165109

166-
return await self.__execute_request(execute_request)
110+
return validated_response
111+
112+
return await execute_request(request_executor)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from collections import namedtuple
2+
3+
from ..errors.client_error import ClientError
4+
from ..errors.server_error import ServerError
5+
from .get_error_message import get_error_message
6+
from .response import Response
7+
8+
Range = namedtuple('Range', 'lower, upper')
9+
10+
async def validate_response(response: Response) -> Response:
11+
server_failure_range = Range(500, 600)
12+
if server_failure_range.lower <= response.status_code < server_failure_range.upper:
13+
raise ServerError(await get_error_message(response))
14+
15+
client_failure_range = Range(400, 500)
16+
if client_failure_range.lower <= response.status_code < client_failure_range.upper:
17+
raise ClientError(await get_error_message(response))
18+
19+
return response

eventsourcingdb/json_encoder.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
class EventSourcingDBJSONEncoder(json.JSONEncoder):
99
def default(self, o: Any) -> Any:
1010
if isinstance(o, Bound):
11-
return o.to_dict()
12-
elif isinstance(o, Enum):
11+
return o.to_json()
12+
if isinstance(o, Enum):
1313
return o.value
1414
return super().default(o)

0 commit comments

Comments
 (0)