utg-base 1.3.2__py3-none-any.whl → 1.5.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/permissions.py +11 -0
- utg_base/celery/__init__.py +0 -0
- utg_base/celery/apps.py +6 -0
- utg_base/celery/filters/__init__.py +1 -0
- utg_base/celery/filters/task_result.py +5 -0
- utg_base/celery/management/__init__.py +0 -0
- utg_base/celery/management/commands/__init__.py +0 -0
- utg_base/celery/management/commands/migrate_tasks.py +45 -0
- utg_base/celery/serializers/__init__.py +2 -0
- utg_base/celery/serializers/periodic_task.py +38 -0
- utg_base/celery/serializers/task_result.py +8 -0
- utg_base/celery/urls.py +14 -0
- utg_base/celery/views/__init__.py +2 -0
- utg_base/celery/views/periodic_task.py +56 -0
- utg_base/celery/views/task_result.py +18 -0
- utg_base/env.py +27 -0
- utg_base/logging.py +0 -10
- utg_base/models/__init__.py +1 -0
- utg_base/models/timestamp.py +9 -0
- utg_base/utils/data.py +50 -6
- {utg_base-1.3.2.dist-info → utg_base-1.5.0.dist-info}/METADATA +6 -1
- {utg_base-1.3.2.dist-info → utg_base-1.5.0.dist-info}/RECORD +23 -6
- {utg_base-1.3.2.dist-info → utg_base-1.5.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from rest_framework.permissions import BasePermission
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class IsSuperUser(BasePermission):
|
|
5
|
+
"""
|
|
6
|
+
Custom permission to allow access only to superusers.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
def has_permission(self, request, view):
|
|
10
|
+
# Check if the requesting user is a superuser
|
|
11
|
+
return request.user and request.user.is_superuser
|
|
File without changes
|
utg_base/celery/apps.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .task_result import TaskResultFilterSet
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
from django.core.management.base import BaseCommand
|
|
5
|
+
from django_celery_beat.models import CrontabSchedule, PeriodicTask
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Command(BaseCommand):
|
|
9
|
+
help = "Migrate tasks"
|
|
10
|
+
|
|
11
|
+
def add_arguments(self, parser):
|
|
12
|
+
parser.add_argument('--app', type=str, help="An optional argument", required=True)
|
|
13
|
+
|
|
14
|
+
def handle(self, *args, **options):
|
|
15
|
+
try:
|
|
16
|
+
tasks = importlib.import_module(f"{options['app']}.tasks")
|
|
17
|
+
tasks = tasks.tasks
|
|
18
|
+
for task in tasks:
|
|
19
|
+
celery_task, _ = PeriodicTask.objects.update_or_create(
|
|
20
|
+
name=task['name'],
|
|
21
|
+
defaults={
|
|
22
|
+
'crontab': self.get_crontab_schedule(task['crontab']),
|
|
23
|
+
'task': task['task'].name,
|
|
24
|
+
'args': json.dumps(task.get('args') or []),
|
|
25
|
+
'kwargs': json.dumps(task.get('kwargs') or {}),
|
|
26
|
+
'enabled': task.get('enabled', True),
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
self.stdout.write(
|
|
30
|
+
self.style.SUCCESS('Successfully migrated tasks')
|
|
31
|
+
)
|
|
32
|
+
except ModuleNotFoundError:
|
|
33
|
+
self.stdout.write(self.style.ERROR("Tasks module not found"))
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def get_crontab_schedule(crontab='* * * * *'):
|
|
37
|
+
minute, hour, day_of_month, month_of_year, day_of_week = crontab.split(' ')
|
|
38
|
+
cron, _ = CrontabSchedule.objects.get_or_create(
|
|
39
|
+
minute=minute,
|
|
40
|
+
hour=hour,
|
|
41
|
+
day_of_month=day_of_month,
|
|
42
|
+
month_of_year=month_of_year,
|
|
43
|
+
day_of_week=day_of_week,
|
|
44
|
+
)
|
|
45
|
+
return cron
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from django_celery_beat.models import PeriodicTask, CrontabSchedule
|
|
2
|
+
from django_celery_results.models import TaskResult
|
|
3
|
+
from rest_framework import serializers
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from utg_base.celery.serializers import TaskResultSerializer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CrontabScheduleSerializer(serializers.ModelSerializer):
|
|
10
|
+
timezone = serializers.SerializerMethodField()
|
|
11
|
+
|
|
12
|
+
class Meta:
|
|
13
|
+
model = CrontabSchedule
|
|
14
|
+
fields = '__all__'
|
|
15
|
+
|
|
16
|
+
def get_timezone(self, obj):
|
|
17
|
+
return str(obj.timezone) if obj.timezone else None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PeriodicTaskSerializer(serializers.ModelSerializer):
|
|
21
|
+
crontab = CrontabScheduleSerializer(read_only=True)
|
|
22
|
+
task_result = serializers.SerializerMethodField(read_only=True)
|
|
23
|
+
|
|
24
|
+
class Meta:
|
|
25
|
+
model = PeriodicTask
|
|
26
|
+
fields = '__all__'
|
|
27
|
+
read_only_fields = ['name', 'task', 'args', 'kwargs', 'queue', 'exchange', 'routing_key', 'headers', 'priority',
|
|
28
|
+
'expires', 'expire_seconds', 'one_off', 'start_time', 'interval', 'solar', 'clocked']
|
|
29
|
+
|
|
30
|
+
def get_task_result(self, obj):
|
|
31
|
+
latest_task_result = TaskResult.objects.filter(
|
|
32
|
+
periodic_task_name=obj.name
|
|
33
|
+
).order_by('-date_created').first()
|
|
34
|
+
|
|
35
|
+
if not latest_task_result:
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
return TaskResultSerializer(latest_task_result).data
|
utg_base/celery/urls.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from django.urls import path
|
|
2
|
+
|
|
3
|
+
from utg_base.api.routers import OptionalSlashRouter
|
|
4
|
+
from utg_base.celery.views import TaskResultViewSet, PeriodicTaskViewSet, PeriodicTaskRunNowView
|
|
5
|
+
|
|
6
|
+
router = OptionalSlashRouter()
|
|
7
|
+
router.register('task-results', TaskResultViewSet, basename='task-results')
|
|
8
|
+
router.register('periodic-tasks', PeriodicTaskViewSet, basename='periodic-tasks')
|
|
9
|
+
|
|
10
|
+
urlpatterns = [
|
|
11
|
+
path('periodic-tasks/<pk>/run-now/', PeriodicTaskRunNowView.as_view(), name='periodic-tasks-run-now'),
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
urlpatterns += router.urls
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from celery import current_app
|
|
4
|
+
from django_celery_beat.models import PeriodicTask
|
|
5
|
+
from drf_spectacular.utils import extend_schema
|
|
6
|
+
from rest_framework import viewsets, filters
|
|
7
|
+
from rest_framework.exceptions import NotFound, ValidationError
|
|
8
|
+
from rest_framework.permissions import IsAuthenticated
|
|
9
|
+
from rest_framework.response import Response
|
|
10
|
+
from rest_framework.views import APIView
|
|
11
|
+
|
|
12
|
+
from utg_base.api.permissions import IsSuperUser
|
|
13
|
+
from utg_base.celery.serializers import PeriodicTaskSerializer
|
|
14
|
+
from utg_base.utils.translation import translate as _
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@extend_schema(tags=['admin/periodic-tasks'])
|
|
18
|
+
class PeriodicTaskViewSet(viewsets.ModelViewSet):
|
|
19
|
+
http_method_names = ['get', 'patch']
|
|
20
|
+
queryset = PeriodicTask.objects.all()
|
|
21
|
+
serializer_class = PeriodicTaskSerializer
|
|
22
|
+
permission_classes = [IsSuperUser]
|
|
23
|
+
filter_backends = [filters.SearchFilter]
|
|
24
|
+
search_fields = ['name']
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@extend_schema(tags=['admin/periodic-tasks'])
|
|
28
|
+
class PeriodicTaskRunNowView(APIView):
|
|
29
|
+
permission_classes = [IsAuthenticated]
|
|
30
|
+
|
|
31
|
+
def patch(self, request, pk):
|
|
32
|
+
try:
|
|
33
|
+
periodic_task = PeriodicTask.objects.get(pk=pk)
|
|
34
|
+
except PeriodicTask.DoesNotExist:
|
|
35
|
+
raise NotFound(detail=_("Periodic task not found"))
|
|
36
|
+
|
|
37
|
+
if not periodic_task.enabled:
|
|
38
|
+
raise ValidationError(detail=_("Task is disabled"))
|
|
39
|
+
|
|
40
|
+
args = json.loads(periodic_task.args) if periodic_task.args else []
|
|
41
|
+
kwargs = json.loads(periodic_task.kwargs) if periodic_task.kwargs else {}
|
|
42
|
+
|
|
43
|
+
task = current_app.send_task(
|
|
44
|
+
periodic_task.task,
|
|
45
|
+
args=args,
|
|
46
|
+
kwargs=kwargs,
|
|
47
|
+
countdown=0,
|
|
48
|
+
headers = {'periodic_task_name': periodic_task.name}
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return Response({
|
|
52
|
+
"detail": _("Task successfully triggered"),
|
|
53
|
+
"task_id": task.id,
|
|
54
|
+
"task_name": periodic_task.name,
|
|
55
|
+
"celery_task": periodic_task.task,
|
|
56
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import django_filters
|
|
2
|
+
from django_celery_results.models import TaskResult
|
|
3
|
+
from drf_spectacular.utils import extend_schema
|
|
4
|
+
from rest_framework import viewsets, filters
|
|
5
|
+
|
|
6
|
+
from utg_base.celery.filters import TaskResultFilterSet
|
|
7
|
+
from utg_base.api.permissions import IsSuperUser
|
|
8
|
+
from utg_base.celery.serializers import TaskResultSerializer
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@extend_schema(tags=['admin/task-results'])
|
|
12
|
+
class TaskResultViewSet(viewsets.ReadOnlyModelViewSet):
|
|
13
|
+
queryset = TaskResult.objects.all()
|
|
14
|
+
serializer_class = TaskResultSerializer
|
|
15
|
+
permission_classes = [IsSuperUser]
|
|
16
|
+
filterset_class = TaskResultFilterSet
|
|
17
|
+
filter_backends = [filters.SearchFilter, django_filters.rest_framework.DjangoFilterBackend]
|
|
18
|
+
search_fields = ['name']
|
utg_base/env.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import dotenv
|
|
4
|
+
import hvac
|
|
5
|
+
from django.conf import settings
|
|
6
|
+
|
|
7
|
+
dotenv.load_dotenv(settings.BASE_DIR / '.env')
|
|
8
|
+
|
|
9
|
+
client = hvac.Client(
|
|
10
|
+
url=os.environ.get("VAULT_URL"),
|
|
11
|
+
token=os.environ.get("VAULT_TOKEN"),
|
|
12
|
+
verify=False
|
|
13
|
+
)
|
|
14
|
+
if not client.is_authenticated():
|
|
15
|
+
raise Exception("Vault authentication failed")
|
|
16
|
+
|
|
17
|
+
envs = client.secrets.kv.read_secret_version(
|
|
18
|
+
path=os.environ.get("VAULT_PATH"),
|
|
19
|
+
mount_point="utg-scada"
|
|
20
|
+
)['data']['data']
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def env(key, default=None):
|
|
24
|
+
if key in os.environ:
|
|
25
|
+
return os.environ.get(key, default)
|
|
26
|
+
else:
|
|
27
|
+
return envs.get(key, default)
|
utg_base/logging.py
CHANGED
|
@@ -21,7 +21,6 @@ class UtgBaseFilter(logging.Filter):
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class UtgBaseLogging:
|
|
24
|
-
enable_file = int(os.environ.get('LOGGING_FILE', False))
|
|
25
24
|
enable_console_info = int(os.environ.get('LOGGING_CONSOLE_INFO', True))
|
|
26
25
|
enable_db_debug = int(os.environ.get('LOGGING_DB_DEBUG', False))
|
|
27
26
|
enable_loki = int(os.environ.get('LOGGING_LOKI', True))
|
|
@@ -51,13 +50,6 @@ class UtgBaseLogging:
|
|
|
51
50
|
},
|
|
52
51
|
},
|
|
53
52
|
'handlers': {
|
|
54
|
-
'file': {
|
|
55
|
-
'level': 'ERROR',
|
|
56
|
-
'class': 'logging.FileHandler',
|
|
57
|
-
'filename': 'logs/django-error.log',
|
|
58
|
-
'formatter': 'simple',
|
|
59
|
-
'filters': ['trim_path'],
|
|
60
|
-
},
|
|
61
53
|
'console_info': {
|
|
62
54
|
'level': 'INFO',
|
|
63
55
|
'class': 'logging.StreamHandler',
|
|
@@ -114,8 +106,6 @@ class UtgBaseLogging:
|
|
|
114
106
|
def logging(cls):
|
|
115
107
|
_logging = cls.__LOGGING.copy()
|
|
116
108
|
|
|
117
|
-
if cls.enable_file:
|
|
118
|
-
_logging['loggers']['django']['handlers'].append('file')
|
|
119
109
|
if cls.enable_console_info:
|
|
120
110
|
_logging['loggers']['django']['handlers'].append('console_info')
|
|
121
111
|
if cls.enable_db_debug:
|
utg_base/models/__init__.py
CHANGED
utg_base/utils/data.py
CHANGED
|
@@ -24,13 +24,24 @@ def deep_map(data: dict | list, func_cond, func_map, in_place=True):
|
|
|
24
24
|
return data
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def
|
|
28
|
-
|
|
27
|
+
def to_numeric_or_none(*args):
|
|
28
|
+
_is_iterable = isinstance(args[0], Iterable) and not isinstance(args[0], str)
|
|
29
|
+
if _is_iterable:
|
|
30
|
+
args = args[0]
|
|
31
|
+
result = []
|
|
32
|
+
|
|
33
|
+
for x in args:
|
|
34
|
+
if isinstance(x, (int, float, complex, bool)):
|
|
35
|
+
result.append(x)
|
|
36
|
+
else:
|
|
37
|
+
result.append(None)
|
|
38
|
+
if not _is_iterable and len(result) == 1 and len(args) == 1:
|
|
39
|
+
return result[0]
|
|
40
|
+
return result
|
|
29
41
|
|
|
30
42
|
|
|
31
43
|
def safe_sum(*args, allow_null=True):
|
|
32
|
-
|
|
33
|
-
args = args[0]
|
|
44
|
+
args = to_numeric_or_none(*args)
|
|
34
45
|
|
|
35
46
|
if all(arg is None for arg in args):
|
|
36
47
|
return None
|
|
@@ -44,8 +55,7 @@ def safe_sum(*args, allow_null=True):
|
|
|
44
55
|
|
|
45
56
|
|
|
46
57
|
def safe_subtract(*args, allow_null=False):
|
|
47
|
-
|
|
48
|
-
args = args[0]
|
|
58
|
+
args = to_numeric_or_none(*args)
|
|
49
59
|
|
|
50
60
|
if all(arg is None for arg in args):
|
|
51
61
|
return None
|
|
@@ -56,3 +66,37 @@ def safe_subtract(*args, allow_null=False):
|
|
|
56
66
|
for arg in args[1:]:
|
|
57
67
|
_sum -= arg or 0
|
|
58
68
|
return _sum
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def safe_multiply(*args, allow_null=False):
|
|
72
|
+
args = to_numeric_or_none(*args)
|
|
73
|
+
|
|
74
|
+
if all(arg is None for arg in args):
|
|
75
|
+
return None
|
|
76
|
+
if not allow_null and any(arg is None for arg in args):
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
result = 1
|
|
80
|
+
for arg in args:
|
|
81
|
+
value = 0 if allow_null and arg is None else arg
|
|
82
|
+
result *= value
|
|
83
|
+
return result
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def safe_divide(*args, allow_null=False):
|
|
87
|
+
args = to_numeric_or_none(*args)
|
|
88
|
+
|
|
89
|
+
if all(arg is None for arg in args):
|
|
90
|
+
return None
|
|
91
|
+
if not allow_null and any(arg is None for arg in args):
|
|
92
|
+
return None
|
|
93
|
+
|
|
94
|
+
result = 0 if allow_null and args[0] is None else args[0]
|
|
95
|
+
|
|
96
|
+
for arg in args[1:]:
|
|
97
|
+
value = 0 if allow_null and arg is None else arg
|
|
98
|
+
if value == 0:
|
|
99
|
+
return None
|
|
100
|
+
result /= value
|
|
101
|
+
|
|
102
|
+
return result
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: utg-base
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: UTG Base Package
|
|
5
5
|
Author: Rovshen
|
|
6
6
|
Author-email: rovshenashirov1619@gmail.com
|
|
7
7
|
Requires-Python: >=3.14,<4.0
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Requires-Dist: celery (>=5.5.3,<6.0.0)
|
|
9
10
|
Requires-Dist: croniter (>=2.0.3,<3.0.0)
|
|
10
11
|
Requires-Dist: django (>=5.2.7,<6.0.0)
|
|
12
|
+
Requires-Dist: django-celery-beat (>=2.8.1,<3.0.0)
|
|
13
|
+
Requires-Dist: django-celery-results (>=2.6.0,<3.0.0)
|
|
11
14
|
Requires-Dist: django-filter (>=23.5,<24.0)
|
|
12
15
|
Requires-Dist: djangorestframework (>=3.16.1,<4.0.0)
|
|
13
16
|
Requires-Dist: djangorestframework-simplejwt[crypto] (>=5.5.1,<6.0.0)
|
|
17
|
+
Requires-Dist: dotenv (>=0.9.9,<0.10.0)
|
|
14
18
|
Requires-Dist: drf-spectacular[sidecar] (>=0.29.0,<0.30.0)
|
|
19
|
+
Requires-Dist: hvac (>=2.4.0,<3.0.0)
|
|
15
20
|
Requires-Dist: inflect (>=7.2.1,<8.0.0)
|
|
16
21
|
Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
|
|
17
22
|
Description-Content-Type: text/markdown
|
|
@@ -2,19 +2,36 @@ utg_base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
2
2
|
utg_base/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
utg_base/api/base.py,sha256=giGKC68sL1j1NQbbkhIWzhHPcPlvjTPG2evra-xAJ3s,2574
|
|
4
4
|
utg_base/api/pagination.py,sha256=zzIUwW3iF5G_11gFsno9y1DmgFiULQIWRHUj0LKhYfE,854
|
|
5
|
+
utg_base/api/permissions.py,sha256=RjkxYWPl5Xwgk5lIZrcBzIAwlXolX5XPlae1jr-Ln2w,323
|
|
5
6
|
utg_base/api/routers.py,sha256=lU54MVN2BF_q1AWp9EdXkG3m_ivYRtvbNGXFIRKz7u0,177
|
|
6
7
|
utg_base/api/serializers.py,sha256=qI6wWjwl1oeUPHCJUCpYFIaiRFvfQW6FM0xPC9fwfQI,1214
|
|
7
8
|
utg_base/api/views.py,sha256=yYCEJRouFA71cI2Ubc1A736oLg9NGWyTIVnD-Q85k6w,279
|
|
8
9
|
utg_base/authentications/__init__.py,sha256=a6twO_bBf8FAHYl7PXawfR2UbBwwdueG1uS_dbq2g_I,109
|
|
9
10
|
utg_base/authentications/microservice_authentication.py,sha256=6aAncxIpA4FcyRegd7QqRYvW5Wn8FxyPU0nQqCVuEs4,976
|
|
10
11
|
utg_base/authentications/models.py,sha256=JQonSdXeSeoF003QlmPvH58nWmVJRKlWWjW_ySqXaYg,2496
|
|
12
|
+
utg_base/celery/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
utg_base/celery/apps.py,sha256=eL9Il9gGLrtZtXOxWgQK1j8JH5g677h_He7Z1ldUiuA,151
|
|
14
|
+
utg_base/celery/filters/__init__.py,sha256=wnkV8cPEvvHIl8OoMTv7fvSglDSFY8XxpCjUveRNUyg,45
|
|
15
|
+
utg_base/celery/filters/task_result.py,sha256=iXgOrXrO8bvF9S47D53UzsdWQr_JrJ-LtxdjPfcTVjA,138
|
|
16
|
+
utg_base/celery/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
utg_base/celery/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
+
utg_base/celery/management/commands/migrate_tasks.py,sha256=TAvPmYAmMkODdPAucbQDya2dd-BkVFCvWJrolqFdz6w,1667
|
|
19
|
+
utg_base/celery/serializers/__init__.py,sha256=NjQ4dcnyoX9p5ljUBCjDegTKt7icia48GkVSmFCK9Ao,96
|
|
20
|
+
utg_base/celery/serializers/periodic_task.py,sha256=lQShBqUQUOvk6-VQocyGfATZHAAVrng-w6_VjD3_WH4,1298
|
|
21
|
+
utg_base/celery/serializers/task_result.py,sha256=pt6BRjjvqU1Ah8IUSyL67AZJ1Z5iXAelYe6z-Pv1Nco,220
|
|
22
|
+
utg_base/celery/urls.py,sha256=ww-ZwAzK0CnOZxqh4gaEYGuRoCgkrolB3jvKsLZEknI,524
|
|
23
|
+
utg_base/celery/views/__init__.py,sha256=WPNtK_40JCSYGWkDgtpTdOWJ_GOp_dBKs9eK4VNq5Xs,114
|
|
24
|
+
utg_base/celery/views/periodic_task.py,sha256=OyRJh_-KCicUZD84hksRoOXLHGk7mLF7QlsjncqvQac,1945
|
|
25
|
+
utg_base/celery/views/task_result.py,sha256=c9HIcohrToRfz1jfZRRZ1ri15FOasjKgMYnzKcA2X8M,726
|
|
11
26
|
utg_base/constants/__init__.py,sha256=nC8qE-2V6APtjSz8j0A-3ez8yyoRpdRO8pwQnvvpRMk,53
|
|
12
27
|
utg_base/constants/available_languages.py,sha256=zQh0S0PMuYUdRW_RH36llvMxbvsfbdUtotDjFeysWfQ,56
|
|
13
|
-
utg_base/
|
|
28
|
+
utg_base/env.py,sha256=1Ljxt9clniKl_P2FKG9eoU-7lj00iLHKWDcSVd8wBD4,603
|
|
29
|
+
utg_base/logging.py,sha256=6mqhirIz5p1ne3av4S8j02TD5lJ4HyDKvMQsfUJ62po,4667
|
|
14
30
|
utg_base/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
31
|
utg_base/middleware/locale.py,sha256=1hp_T_VuHCz0ITjwJ_F1rpf5kXQ0ulEmK1yoRWD1GRc,557
|
|
16
|
-
utg_base/models/__init__.py,sha256=
|
|
32
|
+
utg_base/models/__init__.py,sha256=1zXygGICiR3iUCKdkNal9d3i3kNp654gFgBf_VlR2gI,67
|
|
17
33
|
utg_base/models/jwt_user.py,sha256=6TQ5wB_OZBtGhRL-2MonBGZm0n0Y86s4BRTxiRlUJOk,375
|
|
34
|
+
utg_base/models/timestamp.py,sha256=AkCliNXnvs8Z17b1mcS7gOK7v6h3Jul6WCyGyVAkb-w,217
|
|
18
35
|
utg_base/references_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
36
|
utg_base/references_api/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
|
|
20
37
|
utg_base/references_api/apps.py,sha256=thAGmO-ZT-OD9dHHBSQRL_RRt-Es_jt-mEmHgVTpERs,168
|
|
@@ -25,12 +42,12 @@ utg_base/references_api/utils.py,sha256=VzQMnGeWC0I-6BkK_9Lo9eSH6wd4C766oQ84n7SB
|
|
|
25
42
|
utg_base/services/__init__.py,sha256=LqtwUiqEZPIbKRGJfve5D5m3ucV6Kw1Nbo5Jnj_hPhY,37
|
|
26
43
|
utg_base/services/base_api.py,sha256=RBwzO6frYs2TeMKkAohUxtH9JhDTgmb9G5BFijajg68,5207
|
|
27
44
|
utg_base/utils/__init__.py,sha256=5XmIPVpOl9Tjtzkx_bBeZD1uCpBE-R3WX6yiJii9Ip0,101
|
|
28
|
-
utg_base/utils/data.py,sha256=
|
|
45
|
+
utg_base/utils/data.py,sha256=luD1L8RwAtvs-qraQMJ2K34fZTlGZy1PvClNeF_Ei-s,2661
|
|
29
46
|
utg_base/utils/date.py,sha256=thcbK6RgTUYZfs4_vW5ucuu2e8H0rei6tv7SEC72iwM,3612
|
|
30
47
|
utg_base/utils/dict_util.py,sha256=ipdCZO8aTukGQ319OWHb2Ij5MNtV-FioJQ4qCX3Th48,758
|
|
31
48
|
utg_base/utils/response_processors.py,sha256=WdZQL49wOJqCIY2MucAI6sez_llCqih0v_ltQa-mv7k,687
|
|
32
49
|
utg_base/utils/sql.py,sha256=rqIWcSjdjIMszdRnsnhV5TTYB8W17RPOujIQA9rKC_Y,762
|
|
33
50
|
utg_base/utils/translation.py,sha256=HAUB64h0Maw82ehCoi0Yb6V6gj1Y5l5RMsv8_FMoV2U,456
|
|
34
|
-
utg_base-1.
|
|
35
|
-
utg_base-1.
|
|
36
|
-
utg_base-1.
|
|
51
|
+
utg_base-1.5.0.dist-info/METADATA,sha256=E-cHB0OHYpNnWjOuSBCW-H5dxE8EtirNZOLsTn3gJXE,881
|
|
52
|
+
utg_base-1.5.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
53
|
+
utg_base-1.5.0.dist-info/RECORD,,
|
|
File without changes
|