ipulse-shared-core-ftredge 2.23__tar.gz → 2.26__tar.gz
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-2.23/src/ipulse_shared_core_ftredge.egg-info → ipulse_shared_core_ftredge-2.26}/PKG-INFO +2 -1
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/setup.py +3 -2
- ipulse_shared_core_ftredge-2.26/src/ipulse_shared_core_ftredge/__init__.py +5 -0
- ipulse_shared_core_ftredge-2.23/src/ipulse_shared_core_ftredge/gcp_utils.py → ipulse_shared_core_ftredge-2.26/src/ipulse_shared_core_ftredge/utils_gcp.py +1 -1
- ipulse_shared_core_ftredge-2.26/src/ipulse_shared_core_ftredge/utils_templates_and_schemas.py +135 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26/src/ipulse_shared_core_ftredge.egg-info}/PKG-INFO +2 -1
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge.egg-info/SOURCES.txt +2 -2
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge.egg-info/requires.txt +1 -0
- ipulse_shared_core_ftredge-2.23/src/ipulse_shared_core_ftredge/__init__.py +0 -5
- ipulse_shared_core_ftredge-2.23/src/ipulse_shared_core_ftredge/template_config_utils.py +0 -32
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/LICENCE +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/README.md +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/pyproject.toml +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/setup.cfg +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/models/__init__.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/models/audit_log_firestore.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/models/organisation.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/models/pulse_enums.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/models/resource_catalog_item.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/models/user_auth.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/models/user_profile.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/models/user_profile_update.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/models/user_status.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/tests/__init__.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge/tests/test.py +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge.egg-info/dependency_links.txt +0 -0
- {ipulse_shared_core_ftredge-2.23 → ipulse_shared_core_ftredge-2.26}/src/ipulse_shared_core_ftredge.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ipulse_shared_core_ftredge
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.26
|
|
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
|
|
@@ -10,3 +10,4 @@ Requires-Dist: python-dateutil~=2.8
|
|
|
10
10
|
Requires-Dist: pytest~=7.1
|
|
11
11
|
Requires-Dist: google-cloud-logging~=3.10.0
|
|
12
12
|
Requires-Dist: google-cloud-error-reporting~=1.11.0
|
|
13
|
+
Requires-Dist: google-cloud-bigquery~=3.24.0
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name='ipulse_shared_core_ftredge',
|
|
5
|
-
version='2.
|
|
5
|
+
version='2.26',
|
|
6
6
|
package_dir={'': 'src'}, # Specify the source directory
|
|
7
7
|
packages=find_packages(where='src'), # Look for packages in 'src'
|
|
8
8
|
install_requires=[
|
|
@@ -11,7 +11,8 @@ setup(
|
|
|
11
11
|
'python-dateutil~=2.8',
|
|
12
12
|
'pytest~=7.1',
|
|
13
13
|
'google-cloud-logging~=3.10.0',
|
|
14
|
-
'google-cloud-error-reporting~=1.11.0'
|
|
14
|
+
'google-cloud-error-reporting~=1.11.0',
|
|
15
|
+
'google-cloud-bigquery~=3.24.0'
|
|
15
16
|
],
|
|
16
17
|
author='Russlan Ramdowar',
|
|
17
18
|
description='Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.',
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from .models import Organisation, UserAuth, UserProfile, UserStatus, UserProfileUpdate, pulse_enums
|
|
2
|
+
from .utils_gcp import setup_gcp_logger_and_error_report, read_csv_from_gcs, read_json_from_gcs, write_csv_to_gcs, write_json_to_gcs
|
|
3
|
+
from .utils_templates_and_schemas import create_bigquery_schema_from_json,update_check_with_schema_template, update_check_with_dict_template
|
|
4
|
+
|
|
5
|
+
|
|
@@ -77,7 +77,7 @@ def setup_gcp_logger_and_error_report(logger_name):
|
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
############################################################################
|
|
80
|
-
##################### GOOGLE
|
|
80
|
+
##################### GOOGLE CLOUD STORAGE UTILS ##########################
|
|
81
81
|
|
|
82
82
|
def read_json_from_gcs(bucket_name, file_name, stor_client, logger):
|
|
83
83
|
""" Helper function to read a JSON file from Google Cloud Storage """
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
from google.cloud import bigquery
|
|
3
|
+
|
|
4
|
+
def create_bigquery_schema_from_json(json_schema):
|
|
5
|
+
schema = []
|
|
6
|
+
for field in json_schema:
|
|
7
|
+
if "max_length" in field:
|
|
8
|
+
schema.append(bigquery.SchemaField(field["name"], field["type"], mode=field["mode"], max_length=field["max_length"]))
|
|
9
|
+
else:
|
|
10
|
+
schema.append(bigquery.SchemaField(field["name"], field["type"], mode=field["mode"]))
|
|
11
|
+
return schema
|
|
12
|
+
|
|
13
|
+
def update_check_with_dict_template(template, updates, logger):
|
|
14
|
+
template_dict = template.copy()
|
|
15
|
+
filtered_updates = {k: v for k, v in updates.items() if k in template}
|
|
16
|
+
template_dict.update(filtered_updates)
|
|
17
|
+
# Log warnings for any fields in the updates that are not in the template
|
|
18
|
+
extra_fields = set(updates.keys()) - set(template.keys())
|
|
19
|
+
if extra_fields:
|
|
20
|
+
logger.warning(f"Fields in the updates extra to the template config: {extra_fields}. You probably forgot to update the Template Config. Do so now.")
|
|
21
|
+
return template_dict
|
|
22
|
+
|
|
23
|
+
def update_check_with_schema_template(updates, schema, logger, dt_ts_to_str=True, check_max_length=True):
|
|
24
|
+
"""Ensure Update dict corresponds to the config schema, ensuring proper formats and lengths."""
|
|
25
|
+
valid_updates = {}
|
|
26
|
+
schema_dict = {field["name"]: field for field in schema}
|
|
27
|
+
|
|
28
|
+
for field_name, value in updates.items():
|
|
29
|
+
if field_name in schema_dict:
|
|
30
|
+
field_type = schema_dict[field_name]["type"]
|
|
31
|
+
|
|
32
|
+
if dt_ts_to_str:
|
|
33
|
+
if field_type == "DATE":
|
|
34
|
+
value = handle_date_fields(field_name, value, logger)
|
|
35
|
+
elif field_type == "TIMESTAMP":
|
|
36
|
+
value = handle_timestamp_fields(field_name, value, logger)
|
|
37
|
+
|
|
38
|
+
if check_max_length and "max_length" in schema_dict[field_name]:
|
|
39
|
+
value = check_and_truncate_length(field_name, value, schema_dict[field_name]["max_length"], logger)
|
|
40
|
+
|
|
41
|
+
# Set the value in the template dictionary based on the field type
|
|
42
|
+
if field_type == "STRING" and not isinstance(value, str):
|
|
43
|
+
logger.warning(f"Field {field_name} expected to be a string but got {type(value).__name__}.")
|
|
44
|
+
value = str(value)
|
|
45
|
+
elif field_type == "INT64" and not isinstance(value, int):
|
|
46
|
+
logger.warning(f"Field {field_name} expected to be an int but got {type(value).__name__}.")
|
|
47
|
+
try:
|
|
48
|
+
value = int(value)
|
|
49
|
+
except ValueError:
|
|
50
|
+
logger.warning(f"Cannot convert value {value} of field {field_name} to int.")
|
|
51
|
+
value = None
|
|
52
|
+
elif field_type == "FLOAT64" and not isinstance(value, float):
|
|
53
|
+
logger.warning(f"Field {field_name} expected to be a float but got {type(value).__name__}.")
|
|
54
|
+
try:
|
|
55
|
+
value = float(value)
|
|
56
|
+
except ValueError:
|
|
57
|
+
logger.warning(f"Cannot convert value {value} of field {field_name} to float.")
|
|
58
|
+
value = None
|
|
59
|
+
elif field_type == "BOOL" and not isinstance(value, bool):
|
|
60
|
+
logger.warning(f"Field {field_name} expected to be a bool but got {type(value).__name__}.")
|
|
61
|
+
value = bool(value)
|
|
62
|
+
|
|
63
|
+
valid_updates[field_name] = value
|
|
64
|
+
else:
|
|
65
|
+
logger.warning(f"Field {field_name} not in schema template, it will be ignored.You probably forgot to update the Schema Config. Do so now. "
|
|
66
|
+
"And assess the manual work required to fix missed data.")
|
|
67
|
+
|
|
68
|
+
# Check for missing REQUIRED fields
|
|
69
|
+
for field in schema:
|
|
70
|
+
if field["mode"] == "REQUIRED" and field["name"] not in valid_updates:
|
|
71
|
+
logger.warning(f"Required field '{field['name']}' is missing in the updates.")
|
|
72
|
+
|
|
73
|
+
return valid_updates
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def check_updates_formatting(updates, schema, logger, dt_ts_to_str, check_max_length):
|
|
77
|
+
"""Processes updates to ensure they match the schema, handling dates, timestamps, and lengths."""
|
|
78
|
+
for field in schema:
|
|
79
|
+
field_name = field["name"]
|
|
80
|
+
field_type = field["type"]
|
|
81
|
+
|
|
82
|
+
if field_name in updates:
|
|
83
|
+
value = updates[field_name]
|
|
84
|
+
|
|
85
|
+
if dt_ts_to_str:
|
|
86
|
+
if field_type == "DATE":
|
|
87
|
+
updates[field_name] = handle_date_fields(field_name, value, logger)
|
|
88
|
+
elif field_type == "TIMESTAMP":
|
|
89
|
+
updates[field_name] = handle_timestamp_fields(field_name, value, logger)
|
|
90
|
+
|
|
91
|
+
if check_max_length and "max_length" in field:
|
|
92
|
+
updates[field_name] = check_and_truncate_length(field_name, value, field["max_length"], logger)
|
|
93
|
+
|
|
94
|
+
return updates
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def handle_date_fields(field_name, value, logger):
|
|
98
|
+
"""Handles date fields, ensuring they are in the correct format."""
|
|
99
|
+
if isinstance(value, datetime.date):
|
|
100
|
+
return value.strftime("%Y-%m-%d")
|
|
101
|
+
elif isinstance(value, str):
|
|
102
|
+
try:
|
|
103
|
+
datetime.datetime.strptime(value, "%Y-%m-%d")
|
|
104
|
+
return value
|
|
105
|
+
except ValueError:
|
|
106
|
+
logger.warning(f"Invalid date format for field {field_name}, expected YYYY-MM-DD")
|
|
107
|
+
return None
|
|
108
|
+
else:
|
|
109
|
+
logger.warning(f"Invalid date format for field {field_name}")
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def handle_timestamp_fields(field_name, value, logger):
|
|
114
|
+
"""Handles timestamp fields, ensuring they are in the correct format."""
|
|
115
|
+
if isinstance(value, datetime.datetime):
|
|
116
|
+
return value.isoformat()
|
|
117
|
+
elif isinstance(value, str):
|
|
118
|
+
try:
|
|
119
|
+
datetime.datetime.fromisoformat(value)
|
|
120
|
+
return value
|
|
121
|
+
except ValueError:
|
|
122
|
+
logger.warning(f"Invalid timestamp format for field {field_name}, expected ISO format")
|
|
123
|
+
return None
|
|
124
|
+
else:
|
|
125
|
+
logger.warning(f"Invalid timestamp format for field {field_name}")
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
def check_and_truncate_length(field_name, value, max_length, logger):
|
|
129
|
+
"""Checks and truncates the length of string fields if they exceed the max length."""
|
|
130
|
+
if isinstance(value, str) and len(value) > max_length:
|
|
131
|
+
logger.warning(f"Field {field_name} exceeds max length of {max_length}. Truncating.")
|
|
132
|
+
return value[:max_length]
|
|
133
|
+
return value
|
|
134
|
+
|
|
135
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ipulse_shared_core_ftredge
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.26
|
|
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
|
|
@@ -10,3 +10,4 @@ Requires-Dist: python-dateutil~=2.8
|
|
|
10
10
|
Requires-Dist: pytest~=7.1
|
|
11
11
|
Requires-Dist: google-cloud-logging~=3.10.0
|
|
12
12
|
Requires-Dist: google-cloud-error-reporting~=1.11.0
|
|
13
|
+
Requires-Dist: google-cloud-bigquery~=3.24.0
|
|
@@ -3,8 +3,8 @@ README.md
|
|
|
3
3
|
pyproject.toml
|
|
4
4
|
setup.py
|
|
5
5
|
src/ipulse_shared_core_ftredge/__init__.py
|
|
6
|
-
src/ipulse_shared_core_ftredge/
|
|
7
|
-
src/ipulse_shared_core_ftredge/
|
|
6
|
+
src/ipulse_shared_core_ftredge/utils_gcp.py
|
|
7
|
+
src/ipulse_shared_core_ftredge/utils_templates_and_schemas.py
|
|
8
8
|
src/ipulse_shared_core_ftredge.egg-info/PKG-INFO
|
|
9
9
|
src/ipulse_shared_core_ftredge.egg-info/SOURCES.txt
|
|
10
10
|
src/ipulse_shared_core_ftredge.egg-info/dependency_links.txt
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
from .models import Organisation, UserAuth, UserProfile, UserStatus, UserProfileUpdate, pulse_enums
|
|
2
|
-
from .gcp_utils import setup_gcp_logger_and_error_report, read_csv_from_gcs, read_json_from_gcs, write_csv_to_gcs, write_json_to_gcs
|
|
3
|
-
from .template_config_utils import full_update_template, partial_update_template
|
|
4
|
-
|
|
5
|
-
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
def full_update_template(template, updates, logger):
|
|
2
|
-
template_dict = template.copy()
|
|
3
|
-
filtered_updates = {k: v for k, v in updates.items() if k in template}
|
|
4
|
-
template_dict.update(filtered_updates)
|
|
5
|
-
|
|
6
|
-
# Log warnings for any fields in the template that are not updated
|
|
7
|
-
missing_fields = set(template.keys()) - set(filtered_updates.keys())
|
|
8
|
-
if missing_fields:
|
|
9
|
-
logger.warning(f"Fields in the template config but not updated: {missing_fields}")
|
|
10
|
-
# Log warnings for any fields in the updates that are not in the template
|
|
11
|
-
extra_fields = set(updates.keys()) - set(template.keys())
|
|
12
|
-
if extra_fields:
|
|
13
|
-
logger.warning(f"Fields in the updates extea to the template config: {extra_fields}. You probably forgot to update the Template Config. Do so now.")
|
|
14
|
-
if extra_fields:
|
|
15
|
-
raise ValueError(f"Updates contain fields not present in the template: {extra_fields}")
|
|
16
|
-
|
|
17
|
-
return template_dict
|
|
18
|
-
|
|
19
|
-
def partial_update_template(template, updates, logger):
|
|
20
|
-
template_dict = template.copy()
|
|
21
|
-
filtered_updates = {k: v for k, v in updates.items() if k in template}
|
|
22
|
-
template_dict.update(filtered_updates)
|
|
23
|
-
|
|
24
|
-
# Log warnings for any fields in the updates that are not in the template
|
|
25
|
-
extra_fields = set(updates.keys()) - set(template.keys())
|
|
26
|
-
if extra_fields:
|
|
27
|
-
logger.warning(f"Fields in the updates not in the template: {extra_fields}")
|
|
28
|
-
|
|
29
|
-
if extra_fields:
|
|
30
|
-
raise ValueError(f"Updates contain fields not present in the template: {extra_fields}")
|
|
31
|
-
|
|
32
|
-
return template_dict
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|