arpakitlib 1.8.273__py3-none-any.whl → 1.8.275__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.
@@ -0,0 +1,71 @@
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()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arpakitlib
3
- Version: 1.8.273
3
+ Version: 1.8.275
4
4
  Summary: arpakitlib
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -399,6 +399,7 @@ arpakitlib/ar_exception_util.py,sha256=3hZKsj34TZVdmd4JAQz7w515smWqB8o3gTwAEjuMd
399
399
  arpakitlib/ar_file_storage_in_dir_util.py,sha256=Zh922S6-aIy0p_Fen8GTTrGpixpPQ6c-wFLukiSK4Ck,4091
400
400
  arpakitlib/ar_file_util.py,sha256=GUdJYm1tUZnYpY-SIPRHAZBHGra8NKy1eYEI0D5AfhY,489
401
401
  arpakitlib/ar_func_util.py,sha256=lG0bx_DtxWN4skbUim0liRZ6WUyLVV8Qfk6iZNtCZOs,1042
402
+ arpakitlib/ar_generate_celery_url.py,sha256=ddzOokXKZRGRDQu18amnW5ZaekcMihwsmyUn0FzpgVU,2274
402
403
  arpakitlib/ar_generate_simple_code.py,sha256=EkrebrTi7sArSRAuxvN5BPm_A0-dFSCZgdoJhx5kPhk,344
403
404
  arpakitlib/ar_hash_util.py,sha256=Iqy6KBAOLBQMFLWv676boI5sV7atT2B-fb7aCdHOmIQ,340
404
405
  arpakitlib/ar_http_request_util.py,sha256=PCUtGOQIvNScrLqD_9Z8LqT-7a-lP2y-Y-CH5vGdn7Q,7663
@@ -430,9 +431,8 @@ arpakitlib/ar_sqlalchemy_drop_check_constraints.py,sha256=XEqnMrIwSYasW_UOJ8xU-J
430
431
  arpakitlib/ar_sqlalchemy_util.py,sha256=nUDCxhu0l8P0eBCdLyXej3_yLvBlB3LrGhMWzAekm5E,16532
431
432
  arpakitlib/ar_str_util.py,sha256=2lGpnXDf2h1cBZpVf5i1tX_HCv5iBd6IGnrCw4QWWlY,4350
432
433
  arpakitlib/ar_type_util.py,sha256=Cs_tef-Fc5xeyAF54KgISCsP11NHyzIsglm4S3Xx7iM,4049
433
- arpakitlib/ar_yookassa_api_client_util.py,sha256=VozuZeCJjmLd1zj2BdC9WfiAQ3XYOrIMsdpNK-AUlm0,5347
434
- arpakitlib-1.8.273.dist-info/METADATA,sha256=qGtKkpT3h_WYVpYmX8G78QgYXjZlTaOEyApAGNO_VoU,3983
435
- arpakitlib-1.8.273.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
436
- arpakitlib-1.8.273.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
437
- arpakitlib-1.8.273.dist-info/licenses/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
438
- arpakitlib-1.8.273.dist-info/RECORD,,
434
+ arpakitlib-1.8.275.dist-info/METADATA,sha256=kVwmU3-XuutMHrTuEhuxs0Mw7Y29OF8nLX3m1ks8Xn0,3983
435
+ arpakitlib-1.8.275.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
436
+ arpakitlib-1.8.275.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
437
+ arpakitlib-1.8.275.dist-info/licenses/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
438
+ arpakitlib-1.8.275.dist-info/RECORD,,
@@ -1,189 +0,0 @@
1
- # arpakit
2
-
3
- from __future__ import annotations
4
-
5
- import asyncio
6
- import logging
7
- import uuid
8
- from datetime import timedelta
9
- from typing import Optional, Any
10
-
11
- import aiohttp
12
- import requests
13
-
14
- from arpakitlib.ar_dict_util import combine_dicts
15
- from arpakitlib.ar_enumeration_util import Enumeration
16
- from arpakitlib.ar_http_request_util import sync_make_http_request, async_make_http_request
17
- from arpakitlib.ar_type_util import raise_for_type
18
-
19
- _ARPAKIT_LIB_MODULE_VERSION = "3.0"
20
-
21
- """
22
- https://yookassa.ru/developers/api
23
- """
24
-
25
-
26
- class YookassaPaymentStatuses(Enumeration):
27
- pending = "pending"
28
- waiting_for_capture = "waiting_for_capture"
29
- succeeded = "succeeded"
30
- canceled = "canceled"
31
-
32
-
33
- class YookassaAPIException(Exception):
34
- pass
35
-
36
-
37
- class YookassaAPIClient:
38
- def __init__(self, *, secret_key: str, shop_id: int):
39
- super().__init__()
40
- self.secret_key = secret_key
41
- self.shop_id = shop_id
42
- self.headers = {"Content-Type": "application/json"}
43
- self.timeout_ = timedelta(seconds=3)
44
- self._logger = logging.getLogger(self.__class__.__name__)
45
-
46
- def _sync_make_http_request(
47
- self,
48
- *,
49
- method: str,
50
- url: str,
51
- headers: dict[str, Any] | None = None,
52
- **kwargs
53
- ) -> requests.Response:
54
- return sync_make_http_request(
55
- method=method,
56
- url=url,
57
- headers=combine_dicts(self.headers, (headers if headers is not None else {})),
58
- max_tries_=5,
59
- raise_for_status_=True,
60
- timeout_=self.timeout_,
61
- not_raise_for_statuses_=[404],
62
- auth=(self.shop_id, self.secret_key),
63
- **kwargs
64
- )
65
-
66
- def sync_create_payment(
67
- self,
68
- json_body: dict[str, Any]
69
- ) -> dict[str, Any]:
70
-
71
- """
72
- json_body example
73
- json_body = {
74
- "amount": {
75
- "value": "2.0",
76
- "currency": "RUB"
77
- },
78
- "description": "description",
79
- "confirmation": {
80
- "type": "redirect",
81
- "return_url": f"https://t.me/{get_tg_bot_username()}",
82
- "locale": "ru_RU"
83
- },
84
- "capture": True,
85
- "metadata": {},
86
- "merchant_customer_id": ""
87
- }
88
- """
89
-
90
- response = self._sync_make_http_request(
91
- method="POST",
92
- url="https://api.yookassa.ru/v3/payments",
93
- headers={"Idempotence-Key": str(uuid.uuid4())},
94
- json=json_body,
95
- )
96
- json_data = response.json()
97
- response.raise_for_status()
98
- return json_data
99
-
100
- def sync_get_payment(self, payment_id: str) -> dict[str, Any] | None:
101
- raise_for_type(payment_id, str)
102
- response = self._sync_make_http_request(
103
- method="GET",
104
- url=f"https://api.yookassa.ru/v3/payments/{payment_id}",
105
- headers=self.headers
106
- )
107
- json_data = response.json()
108
- if response.status_code == 404:
109
- return None
110
- response.raise_for_status()
111
- return json_data
112
-
113
- async def _async_make_http_request(
114
- self,
115
- *,
116
- method: str = "GET",
117
- url: str,
118
- headers: dict[str, Any] | None = None,
119
- **kwargs
120
- ) -> aiohttp.ClientResponse:
121
- return await async_make_http_request(
122
- method=method,
123
- url=url,
124
- headers=combine_dicts(self.headers, (headers if headers is not None else {})),
125
- max_tries_=5,
126
- raise_for_status_=True,
127
- not_raise_for_statuses_=[404],
128
- timeout_=self.timeout_,
129
- auth=aiohttp.BasicAuth(login=str(self.shop_id), password=self.secret_key),
130
- **kwargs
131
- )
132
-
133
- async def async_create_payment(
134
- self, json_body: dict[str, Any]
135
- ) -> dict[str, Any]:
136
-
137
- """
138
- json_body example
139
- json_body = {
140
- "amount": {
141
- "value": "2.0",
142
- "currency": "RUB"
143
- },
144
- "description": "description",
145
- "confirmation": {
146
- "type": "redirect",
147
- "return_url": f"https://t.me/{get_tg_bot_username()}",
148
- "locale": "ru_RU"
149
- },
150
- "capture": True,
151
- "metadata": {},
152
- "merchant_customer_id": ""
153
- }
154
- """
155
-
156
- response = await self._async_make_http_request(
157
- method="POST",
158
- url="https://api.yookassa.ru/v3/payments",
159
- headers={"Idempotence-Key": str(uuid.uuid4())},
160
- json=json_body,
161
- )
162
- json_data = await response.json()
163
- response.raise_for_status()
164
- return json_data
165
-
166
- async def async_get_payment(self, payment_id: str) -> Optional[dict[str, Any]]:
167
- raise_for_type(payment_id, str)
168
- response = await self._async_make_http_request(
169
- method="GET",
170
- url=f"https://api.yookassa.ru/v3/payments/{payment_id}",
171
- )
172
- json_data = await response.json()
173
- if response.status == 404:
174
- return None
175
- response.raise_for_status()
176
- return json_data
177
-
178
-
179
- def __example():
180
- pass
181
-
182
-
183
- async def __async_example():
184
- pass
185
-
186
-
187
- if __name__ == '__main__':
188
- __example()
189
- asyncio.run(__async_example())