arpakitlib 1.7.213__py3-none-any.whl → 1.7.216__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.
- arpakitlib/ar_arpakit_schedule_uust_api_client_util.py +173 -272
- arpakitlib/ar_fastapi_util.py +20 -10
- arpakitlib/ar_http_request_util.py +20 -8
- arpakitlib/ar_schedule_uust_api_client_util.py +4 -2
- {arpakitlib-1.7.213.dist-info → arpakitlib-1.7.216.dist-info}/METADATA +1 -1
- {arpakitlib-1.7.213.dist-info → arpakitlib-1.7.216.dist-info}/RECORD +9 -9
- {arpakitlib-1.7.213.dist-info → arpakitlib-1.7.216.dist-info}/LICENSE +0 -0
- {arpakitlib-1.7.213.dist-info → arpakitlib-1.7.216.dist-info}/WHEEL +0 -0
- {arpakitlib-1.7.213.dist-info → arpakitlib-1.7.216.dist-info}/entry_points.txt +0 -0
@@ -3,23 +3,18 @@
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
5
|
import asyncio
|
6
|
-
import hashlib
|
7
|
-
import json
|
8
6
|
import logging
|
9
7
|
from datetime import timedelta, datetime, time
|
10
8
|
from typing import Any
|
11
9
|
from urllib.parse import urljoin
|
12
10
|
|
13
|
-
import aiohttp
|
14
11
|
import cachetools
|
15
|
-
from aiohttp import ClientResponse
|
12
|
+
from aiohttp import ClientResponse
|
16
13
|
from pydantic import ConfigDict, BaseModel
|
17
14
|
|
18
|
-
from arpakitlib.ar_dict_util import combine_dicts
|
19
15
|
from arpakitlib.ar_enumeration_util import Enumeration
|
16
|
+
from arpakitlib.ar_http_request_util import async_make_http_request
|
20
17
|
from arpakitlib.ar_json_util import safely_transfer_obj_to_json_str
|
21
|
-
from arpakitlib.ar_sleep_util import async_safe_sleep
|
22
|
-
from arpakitlib.ar_type_util import raise_for_type
|
23
18
|
|
24
19
|
_ARPAKIT_LIB_MODULE_VERSION = "3.0"
|
25
20
|
|
@@ -52,14 +47,31 @@ class Months(Enumeration):
|
|
52
47
|
class BaseAPIModel(BaseModel):
|
53
48
|
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True, from_attributes=True)
|
54
49
|
|
55
|
-
|
56
|
-
|
50
|
+
|
51
|
+
class CurrentSemesterAPIModel(BaseAPIModel):
|
52
|
+
id: int
|
53
|
+
long_id: str
|
54
|
+
creation_dt: datetime
|
55
|
+
entity_type: str
|
56
|
+
actualization_dt: datetime
|
57
|
+
value: str
|
58
|
+
|
59
|
+
|
60
|
+
class CurrentWeekAPIModel(BaseAPIModel):
|
61
|
+
id: int
|
62
|
+
long_id: str
|
63
|
+
creation_dt: datetime
|
64
|
+
entity_type: str
|
65
|
+
actualization_dt: datetime
|
66
|
+
value: int
|
57
67
|
|
58
68
|
|
59
69
|
class GroupAPIModel(BaseAPIModel):
|
60
70
|
id: int
|
71
|
+
long_id: str
|
61
72
|
creation_dt: datetime
|
62
|
-
|
73
|
+
entity_type: str
|
74
|
+
actualization_dt: datetime
|
63
75
|
uust_api_id: int
|
64
76
|
title: str
|
65
77
|
faculty: str | None
|
@@ -67,20 +79,13 @@ class GroupAPIModel(BaseAPIModel):
|
|
67
79
|
difference_level: int | None = None
|
68
80
|
uust_api_data: dict[str, Any]
|
69
81
|
|
70
|
-
arpakit_uust_api_data: dict[str, Any]
|
71
|
-
|
72
|
-
@classmethod
|
73
|
-
def from_arpakit_uust_api_data(cls, arpakit_uust_api_data: dict[str, Any]) -> GroupAPIModel:
|
74
|
-
return GroupAPIModel.model_validate(combine_dicts(
|
75
|
-
arpakit_uust_api_data,
|
76
|
-
{"arpakit_uust_api_data": arpakit_uust_api_data}
|
77
|
-
))
|
78
|
-
|
79
82
|
|
80
83
|
class TeacherAPIModel(BaseAPIModel):
|
81
84
|
id: int
|
85
|
+
long_id: str
|
82
86
|
creation_dt: datetime
|
83
|
-
|
87
|
+
entity_type: str
|
88
|
+
actualization_dt: datetime
|
84
89
|
uust_api_id: int
|
85
90
|
name: str | None
|
86
91
|
surname: str | None
|
@@ -94,20 +99,13 @@ class TeacherAPIModel(BaseAPIModel):
|
|
94
99
|
difference_level: int | None
|
95
100
|
uust_api_data: dict[str, Any]
|
96
101
|
|
97
|
-
arpakit_uust_api_data: dict[str, Any]
|
98
|
-
|
99
|
-
@classmethod
|
100
|
-
def from_arpakit_uust_api_data(cls, arpakit_uust_api_data: dict[str, Any]) -> TeacherAPIModel:
|
101
|
-
return TeacherAPIModel.model_validate(combine_dicts(
|
102
|
-
arpakit_uust_api_data,
|
103
|
-
{"arpakit_uust_api_data": arpakit_uust_api_data}
|
104
|
-
))
|
105
|
-
|
106
102
|
|
107
103
|
class GroupLessonAPIModel(BaseAPIModel):
|
108
104
|
id: int
|
105
|
+
long_id: str
|
109
106
|
creation_dt: datetime
|
110
|
-
|
107
|
+
entity_type: str
|
108
|
+
actualization_dt: datetime
|
111
109
|
uust_api_id: int
|
112
110
|
type: str
|
113
111
|
title: str
|
@@ -125,29 +123,6 @@ class GroupLessonAPIModel(BaseAPIModel):
|
|
125
123
|
teacher: TeacherAPIModel | None
|
126
124
|
uust_api_data: dict[str, Any]
|
127
125
|
|
128
|
-
arpakit_uust_api_data: dict[str, Any]
|
129
|
-
|
130
|
-
@classmethod
|
131
|
-
def from_arpakit_uust_api_data(cls, arpakit_uust_api_data: dict[str, Any]) -> GroupLessonAPIModel:
|
132
|
-
return GroupLessonAPIModel.model_validate(combine_dicts(
|
133
|
-
arpakit_uust_api_data,
|
134
|
-
{"arpakit_uust_api_data": arpakit_uust_api_data},
|
135
|
-
{
|
136
|
-
"group": GroupAPIModel.from_arpakit_uust_api_data(
|
137
|
-
arpakit_uust_api_data=arpakit_uust_api_data["group"]
|
138
|
-
)
|
139
|
-
},
|
140
|
-
{
|
141
|
-
"teacher": (
|
142
|
-
TeacherAPIModel.from_arpakit_uust_api_data(
|
143
|
-
arpakit_uust_api_data=arpakit_uust_api_data["teacher"]
|
144
|
-
)
|
145
|
-
if arpakit_uust_api_data["teacher"] is not None
|
146
|
-
else None
|
147
|
-
)
|
148
|
-
},
|
149
|
-
))
|
150
|
-
|
151
126
|
def compare_type(self, *types: str | list[str]) -> bool:
|
152
127
|
type_ = self.type.strip().lower()
|
153
128
|
for type__ in types:
|
@@ -165,8 +140,10 @@ class GroupLessonAPIModel(BaseAPIModel):
|
|
165
140
|
|
166
141
|
class TeacherLessonAPIModel(BaseAPIModel):
|
167
142
|
id: int
|
143
|
+
long_id: str
|
168
144
|
creation_dt: datetime
|
169
|
-
|
145
|
+
entity_type: str
|
146
|
+
actualization_dt: datetime
|
170
147
|
uust_api_id: int
|
171
148
|
type: str
|
172
149
|
title: str
|
@@ -184,26 +161,6 @@ class TeacherLessonAPIModel(BaseAPIModel):
|
|
184
161
|
groups: list[GroupAPIModel]
|
185
162
|
uust_api_data: dict[str, Any]
|
186
163
|
|
187
|
-
arpakit_uust_api_data: dict[str, Any]
|
188
|
-
|
189
|
-
@classmethod
|
190
|
-
def from_arpakit_uust_api_data(cls, arpakit_uust_api_data: dict[str, Any]) -> TeacherLessonAPIModel:
|
191
|
-
return TeacherLessonAPIModel.model_validate(combine_dicts(
|
192
|
-
arpakit_uust_api_data,
|
193
|
-
{"arpakit_uust_api_data": arpakit_uust_api_data},
|
194
|
-
{
|
195
|
-
"teacher": TeacherAPIModel.from_arpakit_uust_api_data(
|
196
|
-
arpakit_uust_api_data=arpakit_uust_api_data["teacher"]
|
197
|
-
)
|
198
|
-
},
|
199
|
-
{
|
200
|
-
"groups": [
|
201
|
-
GroupAPIModel.from_arpakit_uust_api_data(arpakit_uust_api_data=d)
|
202
|
-
for d in arpakit_uust_api_data["groups"]
|
203
|
-
]
|
204
|
-
},
|
205
|
-
))
|
206
|
-
|
207
164
|
def compare_type(self, *types: str | list[str]) -> bool:
|
208
165
|
type_ = self.type.strip().lower()
|
209
166
|
for type__ in types:
|
@@ -219,39 +176,6 @@ class TeacherLessonAPIModel(BaseAPIModel):
|
|
219
176
|
return False
|
220
177
|
|
221
178
|
|
222
|
-
class CurrentSemesterAPIModel(BaseAPIModel):
|
223
|
-
id: int
|
224
|
-
creation_dt: datetime
|
225
|
-
sync_from_uust_api_dt: datetime
|
226
|
-
value: str
|
227
|
-
raw_value: str
|
228
|
-
|
229
|
-
arpakit_uust_api_data: dict[str, Any]
|
230
|
-
|
231
|
-
@classmethod
|
232
|
-
def from_arpakit_uust_api_data(cls, *, arpakit_uust_api_data: dict[str, Any]) -> CurrentSemesterAPIModel:
|
233
|
-
return CurrentSemesterAPIModel.model_validate(combine_dicts(
|
234
|
-
arpakit_uust_api_data,
|
235
|
-
{"arpakit_uust_api_data": arpakit_uust_api_data}
|
236
|
-
))
|
237
|
-
|
238
|
-
|
239
|
-
class CurrentWeekAPIModel(BaseAPIModel):
|
240
|
-
id: int
|
241
|
-
creation_dt: datetime
|
242
|
-
sync_from_uust_api_dt: datetime
|
243
|
-
value: str
|
244
|
-
|
245
|
-
arpakit_uust_api_data: dict[str, Any]
|
246
|
-
|
247
|
-
@classmethod
|
248
|
-
def from_arpakit_uust_api_data(cls, *, arpakit_uust_api_data: dict[str, Any]) -> CurrentWeekAPIModel:
|
249
|
-
return CurrentWeekAPIModel.model_validate(combine_dicts(
|
250
|
-
arpakit_uust_api_data,
|
251
|
-
{"arpakit_uust_api_data": arpakit_uust_api_data}
|
252
|
-
))
|
253
|
-
|
254
|
-
|
255
179
|
class WeatherInUfaAPIModel(BaseAPIModel):
|
256
180
|
temperature: float
|
257
181
|
temperature_feels_like: float
|
@@ -263,15 +187,6 @@ class WeatherInUfaAPIModel(BaseAPIModel):
|
|
263
187
|
has_snow: bool
|
264
188
|
data: dict
|
265
189
|
|
266
|
-
arpakit_uust_api_data: dict[str, Any]
|
267
|
-
|
268
|
-
@classmethod
|
269
|
-
def from_arpakit_uust_api_data(cls, arpakit_uust_api_data: dict[float, Any]) -> WeatherInUfaAPIModel:
|
270
|
-
return WeatherInUfaAPIModel.model_validate(combine_dicts(
|
271
|
-
arpakit_uust_api_data,
|
272
|
-
{"arpakit_uust_api_data": arpakit_uust_api_data}
|
273
|
-
))
|
274
|
-
|
275
190
|
|
276
191
|
class ARPAKITScheduleUUSTAPIClient:
|
277
192
|
def __init__(
|
@@ -280,7 +195,7 @@ class ARPAKITScheduleUUSTAPIClient:
|
|
280
195
|
base_url: str = "https://api.schedule-uust.arpakit.com/api/v1",
|
281
196
|
api_key: str | None = "viewer",
|
282
197
|
use_cache: bool = False,
|
283
|
-
cache_ttl:
|
198
|
+
cache_ttl: timedelta | None = timedelta(minutes=10)
|
284
199
|
):
|
285
200
|
self._logger = logging.getLogger(__name__)
|
286
201
|
self.api_key = api_key
|
@@ -290,116 +205,75 @@ class ARPAKITScheduleUUSTAPIClient:
|
|
290
205
|
self.base_url = base_url
|
291
206
|
self.headers = {"Content-Type": "application/json"}
|
292
207
|
if api_key is not None:
|
293
|
-
self.headers.update({"apikey": api_key})
|
208
|
+
self.headers.update({"apikey": self.api_key})
|
294
209
|
self.use_cache = use_cache
|
295
210
|
self.cache_ttl = cache_ttl
|
296
211
|
if cache_ttl is not None:
|
297
|
-
self.ttl_cache = cachetools.TTLCache(maxsize=100, ttl=cache_ttl)
|
212
|
+
self.ttl_cache = cachetools.TTLCache(maxsize=100, ttl=cache_ttl.total_seconds())
|
298
213
|
else:
|
299
214
|
self.ttl_cache = None
|
300
215
|
|
301
|
-
def
|
216
|
+
def clear_cache(self):
|
302
217
|
if self.ttl_cache is not None:
|
303
218
|
self.ttl_cache.clear()
|
304
219
|
|
305
|
-
async def
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
220
|
+
async def _async_make_http_request(
|
221
|
+
self,
|
222
|
+
*,
|
223
|
+
method: str = "GET",
|
224
|
+
url: str,
|
225
|
+
params: dict[str, Any] | None = None,
|
226
|
+
**kwargs
|
227
|
+
) -> ClientResponse:
|
228
|
+
response = await async_make_http_request(
|
229
|
+
method=method,
|
230
|
+
url=url,
|
231
|
+
headers=self.headers,
|
232
|
+
params=params,
|
233
|
+
raise_for_status_=True,
|
234
|
+
**kwargs
|
317
235
|
)
|
236
|
+
return response
|
318
237
|
|
319
|
-
|
320
|
-
|
321
|
-
return self.ttl_cache[cache_key]
|
322
|
-
|
323
|
-
while True:
|
324
|
-
tries += 1
|
325
|
-
self._logger.info(f"{method} {url}")
|
326
|
-
try:
|
327
|
-
async with aiohttp.ClientSession() as session:
|
328
|
-
async with session.request(**kwargs) as response:
|
329
|
-
await response.read()
|
330
|
-
if self.use_cache and self.ttl_cache is not None:
|
331
|
-
self.ttl_cache[cache_key] = response
|
332
|
-
return response
|
333
|
-
except Exception as err:
|
334
|
-
self._logger.warning(f"{tries}/{max_tries} {err} {method} {url}")
|
335
|
-
if tries >= max_tries:
|
336
|
-
raise err
|
337
|
-
await async_safe_sleep(timedelta(seconds=0.1).total_seconds())
|
338
|
-
continue
|
339
|
-
|
340
|
-
async def healthcheck(self) -> bool:
|
341
|
-
response = await self._async_make_request(method="GET", url=urljoin(self.base_url, "healthcheck"))
|
342
|
-
response.raise_for_status()
|
238
|
+
async def check_auth(self) -> dict[str, Any]:
|
239
|
+
response = await self._async_make_http_request(method="GET", url=urljoin(self.base_url, "check_auth"))
|
343
240
|
json_data = await response.json()
|
344
|
-
return json_data
|
241
|
+
return json_data
|
345
242
|
|
346
|
-
async def
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
return False
|
351
|
-
|
352
|
-
async def auth_healthcheck(self) -> bool:
|
353
|
-
response = await self._async_make_request(method="GET", url=urljoin(self.base_url, "auth_healthcheck"))
|
354
|
-
response.raise_for_status()
|
355
|
-
json_data = await response.json()
|
356
|
-
return json_data["data"]["auth_healthcheck"]
|
357
|
-
|
358
|
-
async def is_auth_healthcheck_good(self) -> bool:
|
359
|
-
try:
|
360
|
-
return await self.auth_healthcheck()
|
361
|
-
except ClientResponseError:
|
362
|
-
return False
|
363
|
-
|
364
|
-
async def get_required_current_week_value(self) -> int:
|
365
|
-
response = await self._async_make_request(method="GET", url=urljoin(self.base_url, "get_current_week"))
|
366
|
-
response.raise_for_status()
|
243
|
+
async def get_current_week(self) -> CurrentWeekAPIModel | None:
|
244
|
+
response = await self._async_make_http_request(
|
245
|
+
method="GET", url=urljoin(self.base_url, "get_current_week")
|
246
|
+
)
|
367
247
|
json_data = await response.json()
|
368
|
-
|
369
|
-
|
248
|
+
if json_data is None:
|
249
|
+
return None
|
250
|
+
return CurrentWeekAPIModel.model_validate(json_data)
|
370
251
|
|
371
252
|
async def get_current_semester(self) -> CurrentSemesterAPIModel | None:
|
372
|
-
response = await self.
|
253
|
+
response = await self._async_make_http_request(
|
254
|
+
method="GET", url=urljoin(self.base_url, "get_current_semester")
|
255
|
+
)
|
373
256
|
json_data = await response.json()
|
374
257
|
if json_data is None:
|
375
258
|
return None
|
376
|
-
|
377
|
-
return None
|
378
|
-
response.raise_for_status()
|
379
|
-
return CurrentSemesterAPIModel.from_arpakit_uust_api_data(arpakit_uust_api_data=json_data)
|
259
|
+
return CurrentSemesterAPIModel.model_validate(json_data)
|
380
260
|
|
381
|
-
async def
|
382
|
-
response = await self.
|
261
|
+
async def get_weather_in_ufa(self) -> WeatherInUfaAPIModel:
|
262
|
+
response = await self._async_make_http_request(
|
263
|
+
method="GET", url=urljoin(self.base_url, "get_weather_in_ufa")
|
264
|
+
)
|
383
265
|
json_data = await response.json()
|
384
|
-
|
385
|
-
return None
|
386
|
-
if "error_code" in json_data and json_data["error_code"] == "CURRENT_WEEK_NOT_FOUND":
|
387
|
-
return None
|
388
|
-
response.raise_for_status()
|
389
|
-
return CurrentWeekAPIModel.from_arpakit_uust_api_data(arpakit_uust_api_data=json_data)
|
266
|
+
return WeatherInUfaAPIModel.model_validate(json_data)
|
390
267
|
|
391
268
|
async def get_log_file_content(self) -> str | None:
|
392
|
-
|
393
|
-
response = await self._async_make_request(method="GET", url=urljoin(self.base_url, "extra/get_log_file"))
|
394
|
-
response.raise_for_status()
|
269
|
+
response = await self._async_make_http_request(method="GET", url=urljoin(self.base_url, "get_log_file"))
|
395
270
|
text_data = await response.text()
|
396
271
|
return text_data
|
397
272
|
|
398
273
|
async def get_groups(self) -> list[GroupAPIModel]:
|
399
|
-
response = await self.
|
400
|
-
response.raise_for_status()
|
274
|
+
response = await self._async_make_http_request(method="GET", url=urljoin(self.base_url, "get_groups"))
|
401
275
|
json_data = await response.json()
|
402
|
-
return [GroupAPIModel.
|
276
|
+
return [GroupAPIModel.model_validate(d) for d in json_data]
|
403
277
|
|
404
278
|
async def get_group(
|
405
279
|
self, *, filter_id: int | None = None, filter_uust_api_id: int | None = None
|
@@ -409,34 +283,25 @@ class ARPAKITScheduleUUSTAPIClient:
|
|
409
283
|
params["filter_id"] = filter_id
|
410
284
|
if filter_uust_api_id is not None:
|
411
285
|
params["filter_uust_api_id"] = filter_uust_api_id
|
412
|
-
response = await self.
|
413
|
-
|
414
|
-
url=urljoin(self.base_url, "group/get_group"),
|
415
|
-
params=params
|
416
|
-
)
|
286
|
+
response = await self._async_make_http_request(method="GET", url=urljoin(self.base_url, "get_group"),
|
287
|
+
params=params)
|
417
288
|
json_data = await response.json()
|
418
|
-
if
|
289
|
+
if json_data is None:
|
419
290
|
return None
|
420
|
-
|
421
|
-
return GroupAPIModel.from_arpakit_uust_api_data(arpakit_uust_api_data=json_data)
|
291
|
+
return GroupAPIModel.model_validate(json_data)
|
422
292
|
|
423
293
|
async def find_groups(
|
424
294
|
self, *, q: str
|
425
295
|
) -> list[GroupAPIModel]:
|
426
|
-
response = await self.
|
427
|
-
|
428
|
-
url=urljoin(self.base_url, "group/find_groups"),
|
429
|
-
params={"q": q.strip()}
|
430
|
-
)
|
431
|
-
response.raise_for_status()
|
296
|
+
response = await self._async_make_http_request(method="GET", url=urljoin(self.base_url, "find_groups"),
|
297
|
+
params={"q": q.strip()})
|
432
298
|
json_data = await response.json()
|
433
|
-
return [GroupAPIModel.
|
299
|
+
return [GroupAPIModel.model_validate(d) for d in json_data]
|
434
300
|
|
435
301
|
async def get_teachers(self) -> list[TeacherAPIModel]:
|
436
|
-
response = await self.
|
437
|
-
response.raise_for_status()
|
302
|
+
response = await self._async_make_http_request(method="GET", url=urljoin(self.base_url, "get_teachers"))
|
438
303
|
json_data = await response.json()
|
439
|
-
return [TeacherAPIModel.
|
304
|
+
return [TeacherAPIModel.model_validate(d) for d in json_data]
|
440
305
|
|
441
306
|
async def get_teacher(
|
442
307
|
self, *, filter_id: int | None = None, filter_uust_api_id: int | None = None
|
@@ -446,28 +311,37 @@ class ARPAKITScheduleUUSTAPIClient:
|
|
446
311
|
params["filter_id"] = filter_id
|
447
312
|
if filter_uust_api_id is not None:
|
448
313
|
params["filter_uust_api_id"] = filter_uust_api_id
|
449
|
-
response = await self.
|
450
|
-
|
451
|
-
url=urljoin(self.base_url, "teacher/get_teacher"),
|
452
|
-
params=params
|
453
|
-
)
|
314
|
+
response = await self._async_make_http_request(method="GET", url=urljoin(self.base_url, "get_teacher"),
|
315
|
+
params=params)
|
454
316
|
json_data = await response.json()
|
455
|
-
if
|
317
|
+
if json_data is None:
|
456
318
|
return None
|
457
|
-
|
458
|
-
return TeacherAPIModel.from_arpakit_uust_api_data(arpakit_uust_api_data=json_data)
|
319
|
+
return TeacherAPIModel.model_validate(json_data)
|
459
320
|
|
460
321
|
async def find_teachers(
|
461
322
|
self, *, q: str
|
462
323
|
) -> list[TeacherAPIModel]:
|
463
|
-
response = await self.
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
324
|
+
response = await self._async_make_http_request(method="GET", url=urljoin(self.base_url, "find_teachers"),
|
325
|
+
params={"q": q.strip()})
|
326
|
+
json_data = await response.json()
|
327
|
+
return [TeacherAPIModel.model_validate(d) for d in json_data]
|
328
|
+
|
329
|
+
async def find_any(
|
330
|
+
self, *, q: str
|
331
|
+
) -> list[TeacherAPIModel | GroupLessonAPIModel]:
|
332
|
+
response = await self._async_make_http_request(method="GET", url=urljoin(self.base_url, "find_any"),
|
333
|
+
params={"q": q.strip()})
|
469
334
|
json_data = await response.json()
|
470
|
-
|
335
|
+
|
336
|
+
results = []
|
337
|
+
for i in json_data:
|
338
|
+
if i.get("entity_type") == "group":
|
339
|
+
results.append(GroupAPIModel.model_validate(i))
|
340
|
+
elif i.get("entity_type") == "teacher":
|
341
|
+
results.append(TeacherAPIModel.model_validate(i))
|
342
|
+
else:
|
343
|
+
pass
|
344
|
+
return results
|
471
345
|
|
472
346
|
async def get_group_lessons(
|
473
347
|
self,
|
@@ -480,14 +354,11 @@ class ARPAKITScheduleUUSTAPIClient:
|
|
480
354
|
params["filter_group_id"] = filter_group_id
|
481
355
|
if filter_group_uust_api_id is not None:
|
482
356
|
params["filter_group_uust_api_id"] = filter_group_uust_api_id
|
483
|
-
response = await self.
|
484
|
-
method="GET",
|
485
|
-
url=urljoin(self.base_url, "group_lesson/get_group_lessons"),
|
486
|
-
params=params
|
357
|
+
response = await self._async_make_http_request(
|
358
|
+
method="GET", url=urljoin(self.base_url, "get_group_lessons"), params=params
|
487
359
|
)
|
488
|
-
response.raise_for_status()
|
489
360
|
json_data = await response.json()
|
490
|
-
return [GroupLessonAPIModel.
|
361
|
+
return [GroupLessonAPIModel.model_validate(d) for d in json_data]
|
491
362
|
|
492
363
|
async def get_teacher_lessons(
|
493
364
|
self,
|
@@ -500,20 +371,11 @@ class ARPAKITScheduleUUSTAPIClient:
|
|
500
371
|
params["filter_teacher_id"] = filter_teacher_id
|
501
372
|
if filter_teacher_uust_api_id is not None:
|
502
373
|
params["filter_teacher_uust_api_id"] = filter_teacher_uust_api_id
|
503
|
-
response = await self.
|
504
|
-
method="GET",
|
505
|
-
url=urljoin(self.base_url, "teacher_lesson/get_teacher_lessons"),
|
506
|
-
params=params
|
374
|
+
response = await self._async_make_http_request(
|
375
|
+
method="GET", url=urljoin(self.base_url, "get_teacher_lessons"), params=params
|
507
376
|
)
|
508
|
-
response.raise_for_status()
|
509
377
|
json_data = await response.json()
|
510
|
-
return [TeacherLessonAPIModel.
|
511
|
-
|
512
|
-
async def get_weather_in_ufa(self) -> WeatherInUfaAPIModel:
|
513
|
-
response = await self._async_make_request(method="GET", url=urljoin(self.base_url, "get_weather_in_ufa"))
|
514
|
-
response.raise_for_status()
|
515
|
-
json_data = await response.json()
|
516
|
-
return WeatherInUfaAPIModel.from_arpakit_uust_api_data(json_data)
|
378
|
+
return [TeacherLessonAPIModel.model_validate(d) for d in json_data]
|
517
379
|
|
518
380
|
|
519
381
|
def __example():
|
@@ -521,28 +383,67 @@ def __example():
|
|
521
383
|
|
522
384
|
|
523
385
|
async def __async_example():
|
524
|
-
client = ARPAKITScheduleUUSTAPIClient(api_key="
|
525
|
-
|
526
|
-
|
527
|
-
print(
|
528
|
-
|
529
|
-
|
530
|
-
print(
|
531
|
-
|
532
|
-
|
533
|
-
print(
|
534
|
-
|
535
|
-
|
536
|
-
print(
|
537
|
-
|
538
|
-
|
539
|
-
print(f"
|
540
|
-
|
541
|
-
|
542
|
-
print(f"
|
543
|
-
|
544
|
-
|
545
|
-
|
386
|
+
client = ARPAKITScheduleUUSTAPIClient(api_key="viewer", use_cache=True)
|
387
|
+
|
388
|
+
print(f"check_auth")
|
389
|
+
print(safely_transfer_obj_to_json_str(await client.check_auth()))
|
390
|
+
|
391
|
+
print(f"get_weather_in_ufa")
|
392
|
+
print(safely_transfer_obj_to_json_str((await client.get_weather_in_ufa()).model_dump()))
|
393
|
+
|
394
|
+
print(f"get_current_week")
|
395
|
+
print(safely_transfer_obj_to_json_str((await client.get_current_week()).model_dump()))
|
396
|
+
|
397
|
+
print(f"get_current_semester")
|
398
|
+
print(safely_transfer_obj_to_json_str((await client.get_current_semester()).model_dump()))
|
399
|
+
|
400
|
+
# Group
|
401
|
+
print(f"get_groups")
|
402
|
+
print(safely_transfer_obj_to_json_str((await client.get_groups())))
|
403
|
+
|
404
|
+
print(f"get_group")
|
405
|
+
if await client.get_group(filter_id=25285, filter_uust_api_id=6674):
|
406
|
+
print(safely_transfer_obj_to_json_str(
|
407
|
+
(await client.get_group(filter_id=25285, filter_uust_api_id=6674)).model_dump()))
|
408
|
+
else:
|
409
|
+
print("Group is none")
|
410
|
+
|
411
|
+
print(f"find_groups")
|
412
|
+
print(safely_transfer_obj_to_json_str((await client.find_groups(q="ПИ-427Б"))))
|
413
|
+
|
414
|
+
# Teacher
|
415
|
+
print(f"get_teachers")
|
416
|
+
print(safely_transfer_obj_to_json_str((await client.get_teachers())))
|
417
|
+
|
418
|
+
print(f"get_teacher")
|
419
|
+
if await client.get_teacher(filter_id=16975, filter_uust_api_id=112978):
|
420
|
+
print(safely_transfer_obj_to_json_str(
|
421
|
+
(await client.get_teacher(filter_id=16975, filter_uust_api_id=112978)).model_dump()))
|
422
|
+
else:
|
423
|
+
print("Teacher is none")
|
424
|
+
|
425
|
+
print(f"find_teachers")
|
426
|
+
print(safely_transfer_obj_to_json_str((await client.find_teachers(q="Казанцев"))))
|
427
|
+
|
428
|
+
# Group Lesson
|
429
|
+
print(f"get_group_lessons")
|
430
|
+
if await client.get_group_lessons(filter_group_id=25285, filter_group_uust_api_id=6674):
|
431
|
+
print(safely_transfer_obj_to_json_str((await client.get_group_lessons(filter_group_id=25285,
|
432
|
+
filter_group_uust_api_id=6674))))
|
433
|
+
else:
|
434
|
+
print("Group lessons is none")
|
435
|
+
|
436
|
+
# Teacher Lesson
|
437
|
+
print(f"get_teacher_lessons")
|
438
|
+
if await client.get_teacher_lessons(filter_teacher_id=16975, filter_teacher_uust_api_id=112978):
|
439
|
+
print(safely_transfer_obj_to_json_str((await client.get_teacher_lessons(filter_teacher_id=16975,
|
440
|
+
filter_teacher_uust_api_id=112978))))
|
441
|
+
else:
|
442
|
+
print("Teacher lessons is none")
|
443
|
+
|
444
|
+
# Find Any
|
445
|
+
print(f"find_any")
|
446
|
+
print(safely_transfer_obj_to_json_str((await client.find_any(q="ПИ"))))
|
546
447
|
|
547
448
|
|
548
449
|
if __name__ == '__main__':
|
arpakitlib/ar_fastapi_util.py
CHANGED
@@ -282,7 +282,8 @@ def create_handle_exception(
|
|
282
282
|
def create_story_log_before_response_in_handle_exception(
|
283
283
|
*,
|
284
284
|
sqlalchemy_db: SQLAlchemyDB,
|
285
|
-
|
285
|
+
ignore_api_error_codes: list[str] | None = None,
|
286
|
+
ignore_status_codes: list[int] | None = None
|
286
287
|
) -> Callable:
|
287
288
|
def func(
|
288
289
|
*,
|
@@ -292,8 +293,12 @@ def create_story_log_before_response_in_handle_exception(
|
|
292
293
|
exception: Exception,
|
293
294
|
**kwargs
|
294
295
|
) -> (int, ErrorSO, dict[str, Any]):
|
295
|
-
if
|
296
|
+
if ignore_api_error_codes and error_so.error_code in ignore_api_error_codes:
|
296
297
|
return status_code, error_so, kwargs
|
298
|
+
|
299
|
+
if ignore_status_codes and status_code in ignore_status_codes:
|
300
|
+
return status_code, error_so, kwargs
|
301
|
+
|
297
302
|
sqlalchemy_db.init()
|
298
303
|
traceback_str = "".join(traceback.format_exception(type(exception), exception, exception.__traceback__))
|
299
304
|
with sqlalchemy_db.new_session() as session:
|
@@ -391,7 +396,10 @@ def add_needed_api_router_to_app(*, app: FastAPI):
|
|
391
396
|
async def _():
|
392
397
|
return APIJSONResponse(
|
393
398
|
status_code=starlette.status.HTTP_200_OK,
|
394
|
-
content=RawDataSO(data={
|
399
|
+
content=RawDataSO(data={
|
400
|
+
"healthcheck": "healthcheck",
|
401
|
+
"is_ok": True
|
402
|
+
})
|
395
403
|
)
|
396
404
|
|
397
405
|
@api_router.get(
|
@@ -449,8 +457,8 @@ class BaseAPIAuthData(BaseModel):
|
|
449
457
|
token_string: str | None = None
|
450
458
|
api_key_string: str | None = None
|
451
459
|
|
452
|
-
|
453
|
-
|
460
|
+
is_token_correct: bool | None = None
|
461
|
+
is_api_key_correct: bool | None = None
|
454
462
|
|
455
463
|
|
456
464
|
def base_api_auth(
|
@@ -580,7 +588,7 @@ def base_api_auth(
|
|
580
588
|
)
|
581
589
|
if is_async_object(validate_api_key_func_data):
|
582
590
|
validate_api_key_func_data = await validate_api_key_func_data
|
583
|
-
api_auth_data.
|
591
|
+
api_auth_data.is_api_key_correct = validate_api_key_func_data
|
584
592
|
|
585
593
|
# token
|
586
594
|
|
@@ -595,25 +603,27 @@ def base_api_auth(
|
|
595
603
|
)
|
596
604
|
if is_async_object(validate_token_func_data):
|
597
605
|
validate_token_func_data_data = await validate_token_func_data
|
598
|
-
api_auth_data.
|
606
|
+
api_auth_data.is_token_correct = validate_token_func_data_data
|
599
607
|
|
600
608
|
# api_key
|
601
609
|
|
602
610
|
if require_correct_api_key:
|
603
|
-
if not api_auth_data.
|
611
|
+
if not api_auth_data.is_api_key_correct:
|
604
612
|
raise APIException(
|
605
613
|
status_code=starlette.status.HTTP_401_UNAUTHORIZED,
|
606
614
|
error_code=BaseAPIErrorCodes.cannot_authorize,
|
607
|
-
|
615
|
+
error_description="not api_auth_data.is_api_key_correct",
|
616
|
+
error_data=safely_transfer_obj_to_json_str_to_json_obj(api_auth_data.model_dump()),
|
608
617
|
)
|
609
618
|
|
610
619
|
# token
|
611
620
|
|
612
621
|
if require_correct_token:
|
613
|
-
if not api_auth_data.
|
622
|
+
if not api_auth_data.is_token_correct:
|
614
623
|
raise APIException(
|
615
624
|
status_code=starlette.status.HTTP_401_UNAUTHORIZED,
|
616
625
|
error_code=BaseAPIErrorCodes.cannot_authorize,
|
626
|
+
error_description="not api_auth_data.is_token_correct",
|
617
627
|
error_data=safely_transfer_obj_to_json_str_to_json_obj(api_auth_data.model_dump())
|
618
628
|
)
|
619
629
|
|
@@ -26,6 +26,7 @@ def sync_make_http_request(
|
|
26
26
|
max_tries_: int = 9,
|
27
27
|
proxy_url_: str | None = None,
|
28
28
|
raise_for_status_: bool = False,
|
29
|
+
not_raise_for_statuses: list[int] | None = None,
|
29
30
|
timeout_: timedelta | float = timedelta(seconds=15).total_seconds(),
|
30
31
|
enable_logging_: bool = False,
|
31
32
|
**kwargs
|
@@ -53,21 +54,25 @@ def sync_make_http_request(
|
|
53
54
|
kwargs["allow_redirects"] = True
|
54
55
|
|
55
56
|
if enable_logging_:
|
56
|
-
_logger.info(f"
|
57
|
+
_logger.info(f"try http {method} {url} {params}")
|
57
58
|
|
58
59
|
while True:
|
59
60
|
tries_counter += 1
|
60
61
|
try:
|
61
62
|
response = requests.request(**kwargs)
|
62
63
|
if raise_for_status_:
|
63
|
-
response.
|
64
|
+
if not_raise_for_statuses and response.status_code in not_raise_for_statuses:
|
65
|
+
if enable_logging_:
|
66
|
+
_logger.info(f"ignored status {response.status_code} for http {method} {url} {params}")
|
67
|
+
else:
|
68
|
+
response.raise_for_status()
|
64
69
|
if enable_logging_:
|
65
|
-
_logger.info(f"
|
70
|
+
_logger.info(f"good try http {method} {url} {params}")
|
66
71
|
return response
|
67
72
|
except BaseException as exception:
|
68
73
|
if enable_logging_:
|
69
74
|
_logger.warning(
|
70
|
-
f"{tries_counter}/{max_tries_}.
|
75
|
+
f"{tries_counter}/{max_tries_}. retry {method} {url} {params}, exception={exception}"
|
71
76
|
)
|
72
77
|
if tries_counter >= max_tries_:
|
73
78
|
raise exception
|
@@ -84,6 +89,7 @@ async def async_make_http_request(
|
|
84
89
|
max_tries_: int = 9,
|
85
90
|
proxy_url_: str | None = None,
|
86
91
|
raise_for_status_: bool = False,
|
92
|
+
not_raise_for_statuses: list[int] | None = None,
|
87
93
|
timeout_: timedelta | None = timedelta(seconds=15),
|
88
94
|
enable_logging_: bool = False,
|
89
95
|
**kwargs
|
@@ -106,7 +112,7 @@ async def async_make_http_request(
|
|
106
112
|
proxy_connector = ProxyConnector.from_url(proxy_url_)
|
107
113
|
|
108
114
|
if enable_logging_:
|
109
|
-
_logger.info(f"
|
115
|
+
_logger.info(f"try http {method} {url} {params}")
|
110
116
|
|
111
117
|
while True:
|
112
118
|
tries_counter += 1
|
@@ -114,15 +120,21 @@ async def async_make_http_request(
|
|
114
120
|
async with aiohttp.ClientSession(connector=proxy_connector) as session:
|
115
121
|
async with session.request(**kwargs) as response:
|
116
122
|
if raise_for_status_:
|
117
|
-
response.
|
123
|
+
if not_raise_for_statuses and response.status in not_raise_for_statuses:
|
124
|
+
if enable_logging_:
|
125
|
+
_logger.info(
|
126
|
+
f"ignored status {response.status} for http {method} {url} {params}"
|
127
|
+
)
|
128
|
+
else:
|
129
|
+
response.raise_for_status()
|
118
130
|
await response.read()
|
119
131
|
if enable_logging_:
|
120
|
-
_logger.info(f"
|
132
|
+
_logger.info(f"good try http {method} {url} {params}")
|
121
133
|
return response
|
122
134
|
except BaseException as exception:
|
123
135
|
if enable_logging_:
|
124
136
|
_logger.warning(
|
125
|
-
f"{tries_counter}/{max_tries_}.
|
137
|
+
f"{tries_counter}/{max_tries_}. retry http {method} {url} {params}, exception={exception}"
|
126
138
|
)
|
127
139
|
if tries_counter >= max_tries_:
|
128
140
|
raise exception
|
@@ -77,7 +77,8 @@ class ScheduleUUSTAPIClient:
|
|
77
77
|
*,
|
78
78
|
method: str = "GET",
|
79
79
|
url: str,
|
80
|
-
params: dict[str, Any] | None = None
|
80
|
+
params: dict[str, Any] | None = None,
|
81
|
+
**kwargs
|
81
82
|
) -> ClientResponse:
|
82
83
|
response = await async_make_http_request(
|
83
84
|
method=method,
|
@@ -85,7 +86,8 @@ class ScheduleUUSTAPIClient:
|
|
85
86
|
headers=self.headers,
|
86
87
|
params=combine_dicts(params, self.auth_params()),
|
87
88
|
proxy_url_=self.api_proxy_url,
|
88
|
-
raise_for_status_=True
|
89
|
+
raise_for_status_=True,
|
90
|
+
**kwargs
|
89
91
|
)
|
90
92
|
json_data = await response.json()
|
91
93
|
if "error" in json_data.keys():
|
@@ -120,7 +120,7 @@ arpakitlib/ar_aiogram_util.py,sha256=5JPCDZpdBGTE-EIWPRez9amCZAX7XemFIVu5YrQK7Pw
|
|
120
120
|
arpakitlib/ar_api_key_util.py,sha256=E84JlJXiDHtxLQmV8BNHvqNKu_G8-Dox0XxknYJQ37Q,422
|
121
121
|
arpakitlib/ar_arpakit_lib_module_util.py,sha256=UEPU8wk29R_bBP_RENnhXYzNbj_RF9FWjowrj_yxWLA,5931
|
122
122
|
arpakitlib/ar_arpakit_project_template_util.py,sha256=c7yc8w2IvZGH5hH8eOpL7JuD005hUxZ0GVDcSkJF5iI,3705
|
123
|
-
arpakitlib/ar_arpakit_schedule_uust_api_client_util.py,sha256=
|
123
|
+
arpakitlib/ar_arpakit_schedule_uust_api_client_util.py,sha256=006JstWvs6JTuxRCg3toSNQvtKO0KM5pqyPJa1PRDNA,14998
|
124
124
|
arpakitlib/ar_arpakitlib_cli_util.py,sha256=8lhEDxnwMSRX2PGV2xQtQru1AYKSA92SVolol5u7iBk,3154
|
125
125
|
arpakitlib/ar_base64_util.py,sha256=aZkg2cZTuAaP2IWeG_LXJ6RO7qhyskVwec-Lks0iM-k,676
|
126
126
|
arpakitlib/ar_base_worker_util.py,sha256=Qm_C7PFH5W-LPu1AGX1zp29zbqZ04i71Su1U-eeQBkA,5674
|
@@ -152,12 +152,12 @@ arpakitlib/ar_fastapi_static/swagger-ui/swagger-ui.css,sha256=jzPZlgJTFwSdSphk9C
|
|
152
152
|
arpakitlib/ar_fastapi_static/swagger-ui/swagger-ui.css.map,sha256=5wq8eXMLU6Zxb45orZPL1zAsBFJReFw6GjYqGpUX3hg,262650
|
153
153
|
arpakitlib/ar_fastapi_static/swagger-ui/swagger-ui.js,sha256=ffrLZHHEQ_g84A-ul3yWa10Kk09waOAxHcQXPuZuavg,339292
|
154
154
|
arpakitlib/ar_fastapi_static/swagger-ui/swagger-ui.js.map,sha256=9UhIW7MqCOZPAz1Sl1IKfZUuhWU0p-LJqrnjjJD9Xhc,1159454
|
155
|
-
arpakitlib/ar_fastapi_util.py,sha256=
|
155
|
+
arpakitlib/ar_fastapi_util.py,sha256=Otm6sa-xB3qUZ7ttp0A52FVEaBN3yRHQx2JKWKYDEGg,26567
|
156
156
|
arpakitlib/ar_file_storage_in_dir_util.py,sha256=D3e3rGuHoI6xqAA5mVvEpVVpOWY1jyjNsjj2UhyHRbE,3674
|
157
157
|
arpakitlib/ar_file_util.py,sha256=GUdJYm1tUZnYpY-SIPRHAZBHGra8NKy1eYEI0D5AfhY,489
|
158
158
|
arpakitlib/ar_func_util.py,sha256=bCuWbSMoFXBaMNhb89sevj2oaXRk4Jk6Qjot8OXMDT4,1319
|
159
159
|
arpakitlib/ar_hash_util.py,sha256=Iqy6KBAOLBQMFLWv676boI5sV7atT2B-fb7aCdHOmIQ,340
|
160
|
-
arpakitlib/ar_http_request_util.py,sha256=
|
160
|
+
arpakitlib/ar_http_request_util.py,sha256=tvYtLiTGxJ0tsoQm4SqBsPmlUn2X0qQPDeetVEIZ7Lk,5078
|
161
161
|
arpakitlib/ar_ip_util.py,sha256=aEAa1Hvobh9DWX7cmBAPLqnXSTiKe2hRk-WJaiKMaI8,1009
|
162
162
|
arpakitlib/ar_json_db_util.py,sha256=CEyhIU4WuNmX5mqwBVYxUKSdpFelXvWmf_tJ1fuxMSE,7187
|
163
163
|
arpakitlib/ar_json_util.py,sha256=wJOsN8N7Rs7r8cTgMDXrmFa1GOkcD-LghqFEYXc8zGA,1083
|
@@ -172,7 +172,7 @@ arpakitlib/ar_operation_execution_util.py,sha256=uWLDJWYbfsYItUQ48qOSWy4qxCTCFMj
|
|
172
172
|
arpakitlib/ar_parse_command.py,sha256=-s61xcATIsfw1eV_iD3xi-grsitbGzSDoAFc5V0OFy4,3447
|
173
173
|
arpakitlib/ar_postgresql_util.py,sha256=1AuLjEaa1Lg4pzn-ukCVnDi35Eg1k91APRTqZhIJAdo,945
|
174
174
|
arpakitlib/ar_run_cmd_util.py,sha256=D_rPavKMmWkQtwvZFz-Io5Ak8eSODHkcFeLPzNVC68g,1072
|
175
|
-
arpakitlib/ar_schedule_uust_api_client_util.py,sha256=
|
175
|
+
arpakitlib/ar_schedule_uust_api_client_util.py,sha256=93d-bc3S0PddqV65lSvmApcSoDV0gqxPVgIaB7zKXfY,6899
|
176
176
|
arpakitlib/ar_settings_util.py,sha256=rnoTqbRuhiq7294D4crD5kbnU8-gNWJbwGU_Ls2gJoU,2199
|
177
177
|
arpakitlib/ar_sleep_util.py,sha256=OaLtRaJQWMkGjfj_mW1RB2P4RaSWsAIH8LUoXqsH0zM,1061
|
178
178
|
arpakitlib/ar_sqladmin_util.py,sha256=6Nv9VQssk9PB0piyuss__soYKdjVhdbIeXIv4AgUxmQ,2660
|
@@ -183,8 +183,8 @@ arpakitlib/ar_str_util.py,sha256=yU5gOwNXUQaH5b_tM5t6fXUn9oUcv5EQbVnq2wXXIpQ,337
|
|
183
183
|
arpakitlib/ar_type_util.py,sha256=9C3ErtUVs0tAUqtK-foFzjJOykfBOntfCz2IogDOgfA,4134
|
184
184
|
arpakitlib/ar_yookassa_api_client_util.py,sha256=sh4fcUkAkdOetFn9JYoTvjcSXP-M1wU04KEY-ECLfLg,5137
|
185
185
|
arpakitlib/ar_zabbix_api_client_util.py,sha256=Q-VR4MvoZ9aHwZeYZr9G3LwN-ANx1T5KFmF6pvPM-9M,6402
|
186
|
-
arpakitlib-1.7.
|
187
|
-
arpakitlib-1.7.
|
188
|
-
arpakitlib-1.7.
|
189
|
-
arpakitlib-1.7.
|
190
|
-
arpakitlib-1.7.
|
186
|
+
arpakitlib-1.7.216.dist-info/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
|
187
|
+
arpakitlib-1.7.216.dist-info/METADATA,sha256=Pm0yzZbxaZf_Iu4ROSrnQVVa4RbswNleQQC4PoIU9b0,3176
|
188
|
+
arpakitlib-1.7.216.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
189
|
+
arpakitlib-1.7.216.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
|
190
|
+
arpakitlib-1.7.216.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|