utg-base 1.6.0__py3-none-any.whl → 1.7.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.
- utg_base/api/spectacular.py +3 -3
- utg_base/logging.py +13 -11
- utg_base/middleware/debug.py +3 -3
- utg_base/utils/thread.py +67 -0
- utg_base/utils/translation.py +2 -3
- {utg_base-1.6.0.dist-info → utg_base-1.7.0.dist-info}/METADATA +3 -3
- {utg_base-1.6.0.dist-info → utg_base-1.7.0.dist-info}/RECORD +8 -7
- {utg_base-1.6.0.dist-info → utg_base-1.7.0.dist-info}/WHEEL +0 -0
utg_base/api/spectacular.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
1
|
from django.conf import settings
|
|
4
2
|
from django.http import HttpResponseForbidden
|
|
5
3
|
from django.urls import path
|
|
6
4
|
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
|
|
7
5
|
from rest_framework.views import APIView
|
|
8
6
|
|
|
7
|
+
from utg_base.env import env
|
|
8
|
+
|
|
9
9
|
|
|
10
10
|
class DebugTokenRequiredMixin(APIView):
|
|
11
11
|
"""
|
|
@@ -14,7 +14,7 @@ class DebugTokenRequiredMixin(APIView):
|
|
|
14
14
|
|
|
15
15
|
def dispatch(self, request, *args, **kwargs):
|
|
16
16
|
token = request.headers.get("X-Debug-Token")
|
|
17
|
-
if not settings.DEBUG and token !=
|
|
17
|
+
if not settings.DEBUG and token != env("DJANGO_SECRET_KEY"):
|
|
18
18
|
return HttpResponseForbidden("Forbidden")
|
|
19
19
|
return super().dispatch(request, *args, **kwargs)
|
|
20
20
|
|
utg_base/logging.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
3
|
|
|
4
|
+
from utg_base.env import env
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
class UtgBaseFilter(logging.Filter):
|
|
6
8
|
BASE_DIR = os.getcwd()
|
|
@@ -21,10 +23,10 @@ class UtgBaseFilter(logging.Filter):
|
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
class UtgBaseLogging:
|
|
24
|
-
enable_console_info = int(
|
|
25
|
-
enable_db_debug = int(
|
|
26
|
-
enable_loki = int(
|
|
27
|
-
enable_loki_debug = int(
|
|
26
|
+
enable_console_info = int(env('LOGGING_CONSOLE_INFO', True))
|
|
27
|
+
enable_db_debug = int(env('LOGGING_DB_DEBUG', False))
|
|
28
|
+
enable_loki = int(env('LOGGING_LOKI', True))
|
|
29
|
+
enable_loki_debug = int(env('LOGGING_LOKI_DEBUG', False))
|
|
28
30
|
|
|
29
31
|
logger = logging.getLogger('main')
|
|
30
32
|
|
|
@@ -63,19 +65,19 @@ class UtgBaseLogging:
|
|
|
63
65
|
'filters': ['trim_path'],
|
|
64
66
|
},
|
|
65
67
|
'loki': {
|
|
66
|
-
'level':
|
|
68
|
+
'level': env('LOKI_LEVEL', 'ERROR'), # required
|
|
67
69
|
'class': 'django_loki.LokiHttpHandler', # required
|
|
68
|
-
'host':
|
|
70
|
+
'host': env('LOKI_HOST', env('DB_HOST')),
|
|
69
71
|
# required, your grafana/Loki server host, e.g:192.168.25.30
|
|
70
72
|
'formatter': 'loki', # required, loki formatter,
|
|
71
|
-
'port': int(
|
|
73
|
+
'port': int(env('LOKI_PORT', 3100)),
|
|
72
74
|
# optional, your grafana/Loki server port, default is 3100
|
|
73
|
-
'timeout': float(
|
|
75
|
+
'timeout': float(env('LOKI_TIMEOUT', 0.5)),
|
|
74
76
|
# optional, request Loki-server by http or https time out, default is 0.5
|
|
75
|
-
'protocol':
|
|
77
|
+
'protocol': env('LOKI_PROTOCOL', 'http'),
|
|
76
78
|
# optional, Loki-server protocol, default is http
|
|
77
|
-
'source':
|
|
78
|
-
'src_host':
|
|
79
|
+
'source': env('LOKI_SOURCE', 'Loki'), # optional, label name for Loki, default is Loki
|
|
80
|
+
'src_host': env('LOKI_SRC_HOST', 'localhost'),
|
|
79
81
|
# optional, label name for Loki, default is localhost
|
|
80
82
|
'tz': 'Asia/Tashkent',
|
|
81
83
|
# optional, timezone for formatting timestamp, default is UTC, e.g:Asia/Shanghai
|
utg_base/middleware/debug.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
1
|
from django.utils.deprecation import MiddlewareMixin
|
|
4
2
|
|
|
3
|
+
from utg_base.env import env
|
|
4
|
+
|
|
5
5
|
|
|
6
6
|
class DebugOverrideMiddleware(MiddlewareMixin):
|
|
7
7
|
def process_exception(self, request, exception):
|
|
8
|
-
if request.headers.get("X-Debug-Token") ==
|
|
8
|
+
if request.headers.get("X-Debug-Token") == env("DJANGO_SECRET_KEY"):
|
|
9
9
|
from django.views import debug
|
|
10
10
|
return debug.technical_500_response(request, type(exception), exception, exception.__traceback__)
|
utg_base/utils/thread.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import multiprocessing
|
|
2
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
3
|
+
from typing import Callable, Any, Iterable, Tuple, Dict, Union
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ThreadPoolException(Exception):
|
|
7
|
+
"""Exception to wrap the error in each task."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, func: str, exception: Exception):
|
|
10
|
+
self.func = func
|
|
11
|
+
self.exception = exception
|
|
12
|
+
super().__init__(f"Exception in {func}: {exception}")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def parallel_execute(
|
|
16
|
+
*tasks: Union[
|
|
17
|
+
Callable, # func
|
|
18
|
+
Tuple[Callable, Iterable], # (func, args)
|
|
19
|
+
Tuple[Callable, Iterable, Dict[str, Any]] # (func, args, kwargs)
|
|
20
|
+
],
|
|
21
|
+
max_workers: int = None
|
|
22
|
+
) -> list[Any]:
|
|
23
|
+
"""
|
|
24
|
+
Executes multiple functions in parallel.
|
|
25
|
+
Each can be without arguments or with args/kwargs.
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
parallel_execute(func1, func2)
|
|
29
|
+
parallel_execute((func1, (1, 2)), (func2, (), {"x": 5}))
|
|
30
|
+
|
|
31
|
+
The sequence is preserved.
|
|
32
|
+
|
|
33
|
+
:return: Result list or ThreadPoolException objects
|
|
34
|
+
"""
|
|
35
|
+
if not tasks:
|
|
36
|
+
return []
|
|
37
|
+
|
|
38
|
+
cpu_count = multiprocessing.cpu_count()
|
|
39
|
+
max_workers = max_workers or min(cpu_count * 10, len(tasks))
|
|
40
|
+
results = [None] * len(tasks)
|
|
41
|
+
|
|
42
|
+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
43
|
+
futures = {}
|
|
44
|
+
|
|
45
|
+
for i, task in enumerate(tasks):
|
|
46
|
+
# Task unpacking
|
|
47
|
+
if callable(task):
|
|
48
|
+
func, args, kwargs = task, (), {}
|
|
49
|
+
elif isinstance(task, tuple):
|
|
50
|
+
func = task[0]
|
|
51
|
+
args = task[1] if len(task) > 1 else ()
|
|
52
|
+
kwargs = task[2] if len(task) > 2 else {}
|
|
53
|
+
else:
|
|
54
|
+
raise ValueError(f"Invalid task format: {task}")
|
|
55
|
+
|
|
56
|
+
futures[executor.submit(func, *args, **kwargs)] = i
|
|
57
|
+
|
|
58
|
+
for future in as_completed(futures):
|
|
59
|
+
idx = futures[future]
|
|
60
|
+
func = tasks[idx][0] if isinstance(tasks[idx], tuple) else tasks[idx]
|
|
61
|
+
func_name = getattr(func, "__name__", str(func))
|
|
62
|
+
try:
|
|
63
|
+
results[idx] = future.result()
|
|
64
|
+
except Exception as e:
|
|
65
|
+
results[idx] = ThreadPoolException(func=func_name, exception=e)
|
|
66
|
+
|
|
67
|
+
return results
|
utg_base/utils/translation.py
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
1
|
import requests
|
|
4
2
|
from django.utils.translation import get_language
|
|
5
3
|
|
|
6
4
|
from utg_base.constants import AVAILABLE_LANGUAGES
|
|
5
|
+
from utg_base.env import env
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
def translate(key: str) -> str:
|
|
10
|
-
base_url =
|
|
9
|
+
base_url = env('TRANSLATION_SERVICE_URL')
|
|
11
10
|
lang = get_language()
|
|
12
11
|
if lang == 'uz-cyr':
|
|
13
12
|
lang = 'crl'
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: utg-base
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.0
|
|
4
4
|
Summary: UTG Base Package
|
|
5
|
-
Author:
|
|
6
|
-
Author-email:
|
|
5
|
+
Author: Olimboy
|
|
6
|
+
Author-email: shavkatov.olimboy@mail.ru
|
|
7
7
|
Requires-Python: >=3.14,<4.0
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Requires-Dist: celery (>=5.5.3,<6.0.0)
|
|
@@ -5,7 +5,7 @@ utg_base/api/pagination.py,sha256=zzIUwW3iF5G_11gFsno9y1DmgFiULQIWRHUj0LKhYfE,85
|
|
|
5
5
|
utg_base/api/permissions.py,sha256=RjkxYWPl5Xwgk5lIZrcBzIAwlXolX5XPlae1jr-Ln2w,323
|
|
6
6
|
utg_base/api/routers.py,sha256=lU54MVN2BF_q1AWp9EdXkG3m_ivYRtvbNGXFIRKz7u0,177
|
|
7
7
|
utg_base/api/serializers.py,sha256=qI6wWjwl1oeUPHCJUCpYFIaiRFvfQW6FM0xPC9fwfQI,1214
|
|
8
|
-
utg_base/api/spectacular.py,sha256
|
|
8
|
+
utg_base/api/spectacular.py,sha256=W1G2c6Mw8OkTVwXHxJYzbadW9jykkkAn0C8tQu9gfuA,1047
|
|
9
9
|
utg_base/api/views.py,sha256=yYCEJRouFA71cI2Ubc1A736oLg9NGWyTIVnD-Q85k6w,279
|
|
10
10
|
utg_base/authentications/__init__.py,sha256=a6twO_bBf8FAHYl7PXawfR2UbBwwdueG1uS_dbq2g_I,109
|
|
11
11
|
utg_base/authentications/microservice_authentication.py,sha256=6aAncxIpA4FcyRegd7QqRYvW5Wn8FxyPU0nQqCVuEs4,976
|
|
@@ -27,9 +27,9 @@ utg_base/celery/views/task_result.py,sha256=c9HIcohrToRfz1jfZRRZ1ri15FOasjKgMYnz
|
|
|
27
27
|
utg_base/constants/__init__.py,sha256=nC8qE-2V6APtjSz8j0A-3ez8yyoRpdRO8pwQnvvpRMk,53
|
|
28
28
|
utg_base/constants/available_languages.py,sha256=zQh0S0PMuYUdRW_RH36llvMxbvsfbdUtotDjFeysWfQ,56
|
|
29
29
|
utg_base/env.py,sha256=9jRWlaifSDmss6qU2FG2aP0SHP-gPSdk14rjohuXvfM,940
|
|
30
|
-
utg_base/logging.py,sha256=
|
|
30
|
+
utg_base/logging.py,sha256=JHGhuLKU1js_26ReE0LCLWZ66fmlGKuLG9sfbQSfI5w,4565
|
|
31
31
|
utg_base/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
|
-
utg_base/middleware/debug.py,sha256=
|
|
32
|
+
utg_base/middleware/debug.py,sha256=exkeYUK-zSN3PMd4L9F6WlROmQ7Qlpmi_Gr2dqt5vk4,416
|
|
33
33
|
utg_base/middleware/locale.py,sha256=1hp_T_VuHCz0ITjwJ_F1rpf5kXQ0ulEmK1yoRWD1GRc,557
|
|
34
34
|
utg_base/models/__init__.py,sha256=1zXygGICiR3iUCKdkNal9d3i3kNp654gFgBf_VlR2gI,67
|
|
35
35
|
utg_base/models/jwt_user.py,sha256=6TQ5wB_OZBtGhRL-2MonBGZm0n0Y86s4BRTxiRlUJOk,375
|
|
@@ -49,7 +49,8 @@ utg_base/utils/date.py,sha256=thcbK6RgTUYZfs4_vW5ucuu2e8H0rei6tv7SEC72iwM,3612
|
|
|
49
49
|
utg_base/utils/dict_util.py,sha256=ipdCZO8aTukGQ319OWHb2Ij5MNtV-FioJQ4qCX3Th48,758
|
|
50
50
|
utg_base/utils/response_processors.py,sha256=WdZQL49wOJqCIY2MucAI6sez_llCqih0v_ltQa-mv7k,687
|
|
51
51
|
utg_base/utils/sql.py,sha256=rqIWcSjdjIMszdRnsnhV5TTYB8W17RPOujIQA9rKC_Y,762
|
|
52
|
-
utg_base/utils/
|
|
53
|
-
utg_base
|
|
54
|
-
utg_base-1.
|
|
55
|
-
utg_base-1.
|
|
52
|
+
utg_base/utils/thread.py,sha256=4RqRnwtyHymY-dNcuPrMSTamE2V7wCMVfzzyIb0P4TI,2191
|
|
53
|
+
utg_base/utils/translation.py,sha256=GxJHUt0iar_0E7RWBPbeLFQ4DhgXBjffHCmxfKyjFtk,463
|
|
54
|
+
utg_base-1.7.0.dist-info/METADATA,sha256=1XwqfOqDxhuzkk0Rfk5ZRjasjzBHIvYxfA2PuhFO9pk,871
|
|
55
|
+
utg_base-1.7.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
56
|
+
utg_base-1.7.0.dist-info/RECORD,,
|
|
File without changes
|