utg-base 1.4.0__py3-none-any.whl → 1.5.1__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.
@@ -1,4 +1,2 @@
1
1
  from .periodic_task import PeriodicTaskViewSet, PeriodicTaskRunNowView
2
2
  from .task_result import TaskResultViewSet
3
-
4
-
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:
@@ -1 +1,2 @@
1
1
  from .jwt_user import JWTUser
2
+ from .timestamp import BaseTimestamp
@@ -0,0 +1,9 @@
1
+ from django.db import models
2
+
3
+
4
+ class BaseTimestamp(models.Model):
5
+ created_at = models.DateTimeField(auto_now_add=True)
6
+ updated_at = models.DateTimeField(auto_now=True)
7
+
8
+ class Meta:
9
+ abstract = True
utg_base/utils/data.py CHANGED
@@ -28,9 +28,24 @@ def deep_round(data: dict | list, ndigits: int, in_place=True):
28
28
  return deep_map(data, lambda value: isinstance(value, float), lambda value: round(value, ndigits), in_place)
29
29
 
30
30
 
31
- def safe_sum(*args, allow_null=True):
32
- if isinstance(args[0], Iterable):
31
+ def to_numeric_or_none(*args):
32
+ _is_iterable = isinstance(args[0], Iterable) and not isinstance(args[0], str)
33
+ if _is_iterable:
33
34
  args = args[0]
35
+ result = []
36
+
37
+ for x in args:
38
+ if isinstance(x, (int, float, complex, bool)):
39
+ result.append(x)
40
+ else:
41
+ result.append(None)
42
+ if not _is_iterable and len(result) == 1 and len(args) == 1:
43
+ return result[0]
44
+ return result
45
+
46
+
47
+ def safe_sum(*args, allow_null=True):
48
+ args = to_numeric_or_none(*args)
34
49
 
35
50
  if all(arg is None for arg in args):
36
51
  return None
@@ -44,8 +59,7 @@ def safe_sum(*args, allow_null=True):
44
59
 
45
60
 
46
61
  def safe_subtract(*args, allow_null=False):
47
- if isinstance(args[0], Iterable):
48
- args = args[0]
62
+ args = to_numeric_or_none(*args)
49
63
 
50
64
  if all(arg is None for arg in args):
51
65
  return None
@@ -56,3 +70,37 @@ def safe_subtract(*args, allow_null=False):
56
70
  for arg in args[1:]:
57
71
  _sum -= arg or 0
58
72
  return _sum
73
+
74
+
75
+ def safe_multiply(*args, allow_null=False):
76
+ args = to_numeric_or_none(*args)
77
+
78
+ if all(arg is None for arg in args):
79
+ return None
80
+ if not allow_null and any(arg is None for arg in args):
81
+ return None
82
+
83
+ result = 1
84
+ for arg in args:
85
+ value = 0 if allow_null and arg is None else arg
86
+ result *= value
87
+ return result
88
+
89
+
90
+ def safe_divide(*args, allow_null=False):
91
+ args = to_numeric_or_none(*args)
92
+
93
+ if all(arg is None for arg in args):
94
+ return None
95
+ if not allow_null and any(arg is None for arg in args):
96
+ return None
97
+
98
+ result = 0 if allow_null and args[0] is None else args[0]
99
+
100
+ for arg in args[1:]:
101
+ value = 0 if allow_null and arg is None else arg
102
+ if value == 0:
103
+ return None
104
+ result /= value
105
+
106
+ return result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: utg-base
3
- Version: 1.4.0
3
+ Version: 1.5.1
4
4
  Summary: UTG Base Package
5
5
  Author: Rovshen
6
6
  Author-email: rovshenashirov1619@gmail.com
@@ -14,7 +14,9 @@ Requires-Dist: django-celery-results (>=2.6.0,<3.0.0)
14
14
  Requires-Dist: django-filter (>=23.5,<24.0)
15
15
  Requires-Dist: djangorestframework (>=3.16.1,<4.0.0)
16
16
  Requires-Dist: djangorestframework-simplejwt[crypto] (>=5.5.1,<6.0.0)
17
+ Requires-Dist: dotenv (>=0.9.9,<0.10.0)
17
18
  Requires-Dist: drf-spectacular[sidecar] (>=0.29.0,<0.30.0)
19
+ Requires-Dist: hvac (>=2.4.0,<3.0.0)
18
20
  Requires-Dist: inflect (>=7.2.1,<8.0.0)
19
21
  Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
20
22
  Description-Content-Type: text/markdown
@@ -20,16 +20,18 @@ utg_base/celery/serializers/__init__.py,sha256=NjQ4dcnyoX9p5ljUBCjDegTKt7icia48G
20
20
  utg_base/celery/serializers/periodic_task.py,sha256=lQShBqUQUOvk6-VQocyGfATZHAAVrng-w6_VjD3_WH4,1298
21
21
  utg_base/celery/serializers/task_result.py,sha256=pt6BRjjvqU1Ah8IUSyL67AZJ1Z5iXAelYe6z-Pv1Nco,220
22
22
  utg_base/celery/urls.py,sha256=ww-ZwAzK0CnOZxqh4gaEYGuRoCgkrolB3jvKsLZEknI,524
23
- utg_base/celery/views/__init__.py,sha256=L2xbYvFZa3FitjiVD6HwA0vwdOCD0ofUez_rVx68Ozo,116
23
+ utg_base/celery/views/__init__.py,sha256=WPNtK_40JCSYGWkDgtpTdOWJ_GOp_dBKs9eK4VNq5Xs,114
24
24
  utg_base/celery/views/periodic_task.py,sha256=OyRJh_-KCicUZD84hksRoOXLHGk7mLF7QlsjncqvQac,1945
25
25
  utg_base/celery/views/task_result.py,sha256=c9HIcohrToRfz1jfZRRZ1ri15FOasjKgMYnzKcA2X8M,726
26
26
  utg_base/constants/__init__.py,sha256=nC8qE-2V6APtjSz8j0A-3ez8yyoRpdRO8pwQnvvpRMk,53
27
27
  utg_base/constants/available_languages.py,sha256=zQh0S0PMuYUdRW_RH36llvMxbvsfbdUtotDjFeysWfQ,56
28
- utg_base/logging.py,sha256=MNPUQ9Hdg-0YTFlJBOwhajqKz-8Y5P4POkqRNIU9ga8,5078
28
+ utg_base/env.py,sha256=1Ljxt9clniKl_P2FKG9eoU-7lj00iLHKWDcSVd8wBD4,603
29
+ utg_base/logging.py,sha256=6mqhirIz5p1ne3av4S8j02TD5lJ4HyDKvMQsfUJ62po,4667
29
30
  utg_base/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
31
  utg_base/middleware/locale.py,sha256=1hp_T_VuHCz0ITjwJ_F1rpf5kXQ0ulEmK1yoRWD1GRc,557
31
- utg_base/models/__init__.py,sha256=ylLp_n2WJqvmuG-4X8yv119Ikcx-OFSYHUcnggUeQeo,30
32
+ utg_base/models/__init__.py,sha256=1zXygGICiR3iUCKdkNal9d3i3kNp654gFgBf_VlR2gI,67
32
33
  utg_base/models/jwt_user.py,sha256=6TQ5wB_OZBtGhRL-2MonBGZm0n0Y86s4BRTxiRlUJOk,375
34
+ utg_base/models/timestamp.py,sha256=AkCliNXnvs8Z17b1mcS7gOK7v6h3Jul6WCyGyVAkb-w,217
33
35
  utg_base/references_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
36
  utg_base/references_api/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
35
37
  utg_base/references_api/apps.py,sha256=thAGmO-ZT-OD9dHHBSQRL_RRt-Es_jt-mEmHgVTpERs,168
@@ -40,12 +42,12 @@ utg_base/references_api/utils.py,sha256=VzQMnGeWC0I-6BkK_9Lo9eSH6wd4C766oQ84n7SB
40
42
  utg_base/services/__init__.py,sha256=LqtwUiqEZPIbKRGJfve5D5m3ucV6Kw1Nbo5Jnj_hPhY,37
41
43
  utg_base/services/base_api.py,sha256=RBwzO6frYs2TeMKkAohUxtH9JhDTgmb9G5BFijajg68,5207
42
44
  utg_base/utils/__init__.py,sha256=5XmIPVpOl9Tjtzkx_bBeZD1uCpBE-R3WX6yiJii9Ip0,101
43
- utg_base/utils/data.py,sha256=XmGJStl2f5Bx2B5F45KOUlyS7JkxYiVdWu66_RA_sWQ,1635
45
+ utg_base/utils/data.py,sha256=gbDEmEcmtaP1iCKEPG5I-q4orl8N3jvVc5eFNkkhG3c,2840
44
46
  utg_base/utils/date.py,sha256=thcbK6RgTUYZfs4_vW5ucuu2e8H0rei6tv7SEC72iwM,3612
45
47
  utg_base/utils/dict_util.py,sha256=ipdCZO8aTukGQ319OWHb2Ij5MNtV-FioJQ4qCX3Th48,758
46
48
  utg_base/utils/response_processors.py,sha256=WdZQL49wOJqCIY2MucAI6sez_llCqih0v_ltQa-mv7k,687
47
49
  utg_base/utils/sql.py,sha256=rqIWcSjdjIMszdRnsnhV5TTYB8W17RPOujIQA9rKC_Y,762
48
50
  utg_base/utils/translation.py,sha256=HAUB64h0Maw82ehCoi0Yb6V6gj1Y5l5RMsv8_FMoV2U,456
49
- utg_base-1.4.0.dist-info/METADATA,sha256=MjQxUE3JqEN6wiA75E8t86l2uL22z9nbuLEwmjUxkK8,804
50
- utg_base-1.4.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
51
- utg_base-1.4.0.dist-info/RECORD,,
51
+ utg_base-1.5.1.dist-info/METADATA,sha256=vNvfSBSIv7V-dQA2MxM1Fcj-bU6wxSDiBrWAEh9mr1U,881
52
+ utg_base-1.5.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
53
+ utg_base-1.5.1.dist-info/RECORD,,