ipulse-shared-core-ftredge 2.37__py3-none-any.whl → 2.39__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 ipulse-shared-core-ftredge might be problematic. Click here for more details.
- ipulse_shared_core_ftredge/__init__.py +3 -2
- ipulse_shared_core_ftredge/utils_common.py +24 -0
- ipulse_shared_core_ftredge/utils_templates_and_schemas.py +62 -59
- {ipulse_shared_core_ftredge-2.37.dist-info → ipulse_shared_core_ftredge-2.39.dist-info}/METADATA +1 -1
- {ipulse_shared_core_ftredge-2.37.dist-info → ipulse_shared_core_ftredge-2.39.dist-info}/RECORD +8 -7
- {ipulse_shared_core_ftredge-2.37.dist-info → ipulse_shared_core_ftredge-2.39.dist-info}/WHEEL +1 -1
- {ipulse_shared_core_ftredge-2.37.dist-info → ipulse_shared_core_ftredge-2.39.dist-info}/LICENCE +0 -0
- {ipulse_shared_core_ftredge-2.37.dist-info → ipulse_shared_core_ftredge-2.39.dist-info}/top_level.txt +0 -0
|
@@ -4,8 +4,9 @@ from .utils_gcp import (setup_gcp_logger_and_error_report,
|
|
|
4
4
|
read_csv_from_gcs, read_json_from_gcs,
|
|
5
5
|
write_csv_to_gcs, write_json_to_gcs)
|
|
6
6
|
from .utils_templates_and_schemas import (create_bigquery_schema_from_json,
|
|
7
|
-
update_check_with_schema_template
|
|
8
|
-
|
|
7
|
+
update_check_with_schema_template)
|
|
8
|
+
from .utils_common import (create_custom_notice, create_exception_notice)
|
|
9
|
+
|
|
9
10
|
from .enums import (NoticeSeverity, Unit, Frequency,
|
|
10
11
|
Module, SubModule, BaseDataCategory,
|
|
11
12
|
FinCoreCategory, FincCoreSubCategory,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# pylint: disable=missing-module-docstring
|
|
2
|
+
# pylint: disable=missing-function-docstring
|
|
3
|
+
# pylint: disable=logging-fstring-interpolation
|
|
4
|
+
# pylint: disable=line-too-long
|
|
5
|
+
|
|
6
|
+
def create_custom_notice(severity, subject, message):
|
|
7
|
+
return {
|
|
8
|
+
"severity_code": severity.value,
|
|
9
|
+
"severity_name": severity.name,
|
|
10
|
+
"subject": subject,
|
|
11
|
+
"message": message
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def create_exception_notice(severity, exception_code,exception_message, exception_traceback=None, subject=None, message=None):
|
|
16
|
+
return {
|
|
17
|
+
"severity_code": severity.value,
|
|
18
|
+
"severity_name": severity.name,
|
|
19
|
+
"subject": subject,
|
|
20
|
+
"message": message,
|
|
21
|
+
"exception_code": exception_code,
|
|
22
|
+
"exception_message": exception_message,
|
|
23
|
+
"exception_traceback": exception_traceback
|
|
24
|
+
}
|
|
@@ -6,14 +6,8 @@
|
|
|
6
6
|
import datetime
|
|
7
7
|
from google.cloud import bigquery
|
|
8
8
|
from ipulse_shared_core_ftredge.enums.enums_common_utils import NoticeSeverity
|
|
9
|
+
from ipulse_shared_core_ftredge.utils_common import create_custom_notice
|
|
9
10
|
|
|
10
|
-
def create_data_check_notice(severity, field_name, message):
|
|
11
|
-
return {
|
|
12
|
-
"severity_code": severity.value,
|
|
13
|
-
"severity_name": severity.name,
|
|
14
|
-
"subject": field_name,
|
|
15
|
-
"message": message
|
|
16
|
-
}
|
|
17
11
|
|
|
18
12
|
def create_bigquery_schema_from_json(json_schema):
|
|
19
13
|
schema = []
|
|
@@ -36,86 +30,95 @@ def update_check_with_schema_template(updates, schema, dt_ts_to_str=True, check_
|
|
|
36
30
|
field_name = field["name"]
|
|
37
31
|
field_type = field["type"]
|
|
38
32
|
mode = field["mode"]
|
|
33
|
+
|
|
34
|
+
# Initialize notice to None at the start of each field processing
|
|
35
|
+
notice = None
|
|
39
36
|
|
|
40
37
|
if field_name in updates:
|
|
41
38
|
value = updates[field_name]
|
|
42
39
|
|
|
43
40
|
# Handle date and timestamp formatting
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
|
|
42
|
+
# Validate and potentially convert date and timestamp fields
|
|
43
|
+
if field_type == "DATE":
|
|
44
|
+
value, notice = handle_date_fields(field_name, value, dt_ts_to_str)
|
|
45
|
+
elif field_type == "TIMESTAMP":
|
|
46
|
+
value, notice = handle_timestamp_fields(field_name, value, dt_ts_to_str)
|
|
47
|
+
elif field_type in ["STRING", "INT64", "FLOAT64", "BOOL"]:
|
|
48
|
+
value, notice = handle_type_conversion(field_type, field_name, value )
|
|
49
|
+
|
|
50
|
+
if notice:
|
|
51
|
+
notices.append(notice)
|
|
52
|
+
|
|
51
53
|
# Check and handle max length restriction
|
|
52
54
|
if check_max_length and "max_length" in field:
|
|
53
55
|
value,notice = check_and_truncate_length(field_name, value, field["max_length"])
|
|
54
56
|
if notice:
|
|
55
57
|
notices.append(notice)
|
|
56
|
-
|
|
57
|
-
if field_type in ["STRING", "INT64", "FLOAT64", "BOOL"]:
|
|
58
|
-
value, notice = handle_type_conversion(field_type, field_name, value )
|
|
59
|
-
if notice:
|
|
60
|
-
notices.append(notice)
|
|
61
|
-
|
|
58
|
+
|
|
62
59
|
# Only add to the dictionary if value is not None or the field is required
|
|
63
60
|
if value is not None or mode == "REQUIRED":
|
|
64
61
|
valid_updates[field_name] = value
|
|
65
62
|
|
|
66
63
|
elif mode == "REQUIRED":
|
|
67
|
-
notice=
|
|
68
|
-
field_name,
|
|
69
|
-
f"Required field '{field_name}' is missing in the updates.")
|
|
64
|
+
notice=create_custom_notice(severity=NoticeSeverity.WARNING_ACTION_REQUIRED,
|
|
65
|
+
subject=field_name,
|
|
66
|
+
message=f"Required field '{field_name}' is missing in the updates.")
|
|
70
67
|
|
|
71
68
|
notices.append(notice)
|
|
72
69
|
|
|
73
70
|
return valid_updates, notices
|
|
74
71
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"""Handles date fields, ensuring they are in the correct format.
|
|
78
|
-
Return is a tuple of the formatted date and a notice."""
|
|
72
|
+
def handle_date_fields(field_name, value, dt_ts_to_str):
|
|
73
|
+
"""Handles date fields, ensuring they are in the correct format and optionally converts them to string."""
|
|
79
74
|
if isinstance(value, datetime.date):
|
|
80
|
-
|
|
75
|
+
if dt_ts_to_str:
|
|
76
|
+
return value.strftime("%Y-%m-%d"), None
|
|
77
|
+
return value, None
|
|
81
78
|
elif isinstance(value, str):
|
|
82
79
|
try:
|
|
83
|
-
datetime.datetime.strptime(value, "%Y-%m-%d")
|
|
84
|
-
|
|
80
|
+
parsed_date = datetime.datetime.strptime(value, "%Y-%m-%d").date()
|
|
81
|
+
if dt_ts_to_str:
|
|
82
|
+
return value, None
|
|
83
|
+
return parsed_date, None
|
|
85
84
|
except ValueError:
|
|
86
|
-
return None,
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
return None, create_custom_notice(severity=NoticeSeverity.WARNING_ACTION_REQUIRED,
|
|
86
|
+
subject=field_name,
|
|
87
|
+
message=f"Expected a DATE in YYYY-MM-DD format but got {value}.")
|
|
89
88
|
else:
|
|
90
|
-
return None,
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
return None, create_custom_notice(severity=NoticeSeverity.WARNING_ACTION_REQUIRED,
|
|
90
|
+
subject=field_name,
|
|
91
|
+
message= f"Expected a DATE or YYYY-MM-DD str format but got {value} of type {type(value).__name__}.")
|
|
93
92
|
|
|
94
93
|
|
|
95
|
-
def handle_timestamp_fields(field_name, value):
|
|
96
|
-
"""Handles timestamp fields, ensuring they are in the correct format."""
|
|
94
|
+
def handle_timestamp_fields(field_name, value, dt_ts_to_str):
|
|
95
|
+
"""Handles timestamp fields, ensuring they are in the correct format and optionally converts them to ISO format string."""
|
|
97
96
|
if isinstance(value, datetime.datetime):
|
|
98
|
-
|
|
97
|
+
if dt_ts_to_str:
|
|
98
|
+
return value.isoformat(), None
|
|
99
|
+
return value, None
|
|
99
100
|
elif isinstance(value, str):
|
|
100
101
|
try:
|
|
101
|
-
datetime.datetime.fromisoformat(value)
|
|
102
|
-
|
|
102
|
+
parsed_datetime = datetime.datetime.fromisoformat(value)
|
|
103
|
+
if dt_ts_to_str:
|
|
104
|
+
return value, None
|
|
105
|
+
return parsed_datetime, None
|
|
103
106
|
except ValueError:
|
|
104
|
-
return None,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
return None, create_custom_notice(severity=NoticeSeverity.WARNING_ACTION_REQUIRED,
|
|
108
|
+
subject=field_name,
|
|
109
|
+
message= f"Expected ISO format TIMESTAMP but got {value}.")
|
|
107
110
|
else:
|
|
108
|
-
return None,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
+
return None, create_custom_notice(severity=NoticeSeverity.WARNING_ACTION_REQUIRED,
|
|
112
|
+
subject=field_name,
|
|
113
|
+
message= f"Expected ISO format TIMESTAMP but got {value} of type {type(value).__name__}.")
|
|
111
114
|
|
|
112
115
|
|
|
113
116
|
def check_and_truncate_length(field_name, value, max_length):
|
|
114
117
|
"""Checks and truncates the length of string fields if they exceed the max length."""
|
|
115
118
|
if isinstance(value, str) and len(value) > max_length:
|
|
116
|
-
return value[:max_length],
|
|
117
|
-
|
|
118
|
-
f"Field exceeds max length: {len(value)}/{max_length}. Truncating.")
|
|
119
|
+
return value[:max_length], create_custom_notice(severity=NoticeSeverity.WARNING_ACTION_RECOMMENDED,
|
|
120
|
+
subject= field_name,
|
|
121
|
+
message= f"Field exceeds max length: {len(value)}/{max_length}. Truncating.")
|
|
119
122
|
|
|
120
123
|
return value, None
|
|
121
124
|
|
|
@@ -123,24 +126,24 @@ def check_and_truncate_length(field_name, value, max_length):
|
|
|
123
126
|
|
|
124
127
|
def handle_type_conversion(field_type, field_name, value):
|
|
125
128
|
if field_type == "STRING" and not isinstance(value, str):
|
|
126
|
-
return str(value),
|
|
127
|
-
field_name,
|
|
128
|
-
f"Expected STRING but got {value} of type {type(value).__name__}.")
|
|
129
|
+
return str(value), create_custom_notice(severity=NoticeSeverity.WARNING_ACTION_REQUIRED,
|
|
130
|
+
subject=field_name,
|
|
131
|
+
message= f"Expected STRING but got {value} of type {type(value).__name__}.")
|
|
129
132
|
|
|
130
133
|
if field_type == "INT64" and not isinstance(value, int):
|
|
131
134
|
try:
|
|
132
135
|
return int(value), None
|
|
133
136
|
except ValueError:
|
|
134
|
-
return None,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
return None, create_custom_notice(severity=NoticeSeverity.WARNING_ACTION_REQUIRED,
|
|
138
|
+
subject= field_name,
|
|
139
|
+
message=f"Expected INTEGER, but got {value} of type {type(value).__name__}.")
|
|
137
140
|
if field_type == "FLOAT64" and not isinstance(value, float):
|
|
138
141
|
try:
|
|
139
142
|
return float(value), None
|
|
140
143
|
except ValueError:
|
|
141
|
-
return None,
|
|
142
|
-
field_name,
|
|
143
|
-
|
|
144
|
+
return None, create_custom_notice(severity=NoticeSeverity.WARNING_ACTION_REQUIRED,
|
|
145
|
+
subject=field_name,
|
|
146
|
+
message=f"Expected FLOAT, but got {value} of type {type(value).__name__}.")
|
|
144
147
|
if field_type == "BOOL" and not isinstance(value, bool):
|
|
145
148
|
return bool(value), None
|
|
146
149
|
|
{ipulse_shared_core_ftredge-2.37.dist-info → ipulse_shared_core_ftredge-2.39.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ipulse_shared_core_ftredge
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.39
|
|
4
4
|
Summary: Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.
|
|
5
5
|
Home-page: https://github.com/TheFutureEdge/ipulse_shared_core
|
|
6
6
|
Author: Russlan Ramdowar
|
{ipulse_shared_core_ftredge-2.37.dist-info → ipulse_shared_core_ftredge-2.39.dist-info}/RECORD
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
ipulse_shared_core_ftredge/__init__.py,sha256=
|
|
1
|
+
ipulse_shared_core_ftredge/__init__.py,sha256=87fWkJqrx0FMqOlzxclR6vBRJPisz3SbwhCWbeeP4kk,902
|
|
2
|
+
ipulse_shared_core_ftredge/utils_common.py,sha256=Fs8-guNuz_UJd4p7Vh0bFDzxyE2YCVaj4bxJQynOLpk,803
|
|
2
3
|
ipulse_shared_core_ftredge/utils_gcp.py,sha256=E8TvZ05fTjNr-VQXxSZNCiqT9PwPhtqeKOifIGhb2sg,6289
|
|
3
|
-
ipulse_shared_core_ftredge/utils_templates_and_schemas.py,sha256=
|
|
4
|
+
ipulse_shared_core_ftredge/utils_templates_and_schemas.py,sha256=l70p5NV6R4pNEkqdSz0WOy8RPdsR8BqrP-qlZ7Jjep8,7075
|
|
4
5
|
ipulse_shared_core_ftredge/enums/__init__.py,sha256=PjxJiUConI2TuaG_Ushe2BaFVjBDw1rbq1E9Vt9nXvE,801
|
|
5
6
|
ipulse_shared_core_ftredge/enums/enums_common_utils.py,sha256=ukChcm8R2QwlK4NAfM291mWryCAZvfg7bMpdScQQfok,4360
|
|
6
7
|
ipulse_shared_core_ftredge/enums/enums_data_eng.py,sha256=A8_uiGGacd-_AZP09Zft-DX3rF8aVqqFzFak8s4MsfY,1801
|
|
@@ -17,8 +18,8 @@ ipulse_shared_core_ftredge/models/user_profile_update.py,sha256=oKK0XsQDKkgDvjFP
|
|
|
17
18
|
ipulse_shared_core_ftredge/models/user_status.py,sha256=8TyRd8tBK9_xb0MPKbI5pn9-lX7ovKbeiuWYYPtIOiw,3202
|
|
18
19
|
ipulse_shared_core_ftredge/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
20
|
ipulse_shared_core_ftredge/tests/test.py,sha256=0lS8HP5Quo_BqNoscU40qOH9aJRaa1Pfam5VUBmdld8,682
|
|
20
|
-
ipulse_shared_core_ftredge-2.
|
|
21
|
-
ipulse_shared_core_ftredge-2.
|
|
22
|
-
ipulse_shared_core_ftredge-2.
|
|
23
|
-
ipulse_shared_core_ftredge-2.
|
|
24
|
-
ipulse_shared_core_ftredge-2.
|
|
21
|
+
ipulse_shared_core_ftredge-2.39.dist-info/LICENCE,sha256=YBtYAXNqCCOo9Mr2hfkbSPAM9CeAr2j1VZBSwQTrNwE,1060
|
|
22
|
+
ipulse_shared_core_ftredge-2.39.dist-info/METADATA,sha256=I99qJdttOu8XaJhp1dCaYAuJw-17QlN57kJtSghhtpM,561
|
|
23
|
+
ipulse_shared_core_ftredge-2.39.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
|
|
24
|
+
ipulse_shared_core_ftredge-2.39.dist-info/top_level.txt,sha256=8sgYrptpexkA_6_HyGvho26cVFH9kmtGvaK8tHbsGHk,27
|
|
25
|
+
ipulse_shared_core_ftredge-2.39.dist-info/RECORD,,
|
{ipulse_shared_core_ftredge-2.37.dist-info → ipulse_shared_core_ftredge-2.39.dist-info}/LICENCE
RENAMED
|
File without changes
|
|
File without changes
|