arpakitlib 1.8.307__py3-none-any.whl → 1.8.322__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.

Potentially problematic release.


This version of arpakitlib might be problematic. Click here for more details.

@@ -1,422 +0,0 @@
1
- # arpakit
2
-
3
- from __future__ import annotations
4
-
5
- import asyncio
6
- import datetime as dt
7
- import logging
8
- from typing import Any
9
- from urllib.parse import urljoin
10
-
11
- import cachetools
12
- from aiohttp import ClientResponse
13
- from pydantic import ConfigDict, BaseModel
14
-
15
- from arpakitlib.ar_enumeration_util import Enumeration
16
- from arpakitlib.ar_http_request_util import async_make_http_request
17
-
18
- _ARPAKIT_LIB_MODULE_VERSION = "3.0"
19
-
20
-
21
- class Weekdays(Enumeration):
22
- monday = 1
23
- tuesday = 2
24
- wednesday = 3
25
- thursday = 4
26
- friday = 5
27
- saturday = 6
28
- sunday = 7
29
-
30
-
31
- class Months(Enumeration):
32
- january = 1
33
- february = 2
34
- march = 3
35
- april = 4
36
- may = 5
37
- june = 6
38
- july = 7
39
- august = 8
40
- september = 9
41
- october = 10
42
- november = 11
43
- december = 12
44
-
45
-
46
- class BaseAPIModel(BaseModel):
47
- model_config = ConfigDict(extra="ignore", arbitrary_types_allowed=True, from_attributes=True)
48
-
49
-
50
- class CurrentSemesterAPIModel(BaseAPIModel):
51
- id: int
52
- long_id: str
53
- creation_dt: dt.datetime
54
- entity_type: str
55
- actualization_dt: dt.datetime
56
- value: str
57
-
58
-
59
- class CurrentWeekAPIModel(BaseAPIModel):
60
- id: int
61
- long_id: str
62
- creation_dt: dt.datetime
63
- entity_type: str
64
- actualization_dt: dt.datetime
65
- value: int
66
-
67
-
68
- class GroupAPIModel(BaseAPIModel):
69
- id: int
70
- long_id: str
71
- creation_dt: dt.datetime
72
- entity_type: str
73
- actualization_dt: dt.datetime
74
- uust_api_id: int
75
- title: str
76
- faculty: str | None
77
- course: int | None
78
- difference_level: int | None = None
79
- uust_api_data: dict[str, Any]
80
-
81
-
82
- class TeacherAPIModel(BaseAPIModel):
83
- id: int
84
- long_id: str
85
- creation_dt: dt.datetime
86
- entity_type: str
87
- actualization_dt: dt.datetime
88
- uust_api_id: int
89
- name: str | None
90
- surname: str | None
91
- patronymic: str | None
92
- fullname: str | None
93
- shortname: str | None
94
- posts: list[str]
95
- post: str | None
96
- units: list[str]
97
- unit: str | None
98
- difference_level: int | None
99
- uust_api_data: dict[str, Any]
100
-
101
-
102
- class GroupLessonAPIModel(BaseAPIModel):
103
- id: int
104
- long_id: str
105
- creation_dt: dt.datetime
106
- entity_type: str
107
- actualization_dt: dt.datetime
108
- uust_api_id: int
109
- type: str
110
- title: str
111
- weeks: list[int]
112
- weekday: int
113
- comment: str | None
114
- time_title: str | None
115
- time_start: dt.time | None
116
- time_end: dt.time | None
117
- numbers: list[int]
118
- location: str | None
119
- teacher_uust_api_id: int | None
120
- group_uust_api_id: int | None
121
- group: GroupAPIModel
122
- teacher: TeacherAPIModel | None
123
- uust_api_data: dict[str, Any]
124
-
125
- def compare_type(self, *types: str | list[str]) -> bool:
126
- type_ = self.type.strip().lower()
127
- for type__ in types:
128
- if isinstance(type__, str):
129
- if type_ == type__.strip().lower():
130
- return True
131
- elif isinstance(type__, list):
132
- for type___ in type__:
133
- if type_ == type___.strip().lower():
134
- return True
135
- else:
136
- raise TypeError()
137
- return False
138
-
139
-
140
- class TeacherLessonAPIModel(BaseAPIModel):
141
- id: int
142
- long_id: str
143
- creation_dt: dt.datetime
144
- entity_type: str
145
- actualization_dt: dt.datetime
146
- uust_api_id: int
147
- type: str
148
- title: str
149
- weeks: list[int]
150
- weekday: int
151
- comment: str | None
152
- time_title: str | None
153
- time_start: dt.time | None
154
- time_end: dt.time | None
155
- numbers: list[int]
156
- location: str | None
157
- group_uust_api_ids: list[int]
158
- teacher_uust_api_id: int
159
- teacher: TeacherAPIModel
160
- groups: list[GroupAPIModel]
161
- uust_api_data: dict[str, Any]
162
-
163
- def compare_type(self, *types: str | list[str]) -> bool:
164
- type_ = self.type.strip().lower()
165
- for type__ in types:
166
- if isinstance(type__, str):
167
- if type_ == type__.strip().lower():
168
- return True
169
- elif isinstance(type__, list):
170
- for type___ in type__:
171
- if type_ == type___.strip().lower():
172
- return True
173
- else:
174
- raise TypeError()
175
- return False
176
-
177
-
178
- class WeatherInUfaAPIModel(BaseAPIModel):
179
- temperature: float
180
- temperature_feels_like: float
181
- description: str
182
- wind_speed: float
183
- sunrise_dt: dt.datetime
184
- sunset_dt: dt.datetime
185
- has_rain: bool
186
- has_snow: bool
187
- data: dict
188
-
189
-
190
- class DatetimeAPIModel(BaseAPIModel):
191
- date: dt.date
192
- datetime: dt.datetime | None = None
193
- year: int
194
- month: int
195
- day: int
196
- hour: int | None = None
197
- minute: int | None = None
198
- second: int | None = None
199
- microsecond: int | None = None
200
-
201
-
202
- class ARPAKITScheduleUUSTAPIClient:
203
- def __init__(
204
- self,
205
- *,
206
- base_url: str = "https://api.schedule-uust.arpakit.com/api/v1",
207
- api_key: str | None = "viewer",
208
- use_cache: bool = False,
209
- cache_ttl: dt.timedelta | None = dt.timedelta(minutes=10)
210
- ):
211
- self._logger = logging.getLogger(__name__)
212
- self.api_key = api_key
213
- base_url = base_url.strip()
214
- if not base_url.endswith("/"):
215
- base_url += "/"
216
- self.base_url = base_url
217
- self.headers = {"Content-Type": "application/json"}
218
- if api_key is not None:
219
- self.headers.update({"apikey": self.api_key})
220
- self.use_cache = use_cache
221
- self.cache_ttl = cache_ttl
222
- if cache_ttl is not None:
223
- self.ttl_cache = cachetools.TTLCache(maxsize=100, ttl=cache_ttl.total_seconds())
224
- else:
225
- self.ttl_cache = None
226
-
227
- async def _async_make_http_request(
228
- self,
229
- *,
230
- method: str = "GET",
231
- url: str,
232
- params: dict[str, Any] | None = None,
233
- **kwargs
234
- ) -> ClientResponse:
235
- response = await async_make_http_request(
236
- method=method,
237
- url=url,
238
- headers=self.headers,
239
- params=params,
240
- max_tries_=5,
241
- raise_for_status_=True,
242
- **kwargs
243
- )
244
- return response
245
-
246
- def clear_cache(self):
247
- if self.ttl_cache is not None:
248
- self.ttl_cache.clear()
249
-
250
- async def check_auth(self) -> dict[str, Any]:
251
- response = await self._async_make_http_request(
252
- method="GET", url=urljoin(self.base_url, "check_auth")
253
- )
254
- json_data = await response.json()
255
- return json_data
256
-
257
- async def get_current_week(self) -> CurrentWeekAPIModel | None:
258
- response = await self._async_make_http_request(
259
- method="GET", url=urljoin(self.base_url, "get_current_week")
260
- )
261
- json_data = await response.json()
262
- if json_data is None:
263
- return None
264
- return CurrentWeekAPIModel.model_validate(json_data)
265
-
266
- async def get_current_semester(self) -> CurrentSemesterAPIModel | None:
267
- response = await self._async_make_http_request(
268
- method="GET", url=urljoin(self.base_url, "get_current_semester")
269
- )
270
- json_data = await response.json()
271
- if json_data is None:
272
- return None
273
- return CurrentSemesterAPIModel.model_validate(json_data)
274
-
275
- async def get_weather_in_ufa(self) -> WeatherInUfaAPIModel:
276
- response = await self._async_make_http_request(
277
- method="GET", url=urljoin(self.base_url, "get_weather_in_ufa")
278
- )
279
- json_data = await response.json()
280
- return WeatherInUfaAPIModel.model_validate(json_data)
281
-
282
- async def get_now_datetime_in_ufa(self) -> DatetimeAPIModel:
283
- response = await self._async_make_http_request(
284
- method="GET", url=urljoin(self.base_url, "get_now_datetime_in_ufa")
285
- )
286
- json_data = await response.json()
287
- return DatetimeAPIModel.model_validate(json_data)
288
-
289
- async def get_log_file_content(self) -> str | None:
290
- response = await self._async_make_http_request(
291
- method="GET", url=urljoin(self.base_url, "get_log_file")
292
- )
293
- text_data = await response.text()
294
- return text_data
295
-
296
- async def get_groups(self) -> list[GroupAPIModel]:
297
- response = await self._async_make_http_request(
298
- method="GET", url=urljoin(self.base_url, "get_groups")
299
- )
300
- json_data = await response.json()
301
- return [GroupAPIModel.model_validate(d) for d in json_data]
302
-
303
- async def get_group(
304
- self, *, filter_id: int | None = None, filter_uust_api_id: int | None = None
305
- ) -> GroupAPIModel | None:
306
- params = {}
307
- if filter_id is not None:
308
- params["filter_id"] = filter_id
309
- if filter_uust_api_id is not None:
310
- params["filter_uust_api_id"] = filter_uust_api_id
311
- response = await self._async_make_http_request(
312
- method="GET", url=urljoin(self.base_url, "get_group"), params=params)
313
- json_data = await response.json()
314
- if json_data is None:
315
- return None
316
- return GroupAPIModel.model_validate(json_data)
317
-
318
- async def find_groups(
319
- self, *, q: str
320
- ) -> list[GroupAPIModel]:
321
- response = await self._async_make_http_request(
322
- method="GET", url=urljoin(self.base_url, "find_groups"), params={"q": q.strip()}
323
- )
324
- json_data = await response.json()
325
- return [GroupAPIModel.model_validate(d) for d in json_data]
326
-
327
- async def get_teachers(self) -> list[TeacherAPIModel]:
328
- response = await self._async_make_http_request(
329
- method="GET", url=urljoin(self.base_url, "get_teachers")
330
- )
331
- json_data = await response.json()
332
- return [TeacherAPIModel.model_validate(d) for d in json_data]
333
-
334
- async def get_teacher(
335
- self, *, filter_id: int | None = None, filter_uust_api_id: int | None = None
336
- ) -> TeacherAPIModel | None:
337
- params = {}
338
- if filter_id is not None:
339
- params["filter_id"] = filter_id
340
- if filter_uust_api_id is not None:
341
- params["filter_uust_api_id"] = filter_uust_api_id
342
- response = await self._async_make_http_request(
343
- method="GET", url=urljoin(self.base_url, "get_teacher"), params=params
344
- )
345
- json_data = await response.json()
346
- if json_data is None:
347
- return None
348
- return TeacherAPIModel.model_validate(json_data)
349
-
350
- async def find_teachers(
351
- self, *, q: str
352
- ) -> list[TeacherAPIModel]:
353
- response = await self._async_make_http_request(
354
- method="GET", url=urljoin(self.base_url, "find_teachers"), params={"q": q.strip()}
355
- )
356
- json_data = await response.json()
357
- return [TeacherAPIModel.model_validate(d) for d in json_data]
358
-
359
- async def find_any(
360
- self, *, q: str
361
- ) -> list[TeacherAPIModel | GroupLessonAPIModel]:
362
- response = await self._async_make_http_request(
363
- method="GET", url=urljoin(self.base_url, "find_any"), params={"q": q.strip()}
364
- )
365
- json_data = await response.json()
366
-
367
- results = []
368
- for d in json_data:
369
- if d["entity_type"] == "group":
370
- results.append(GroupAPIModel.model_validate(d))
371
- elif d["entity_type"] == "teacher":
372
- results.append(TeacherAPIModel.model_validate(d))
373
- else:
374
- pass
375
- return results
376
-
377
- async def get_group_lessons(
378
- self,
379
- *,
380
- filter_group_id: int | None = None,
381
- filter_group_uust_api_id: int | None = None
382
- ) -> list[GroupLessonAPIModel]:
383
- params = {}
384
- if filter_group_id is not None:
385
- params["filter_group_id"] = filter_group_id
386
- if filter_group_uust_api_id is not None:
387
- params["filter_group_uust_api_id"] = filter_group_uust_api_id
388
- response = await self._async_make_http_request(
389
- method="GET", url=urljoin(self.base_url, "get_group_lessons"), params=params
390
- )
391
- json_data = await response.json()
392
- return [GroupLessonAPIModel.model_validate(d) for d in json_data]
393
-
394
- async def get_teacher_lessons(
395
- self,
396
- *,
397
- filter_teacher_id: int | None = None,
398
- filter_teacher_uust_api_id: int | None = None
399
- ) -> list[TeacherLessonAPIModel]:
400
- params = {}
401
- if filter_teacher_id is not None:
402
- params["filter_teacher_id"] = filter_teacher_id
403
- if filter_teacher_uust_api_id is not None:
404
- params["filter_teacher_uust_api_id"] = filter_teacher_uust_api_id
405
- response = await self._async_make_http_request(
406
- method="GET", url=urljoin(self.base_url, "get_teacher_lessons"), params=params
407
- )
408
- json_data = await response.json()
409
- return [TeacherLessonAPIModel.model_validate(d) for d in json_data]
410
-
411
-
412
- def __example():
413
- pass
414
-
415
-
416
- async def __async_example():
417
- pass
418
-
419
-
420
- if __name__ == '__main__':
421
- __example()
422
- asyncio.run(__async_example())
@@ -1,68 +0,0 @@
1
- # arpakit
2
-
3
- from urllib.parse import urlencode, urljoin
4
-
5
- from arpakitlib.ar_type_util import raise_for_type
6
-
7
- _ARPAKIT_LIB_MODULE_VERSION = "3.0"
8
-
9
-
10
- def generate_arpakit_schedule_uust_site_url(
11
- *,
12
- base_url: str = "https://schedule-uust.arpakit.com",
13
- entity_type: str | None = None,
14
- uust_api_id: int | None = None,
15
- session: bool | None = None,
16
- week: int | None = None,
17
- theme: str | None = None
18
- ) -> str:
19
- raise_for_type(base_url, str)
20
-
21
- params = {}
22
-
23
- if entity_type is not None: # group/teacher
24
- raise_for_type(entity_type, str)
25
- params["entity_type"] = entity_type
26
-
27
- if uust_api_id is not None: # uust_api_id of group/teacher
28
- raise_for_type(uust_api_id, int)
29
- params["uust_api_id"] = uust_api_id
30
-
31
- if session is not None: # true/false
32
- raise_for_type(session, bool)
33
- if session:
34
- params["session"] = "true"
35
- else:
36
- params["session"] = "false"
37
-
38
- if week is not None:
39
- raise_for_type(week, int)
40
- params["week"] = week
41
-
42
- if theme is not None: # dark/light
43
- raise_for_type(theme, str)
44
- params["theme"] = theme
45
-
46
- if params:
47
- res = urljoin(base_url, f"schedule?{urlencode(params)}")
48
- else:
49
- res = base_url
50
-
51
- return res
52
-
53
-
54
- def __example():
55
- base_url = "https://schedule-uust.arpakit.com"
56
- url = generate_arpakit_schedule_uust_site_url(
57
- base_url=base_url,
58
- entity_type="group",
59
- uust_api_id=6662,
60
- session=True,
61
- week=23,
62
- theme="dark"
63
- )
64
- print(url)
65
-
66
-
67
- if __name__ == '__main__':
68
- __example()
@@ -1,71 +0,0 @@
1
- from urllib.parse import quote_plus
2
-
3
- _ARPAKIT_LIB_MODULE_VERSION = "3.0"
4
-
5
-
6
- def generate_celery_url(
7
- *,
8
- scheme: str = "redis", # или amqp, sqs, etc.
9
- user: str | None = None,
10
- password: str | None = None,
11
- host: str = "127.0.0.1",
12
- port: int | None = 6379,
13
- database: str | int | None = 0, # для Redis — номер БД; для AMQP — vhost
14
- **query_params
15
- ) -> str:
16
- """
17
- Генерирует Celery broker/backend URL.
18
-
19
- Примеры:
20
- redis://:mypassword@redis:6379/0
21
- amqp://user:pass@rabbit:5672/myvhost
22
- redis://localhost:6379/1?ssl_cert_reqs=none
23
- """
24
- # Формируем часть авторизации
25
- auth_part = ""
26
- if user and password:
27
- auth_part = f"{quote_plus(user)}:{quote_plus(password)}@"
28
- elif password and not user:
29
- # Redis-style — пароль без юзера
30
- auth_part = f":{quote_plus(password)}@"
31
- elif user:
32
- auth_part = f"{quote_plus(user)}@"
33
-
34
- # Формируем хост и порт
35
- host_part = host
36
- if port:
37
- host_part += f":{port}"
38
-
39
- # Формируем "базу" (для Redis — номер, для AMQP — vhost)
40
- db_part = ""
41
- if database is not None:
42
- db_part = f"/{quote_plus(str(database))}"
43
-
44
- # Формируем query параметры
45
- query_part = ""
46
- if query_params:
47
- query_items = [f"{key}={quote_plus(str(value))}" for key, value in query_params.items()]
48
- query_part = f"?{'&'.join(query_items)}"
49
-
50
- return f"{scheme}://{auth_part}{host_part}{db_part}{query_part}"
51
-
52
-
53
- def __example():
54
- print(generate_celery_url())
55
- # → redis://127.0.0.1:6379/0
56
-
57
- # Redis с паролем
58
- print(generate_celery_url(password="supersecret", host="redis"))
59
- # → redis://:supersecret@redis:6379/0
60
-
61
- # RabbitMQ (AMQP)
62
- print(generate_celery_url(scheme="amqp", user="guest", password="guest", host="rabbitmq"))
63
- # → amqp://guest:guest@rabbitmq:6379/0
64
-
65
- # Redis с параметрами
66
- print(generate_celery_url(password="pass", ssl_cert_reqs="none", socket_timeout=10))
67
- # → redis://:pass@127.0.0.1:6379/0?ssl_cert_reqs=none&socket_timeout=10
68
-
69
-
70
- if __name__ == '__main__':
71
- __example()