gengineapi 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gengineapi/__init__.py +43 -0
- gengineapi/client.py +121 -0
- gengineapi/config.py +242 -0
- gengineapi/exceptions.py +125 -0
- gengineapi/http.py +540 -0
- gengineapi/modules/__init__.py +23 -0
- gengineapi/modules/auth.py +46 -0
- gengineapi/modules/base.py +196 -0
- gengineapi/modules/currencies.py +54 -0
- gengineapi/modules/finances.py +81 -0
- gengineapi/modules/payments.py +115 -0
- gengineapi/modules/transactions.py +70 -0
- gengineapi/modules/users.py +100 -0
- gengineapi-0.1.0.dist-info/METADATA +274 -0
- gengineapi-0.1.0.dist-info/RECORD +17 -0
- gengineapi-0.1.0.dist-info/WHEEL +5 -0
- gengineapi-0.1.0.dist-info/top_level.txt +1 -0
gengineapi/__init__.py
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
"""
|
2
|
+
G-Engine API Client - Асинхронный модульный клиент для взаимодействия с API G-Engine.
|
3
|
+
|
4
|
+
Предоставляет удобный интерфейс для работы с платежами, финансами,
|
5
|
+
пользователями и другими ресурсами API G-Engine.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from .client import GEngineClient
|
9
|
+
from .config import GEngineConfig
|
10
|
+
from .exceptions import (
|
11
|
+
ApiAuthError,
|
12
|
+
ApiConnectionError,
|
13
|
+
ApiError,
|
14
|
+
ApiForbiddenError,
|
15
|
+
ApiParsingError,
|
16
|
+
ApiResourceNotFoundError,
|
17
|
+
ApiServerError,
|
18
|
+
ApiServiceUnavailableError,
|
19
|
+
ApiTimeoutError,
|
20
|
+
ApiValidationError,
|
21
|
+
)
|
22
|
+
from .http import AsyncHttpClient
|
23
|
+
|
24
|
+
__version__ = "1.0.0"
|
25
|
+
__all__ = [
|
26
|
+
# Основной клиент
|
27
|
+
'GEngineClient',
|
28
|
+
# Конфигурация
|
29
|
+
'GEngineConfig',
|
30
|
+
# HTTP клиент
|
31
|
+
'AsyncHttpClient',
|
32
|
+
# Исключения
|
33
|
+
'ApiError',
|
34
|
+
'ApiConnectionError',
|
35
|
+
'ApiTimeoutError',
|
36
|
+
'ApiAuthError',
|
37
|
+
'ApiForbiddenError',
|
38
|
+
'ApiValidationError',
|
39
|
+
'ApiResourceNotFoundError',
|
40
|
+
'ApiServerError',
|
41
|
+
'ApiServiceUnavailableError',
|
42
|
+
'ApiParsingError',
|
43
|
+
]
|
gengineapi/client.py
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
"""
|
2
|
+
Основной класс клиента API G-Engine.
|
3
|
+
|
4
|
+
Предоставляет интерфейс для взаимодействия со всеми модулями API
|
5
|
+
и управления соединением.
|
6
|
+
"""
|
7
|
+
import logging
|
8
|
+
from typing import Optional
|
9
|
+
|
10
|
+
from .http import AsyncHttpClient
|
11
|
+
from .modules import (
|
12
|
+
AuthModule,
|
13
|
+
CurrenciesModule,
|
14
|
+
FinancesModule,
|
15
|
+
PaymentsModule,
|
16
|
+
TransactionsModule,
|
17
|
+
UsersModule,
|
18
|
+
)
|
19
|
+
|
20
|
+
|
21
|
+
class GEngineClient:
|
22
|
+
"""
|
23
|
+
Клиент для API G-Engine.
|
24
|
+
|
25
|
+
Предоставляет доступ ко всем модулям API через единый интерфейс
|
26
|
+
и управляет жизненным циклом HTTP-соединения.
|
27
|
+
"""
|
28
|
+
|
29
|
+
def __init__(
|
30
|
+
self,
|
31
|
+
base_url: str,
|
32
|
+
jwt_token: Optional[str] = None,
|
33
|
+
timeout: int = 30,
|
34
|
+
max_retries: int = 3,
|
35
|
+
logger: Optional[logging.Logger] = None,
|
36
|
+
proxy: Optional[str] = None,
|
37
|
+
) -> None:
|
38
|
+
"""
|
39
|
+
Инициализирует клиент API G-Engine.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
base_url: Базовый URL для API
|
43
|
+
jwt_token: JWT токен для аутентификации (если уже есть)
|
44
|
+
timeout: Таймаут для запросов в секундах (по умолчанию 30)
|
45
|
+
max_retries: Максимальное количество повторных попыток (по умолчанию 3)
|
46
|
+
logger: Логгер для записи информации (опционально)
|
47
|
+
proxy: Прокси для запросов в формате 'socks5://user:pass@host:port' (опционально)
|
48
|
+
"""
|
49
|
+
self.logger = logger or logging.getLogger(__name__)
|
50
|
+
|
51
|
+
if jwt_token:
|
52
|
+
self.logger.info("Клиент инициализирован с существующим JWT токеном")
|
53
|
+
|
54
|
+
if proxy:
|
55
|
+
self.logger.info(f"Клиент будет использовать прокси: {proxy}")
|
56
|
+
|
57
|
+
# Инициализация HTTP-клиента
|
58
|
+
self.http_client = AsyncHttpClient(
|
59
|
+
base_url=base_url,
|
60
|
+
jwt_token=jwt_token,
|
61
|
+
timeout=timeout,
|
62
|
+
max_retries=max_retries,
|
63
|
+
logger=self.logger,
|
64
|
+
proxy=proxy,
|
65
|
+
)
|
66
|
+
|
67
|
+
# Инициализация модулей API
|
68
|
+
self.auth = AuthModule(http_client=self.http_client, logger=self.logger)
|
69
|
+
self.payments = PaymentsModule(http_client=self.http_client, logger=self.logger)
|
70
|
+
self.finances = FinancesModule(http_client=self.http_client, logger=self.logger)
|
71
|
+
self.users = UsersModule(http_client=self.http_client, logger=self.logger)
|
72
|
+
self.transactions = TransactionsModule(http_client=self.http_client, logger=self.logger)
|
73
|
+
self.currencies = CurrenciesModule(http_client=self.http_client, logger=self.logger)
|
74
|
+
|
75
|
+
async def close(self) -> None:
|
76
|
+
"""
|
77
|
+
Закрывает соединение с API.
|
78
|
+
|
79
|
+
Должен быть вызван при завершении работы с клиентом.
|
80
|
+
"""
|
81
|
+
await self.http_client.close()
|
82
|
+
self.logger.info("Соединение с API закрыто")
|
83
|
+
|
84
|
+
async def __aenter__(self) -> "GEngineClient":
|
85
|
+
"""
|
86
|
+
Поддержка контекстного менеджера (async with).
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
GEngineClient: Экземпляр клиента API
|
90
|
+
"""
|
91
|
+
return self
|
92
|
+
|
93
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
|
94
|
+
"""
|
95
|
+
Закрывает соединение при выходе из контекстного менеджера.
|
96
|
+
"""
|
97
|
+
await self.close()
|
98
|
+
|
99
|
+
def update_token(self, jwt_token: str) -> None:
|
100
|
+
"""
|
101
|
+
Обновляет JWT токен для аутентификации.
|
102
|
+
|
103
|
+
Args:
|
104
|
+
jwt_token: Новый JWT токен
|
105
|
+
"""
|
106
|
+
self.http_client.update_token(jwt_token)
|
107
|
+
self.logger.info("JWT токен обновлен")
|
108
|
+
|
109
|
+
def update_proxy(self, proxy: Optional[str] = None) -> None:
|
110
|
+
"""
|
111
|
+
Обновляет настройки прокси.
|
112
|
+
|
113
|
+
Args:
|
114
|
+
proxy: Новый прокси в формате 'socks5://user:pass@host:port' или None для отключения прокси
|
115
|
+
"""
|
116
|
+
if hasattr(self.http_client, 'update_proxy'):
|
117
|
+
self.http_client.update_proxy(proxy)
|
118
|
+
if proxy:
|
119
|
+
self.logger.info(f"Прокси обновлен: {proxy}")
|
120
|
+
else:
|
121
|
+
self.logger.info("Прокси отключен")
|
gengineapi/config.py
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
"""
|
2
|
+
Модуль конфигурации для клиента G-Engine API.
|
3
|
+
|
4
|
+
Предоставляет класс для централизованной настройки параметров клиента
|
5
|
+
и возможность повторного использования клиента без необходимости
|
6
|
+
каждый раз указывать параметры.
|
7
|
+
"""
|
8
|
+
import os
|
9
|
+
import logging
|
10
|
+
import json
|
11
|
+
from pathlib import Path
|
12
|
+
from typing import Optional, Dict, Any, ClassVar
|
13
|
+
|
14
|
+
from .client import GEngineClient
|
15
|
+
|
16
|
+
|
17
|
+
class GEngineConfig:
|
18
|
+
"""
|
19
|
+
Класс-конфигурация для G-Engine клиента.
|
20
|
+
|
21
|
+
Позволяет настроить параметры клиента один раз и затем использовать
|
22
|
+
их для создания экземпляров клиента без повторного указания параметров.
|
23
|
+
|
24
|
+
Attributes:
|
25
|
+
base_url: Базовый URL для API
|
26
|
+
jwt_token: JWT токен для аутентификации
|
27
|
+
timeout: Таймаут для запросов в секундах
|
28
|
+
max_retries: Максимальное количество повторных попыток
|
29
|
+
logger: Логгер для записи информации
|
30
|
+
proxy: Прокси для запросов (например, 'socks5://user:pass@host:port')
|
31
|
+
|
32
|
+
Class Attributes:
|
33
|
+
_instance: Глобальный экземпляр клиента (для повторного использования)
|
34
|
+
"""
|
35
|
+
# Настройки по умолчанию
|
36
|
+
base_url: ClassVar[str] = "https://api.example.com/api/v2"
|
37
|
+
jwt_token: ClassVar[Optional[str]] = None
|
38
|
+
timeout: ClassVar[int] = 30
|
39
|
+
max_retries: ClassVar[int] = 3
|
40
|
+
logger: ClassVar[Optional[logging.Logger]] = None
|
41
|
+
proxy: ClassVar[Optional[str]] = None
|
42
|
+
|
43
|
+
# Глобальный экземпляр клиента
|
44
|
+
_instance: ClassVar[Optional[GEngineClient]] = None
|
45
|
+
|
46
|
+
@classmethod
|
47
|
+
def setup(cls,
|
48
|
+
base_url: Optional[str] = None,
|
49
|
+
jwt_token: Optional[str] = None,
|
50
|
+
timeout: Optional[int] = None,
|
51
|
+
max_retries: Optional[int] = None,
|
52
|
+
logger: Optional[logging.Logger] = None,
|
53
|
+
proxy: Optional[str] = None) -> None:
|
54
|
+
"""
|
55
|
+
Настраивает параметры клиента по умолчанию.
|
56
|
+
|
57
|
+
Args:
|
58
|
+
base_url: Базовый URL для API (опционально)
|
59
|
+
jwt_token: JWT токен для аутентификации (опционально)
|
60
|
+
timeout: Таймаут для запросов в секундах (опционально)
|
61
|
+
max_retries: Максимальное количество повторных попыток (опционально)
|
62
|
+
logger: Логгер для записи информации (опционально)
|
63
|
+
proxy: Прокси для запросов в формате 'socks5://user:pass@host:port' (опционально)
|
64
|
+
"""
|
65
|
+
if base_url:
|
66
|
+
cls.base_url = base_url
|
67
|
+
if jwt_token:
|
68
|
+
cls.jwt_token = jwt_token
|
69
|
+
if timeout:
|
70
|
+
cls.timeout = timeout
|
71
|
+
if max_retries:
|
72
|
+
cls.max_retries = max_retries
|
73
|
+
if logger:
|
74
|
+
cls.logger = logger
|
75
|
+
if proxy is not None: # Проверяем None, чтобы можно было передать пустую строку для отключения прокси
|
76
|
+
cls.proxy = proxy
|
77
|
+
|
78
|
+
# Если есть активный глобальный клиент, закрываем его
|
79
|
+
if cls._instance:
|
80
|
+
import asyncio
|
81
|
+
try:
|
82
|
+
# Пытаемся закрыть клиент синхронно, если мы в событийном цикле
|
83
|
+
asyncio.get_event_loop().create_task(cls.reset())
|
84
|
+
except RuntimeError:
|
85
|
+
# Если мы не в событийном цикле, просто отмечаем инстанс как None
|
86
|
+
# Реальное закрытие произойдет при следующем использовании
|
87
|
+
cls._instance = None
|
88
|
+
|
89
|
+
@classmethod
|
90
|
+
def load_from_env(cls) -> None:
|
91
|
+
"""
|
92
|
+
Загружает настройки из переменных окружения.
|
93
|
+
|
94
|
+
Ищет следующие переменные:
|
95
|
+
- GENGINE_BASE_URL: Базовый URL для API
|
96
|
+
- GENGINE_TOKEN: JWT токен для аутентификации
|
97
|
+
- GENGINE_TIMEOUT: Таймаут для запросов в секундах
|
98
|
+
- GENGINE_MAX_RETRIES: Максимальное количество повторных попыток
|
99
|
+
- GENGINE_PROXY: Прокси для запросов
|
100
|
+
"""
|
101
|
+
base_url = os.environ.get("GENGINE_BASE_URL")
|
102
|
+
jwt_token = os.environ.get("GENGINE_TOKEN")
|
103
|
+
timeout_str = os.environ.get("GENGINE_TIMEOUT")
|
104
|
+
max_retries_str = os.environ.get("GENGINE_MAX_RETRIES")
|
105
|
+
proxy = os.environ.get("GENGINE_PROXY")
|
106
|
+
|
107
|
+
# Преобразуем строковые значения в числа, если они есть
|
108
|
+
timeout = int(timeout_str) if timeout_str and timeout_str.isdigit() else None
|
109
|
+
max_retries = int(max_retries_str) if max_retries_str and max_retries_str.isdigit() else None
|
110
|
+
|
111
|
+
cls.setup(
|
112
|
+
base_url=base_url,
|
113
|
+
jwt_token=jwt_token,
|
114
|
+
timeout=timeout,
|
115
|
+
max_retries=max_retries,
|
116
|
+
proxy=proxy,
|
117
|
+
)
|
118
|
+
|
119
|
+
@classmethod
|
120
|
+
def load_from_file(cls, file_path: str) -> None:
|
121
|
+
"""
|
122
|
+
Загружает настройки из JSON-файла.
|
123
|
+
|
124
|
+
Args:
|
125
|
+
file_path: Путь к файлу настроек
|
126
|
+
|
127
|
+
Raises:
|
128
|
+
FileNotFoundError: Если файл не существует
|
129
|
+
json.JSONDecodeError: Если файл содержит некорректный JSON
|
130
|
+
"""
|
131
|
+
path = Path(file_path)
|
132
|
+
if not path.exists():
|
133
|
+
raise FileNotFoundError(f"Файл конфигурации не найден: {file_path}")
|
134
|
+
|
135
|
+
with open(path, "r") as f:
|
136
|
+
config = json.load(f)
|
137
|
+
|
138
|
+
cls.setup(
|
139
|
+
base_url=config.get("base_url"),
|
140
|
+
jwt_token=config.get("jwt_token"),
|
141
|
+
timeout=config.get("timeout"),
|
142
|
+
max_retries=config.get("max_retries"),
|
143
|
+
proxy=config.get("proxy"),
|
144
|
+
)
|
145
|
+
|
146
|
+
@classmethod
|
147
|
+
def save_to_file(cls, file_path: str) -> None:
|
148
|
+
"""
|
149
|
+
Сохраняет текущие настройки в JSON-файл.
|
150
|
+
|
151
|
+
Args:
|
152
|
+
file_path: Путь к файлу для сохранения настроек
|
153
|
+
"""
|
154
|
+
config = {
|
155
|
+
"base_url": cls.base_url,
|
156
|
+
"jwt_token": cls.jwt_token,
|
157
|
+
"timeout": cls.timeout,
|
158
|
+
"max_retries": cls.max_retries,
|
159
|
+
"proxy": cls.proxy,
|
160
|
+
}
|
161
|
+
|
162
|
+
with open(file_path, "w") as f:
|
163
|
+
json.dump(config, f, indent=2)
|
164
|
+
|
165
|
+
@classmethod
|
166
|
+
def get_client_kwargs(cls) -> Dict[str, Any]:
|
167
|
+
"""
|
168
|
+
Возвращает словарь с параметрами для создания клиента.
|
169
|
+
|
170
|
+
Returns:
|
171
|
+
Dict[str, Any]: Словарь с параметрами клиента
|
172
|
+
"""
|
173
|
+
return {
|
174
|
+
"base_url": cls.base_url,
|
175
|
+
"jwt_token": cls.jwt_token,
|
176
|
+
"timeout": cls.timeout,
|
177
|
+
"max_retries": cls.max_retries,
|
178
|
+
"logger": cls.logger,
|
179
|
+
"proxy": cls.proxy,
|
180
|
+
}
|
181
|
+
|
182
|
+
@classmethod
|
183
|
+
def create_client(cls) -> GEngineClient:
|
184
|
+
"""
|
185
|
+
Создает новый экземпляр клиента с текущими настройками.
|
186
|
+
|
187
|
+
Returns:
|
188
|
+
GEngineClient: Новый экземпляр клиента
|
189
|
+
"""
|
190
|
+
return GEngineClient(**cls.get_client_kwargs())
|
191
|
+
|
192
|
+
@classmethod
|
193
|
+
async def get_client(cls) -> GEngineClient:
|
194
|
+
"""
|
195
|
+
Возвращает глобальный экземпляр клиента или создает новый,
|
196
|
+
если глобальный экземпляр не существует.
|
197
|
+
|
198
|
+
Returns:
|
199
|
+
GEngineClient: Экземпляр клиента
|
200
|
+
"""
|
201
|
+
if cls._instance is None:
|
202
|
+
cls._instance = cls.create_client()
|
203
|
+
return cls._instance
|
204
|
+
|
205
|
+
@classmethod
|
206
|
+
async def reset(cls) -> None:
|
207
|
+
"""
|
208
|
+
Закрывает глобальный экземпляр клиента, если он существует.
|
209
|
+
"""
|
210
|
+
if cls._instance:
|
211
|
+
await cls._instance.close()
|
212
|
+
cls._instance = None
|
213
|
+
|
214
|
+
@classmethod
|
215
|
+
async def update_token(cls, jwt_token: str) -> None:
|
216
|
+
"""
|
217
|
+
Обновляет JWT токен в настройках и в глобальном экземпляре клиента.
|
218
|
+
|
219
|
+
Args:
|
220
|
+
jwt_token: Новый JWT токен
|
221
|
+
"""
|
222
|
+
cls.jwt_token = jwt_token
|
223
|
+
if cls._instance:
|
224
|
+
cls._instance.update_token(jwt_token)
|
225
|
+
|
226
|
+
@classmethod
|
227
|
+
async def update_proxy(cls, proxy: Optional[str] = None) -> None:
|
228
|
+
"""
|
229
|
+
Обновляет настройки прокси в конфигурации и в глобальном экземпляре клиента.
|
230
|
+
|
231
|
+
Args:
|
232
|
+
proxy: Новый прокси в формате 'socks5://user:pass@host:port' или None для отключения прокси
|
233
|
+
"""
|
234
|
+
cls.proxy = proxy
|
235
|
+
if cls._instance:
|
236
|
+
# Если клиент поддерживает обновление прокси
|
237
|
+
if hasattr(cls._instance.http_client, 'update_proxy'):
|
238
|
+
cls._instance.http_client.update_proxy(proxy)
|
239
|
+
else:
|
240
|
+
# Иначе пересоздаем клиент
|
241
|
+
await cls.reset()
|
242
|
+
cls._instance = cls.create_client()
|
gengineapi/exceptions.py
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
"""
|
2
|
+
Модуль для обработки исключений API клиента G-Engine.
|
3
|
+
|
4
|
+
Содержит иерархию исключений для различных типов ошибок,
|
5
|
+
которые могут возникнуть при взаимодействии с API.
|
6
|
+
"""
|
7
|
+
from typing import Any, Dict, Optional, Union
|
8
|
+
|
9
|
+
|
10
|
+
class ApiError(Exception):
|
11
|
+
"""Базовое исключение для всех ошибок API."""
|
12
|
+
|
13
|
+
def __init__(
|
14
|
+
self,
|
15
|
+
message: str,
|
16
|
+
status_code: Optional[int] = None,
|
17
|
+
response_data: Optional[Dict[str, Any]] = None,
|
18
|
+
) -> None:
|
19
|
+
"""
|
20
|
+
Инициализация базового исключения API.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
message: Сообщение об ошибке
|
24
|
+
status_code: HTTP-код ответа
|
25
|
+
response_data: Данные из ответа API
|
26
|
+
"""
|
27
|
+
self.message = message
|
28
|
+
self.status_code = status_code
|
29
|
+
self.response_data = response_data or {}
|
30
|
+
super().__init__(self.message)
|
31
|
+
|
32
|
+
def __str__(self) -> str:
|
33
|
+
"""Строковое представление исключения."""
|
34
|
+
parts = [self.message]
|
35
|
+
if self.status_code:
|
36
|
+
parts.append(f"Status code: {self.status_code}")
|
37
|
+
if self.response_data:
|
38
|
+
parts.append(f"Response data: {self.response_data}")
|
39
|
+
return " | ".join(parts)
|
40
|
+
|
41
|
+
|
42
|
+
# Ошибки соединения
|
43
|
+
class ApiConnectionError(ApiError):
|
44
|
+
"""Исключение при ошибках соединения с API."""
|
45
|
+
pass
|
46
|
+
|
47
|
+
|
48
|
+
class ApiTimeoutError(ApiConnectionError):
|
49
|
+
"""Исключение при превышении времени ожидания ответа от API."""
|
50
|
+
pass
|
51
|
+
|
52
|
+
|
53
|
+
# Ошибки авторизации
|
54
|
+
class ApiAuthError(ApiError):
|
55
|
+
"""Исключение при ошибках авторизации."""
|
56
|
+
pass
|
57
|
+
|
58
|
+
|
59
|
+
class ApiForbiddenError(ApiAuthError):
|
60
|
+
"""Исключение при отсутствии доступа к ресурсу."""
|
61
|
+
pass
|
62
|
+
|
63
|
+
|
64
|
+
# Ошибки валидации
|
65
|
+
class ApiValidationError(ApiError):
|
66
|
+
"""Исключение при ошибках валидации запроса."""
|
67
|
+
pass
|
68
|
+
|
69
|
+
|
70
|
+
# Ошибки ресурсов
|
71
|
+
class ApiResourceNotFoundError(ApiError):
|
72
|
+
"""Исключение при запросе несуществующего ресурса."""
|
73
|
+
pass
|
74
|
+
|
75
|
+
|
76
|
+
# Серверные ошибки
|
77
|
+
class ApiServerError(ApiError):
|
78
|
+
"""Исключение при ошибках на стороне сервера."""
|
79
|
+
pass
|
80
|
+
|
81
|
+
|
82
|
+
class ApiServiceUnavailableError(ApiServerError):
|
83
|
+
"""Исключение при недоступности сервиса."""
|
84
|
+
pass
|
85
|
+
|
86
|
+
|
87
|
+
# Ошибки парсинга
|
88
|
+
class ApiParsingError(ApiError):
|
89
|
+
"""Исключение при ошибках парсинга ответа API."""
|
90
|
+
pass
|
91
|
+
|
92
|
+
|
93
|
+
def create_api_error(
|
94
|
+
status_code: int,
|
95
|
+
message: str = None,
|
96
|
+
response_data: Optional[Dict[str, Any]] = None
|
97
|
+
) -> ApiError:
|
98
|
+
"""
|
99
|
+
Фабрика для создания соответствующего исключения по коду статуса HTTP.
|
100
|
+
|
101
|
+
Args:
|
102
|
+
status_code: HTTP-код ответа
|
103
|
+
message: Сообщение об ошибке (опционально)
|
104
|
+
response_data: Данные из ответа API (опционально)
|
105
|
+
|
106
|
+
Returns:
|
107
|
+
ApiError: Соответствующее исключение
|
108
|
+
"""
|
109
|
+
default_message = f"API вернул ошибку со статусом {status_code}"
|
110
|
+
message = message or default_message
|
111
|
+
|
112
|
+
error_classes = {
|
113
|
+
400: ApiValidationError,
|
114
|
+
401: ApiAuthError,
|
115
|
+
403: ApiForbiddenError,
|
116
|
+
404: ApiResourceNotFoundError,
|
117
|
+
408: ApiTimeoutError,
|
118
|
+
500: ApiServerError,
|
119
|
+
502: ApiServerError,
|
120
|
+
503: ApiServiceUnavailableError,
|
121
|
+
504: ApiTimeoutError,
|
122
|
+
}
|
123
|
+
|
124
|
+
error_class = error_classes.get(status_code, ApiError)
|
125
|
+
return error_class(message=message, status_code=status_code, response_data=response_data)
|