ipulse-shared-core-ftredge 2.33__py3-none-any.whl → 2.36__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.
@@ -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
- from .enums import (NoticeSeverity,Unit, Frequency,
7
+ update_check_with_schema_template,
8
+ create_data_check_notice)
9
+ from .enums import (NoticeSeverity, Unit, Frequency,
9
10
  Module, SubModule, BaseDataCategory,
10
11
  FinCoreCategory, FincCoreSubCategory,
11
12
  FinCoreRecordsCategory, ExchangeOrPublisher,
@@ -5,7 +5,15 @@
5
5
 
6
6
  import datetime
7
7
  from google.cloud import bigquery
8
- from . import NoticeSeverity
8
+ from ipulse_shared_core_ftredge.enums.enums_common_utils import NoticeSeverity
9
+
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
+ }
9
17
 
10
18
  def create_bigquery_schema_from_json(json_schema):
11
19
  schema = []
@@ -17,124 +25,123 @@ def create_bigquery_schema_from_json(json_schema):
17
25
  return schema
18
26
 
19
27
 
20
- def update_check_with_schema_template(updates, schema, logger, dt_ts_to_str=True, check_max_length=True):
21
-
28
+ def update_check_with_schema_template(updates, schema, dt_ts_to_str=True, check_max_length=True):
29
+
22
30
  """Ensure Update dict corresponds to the config schema, ensuring proper formats and lengths."""
23
31
  valid_updates = {}
24
-
32
+ notices=[] ### THIS IS TO AVOID LOGGING A WARNING RANDOMLY , INSTEAD GROUPPING FOR A GIVEN RUN
33
+
25
34
  # Process updates to conform to the schema
26
35
  for field in schema:
27
36
  field_name = field["name"]
28
37
  field_type = field["type"]
29
38
  mode = field["mode"]
30
-
39
+
31
40
  if field_name in updates:
32
41
  value = updates[field_name]
33
-
42
+
34
43
  # Handle date and timestamp formatting
35
44
  if dt_ts_to_str:
36
45
  if field_type == "DATE":
37
- value = handle_date_fields(field_name, value, logger)
46
+ value, notice = handle_date_fields(field_name, value)
38
47
  elif field_type == "TIMESTAMP":
39
- value = handle_timestamp_fields(field_name, value, logger)
40
-
48
+ value,notice = handle_timestamp_fields(field_name, value)
49
+ if notice:
50
+ notices.append(notice)
41
51
  # Check and handle max length restriction
42
52
  if check_max_length and "max_length" in field:
43
- value = check_and_truncate_length(field_name, value, field["max_length"], logger)
44
-
53
+ value,notice = check_and_truncate_length(field_name, value, field["max_length"])
54
+ if notice:
55
+ notices.append(notice)
45
56
  # Validate and convert types
46
- if field_type == "STRING":
47
- if not isinstance(value, str):
48
- logger.warning(f"Field {field_name} expected to be a string but got {type(value).__name__}.")
49
- value = str(value)
50
- elif field_type == "INT64":
51
- if not isinstance(value, int):
52
- logger.warning(f"Field {field_name} expected to be an int but got {type(value).__name__}.")
53
- try:
54
- value = int(value)
55
- except ValueError:
56
- logger.warning(f"Cannot convert value {value} of field {field_name} to int.")
57
- continue
58
- elif field_type == "FLOAT64":
59
- if not isinstance(value, float):
60
- logger.warning(f"Field {field_name} expected to be a float but got {type(value).__name__}.")
61
- try:
62
- value = float(value)
63
- except ValueError:
64
- logger.warning(f"Cannot convert value {value} of field {field_name} to float.")
65
- continue
66
- elif field_type == "BOOL":
67
- if not isinstance(value, bool):
68
- logger.warning(f"Field {field_name} expected to be a bool but got {type(value).__name__}.")
69
- value = bool(value)
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)
70
61
 
71
62
  # Only add to the dictionary if value is not None or the field is required
72
63
  if value is not None or mode == "REQUIRED":
73
64
  valid_updates[field_name] = value
74
65
 
75
66
  elif mode == "REQUIRED":
76
- logger.warning(f"Required field '{field_name}' is missing in the updates.")
77
-
78
- return valid_updates
79
-
80
-
81
- def check_updates_formatting(updates, schema, logger, dt_ts_to_str, check_max_length):
82
- """Processes updates to ensure they match the schema, handling dates, timestamps, and lengths."""
83
- for field in schema:
84
- field_name = field["name"]
85
- field_type = field["type"]
86
-
87
- if field_name in updates:
88
- value = updates[field_name]
67
+ notice=create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
68
+ field_name,
69
+ f"Required field '{field_name}' is missing in the updates.")
89
70
 
90
- if dt_ts_to_str:
91
- if field_type == "DATE":
92
- updates[field_name] = handle_date_fields(field_name, value, logger)
93
- elif field_type == "TIMESTAMP":
94
- updates[field_name] = handle_timestamp_fields(field_name, value, logger)
95
-
96
- if check_max_length and "max_length" in field:
97
- updates[field_name] = check_and_truncate_length(field_name, value, field["max_length"], logger)
98
-
99
- return updates
71
+ notices.append(notice)
72
+
73
+ return valid_updates, notices
100
74
 
101
75
 
102
- def handle_date_fields(field_name, value, logger):
103
- """Handles date fields, ensuring they are in the correct format."""
76
+ def handle_date_fields(field_name, value):
77
+ """Handles date fields, ensuring they are in the correct format.
78
+ Return is a tuple of the formatted date and a notice."""
104
79
  if isinstance(value, datetime.date):
105
- return value.strftime("%Y-%m-%d")
80
+ return value.strftime("%Y-%m-%d"), None
106
81
  elif isinstance(value, str):
107
82
  try:
108
83
  datetime.datetime.strptime(value, "%Y-%m-%d")
109
84
  return value
110
85
  except ValueError:
111
- logger.warning(f"Invalid date format for field {field_name}, expected YYYY-MM-DD")
112
- return None
86
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
87
+ field_name,
88
+ f"Expected a DATE or YYYY-MM-DD str format but got {value} of type {type(value).__name__}.")
113
89
  else:
114
- logger.warning(f"Invalid date format for field {field_name}")
115
- return None
116
-
90
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
91
+ field_name,
92
+ f"Expected a DATE or YYYY-MM-DD str format but got {value} of type {type(value).__name__}.")
93
+
117
94
 
118
- def handle_timestamp_fields(field_name, value, logger):
95
+ def handle_timestamp_fields(field_name, value):
119
96
  """Handles timestamp fields, ensuring they are in the correct format."""
120
97
  if isinstance(value, datetime.datetime):
121
- return value.isoformat()
98
+ return value.isoformat(), None
122
99
  elif isinstance(value, str):
123
100
  try:
124
101
  datetime.datetime.fromisoformat(value)
125
102
  return value
126
103
  except ValueError:
127
- logger.warning(f"Invalid timestamp format for field {field_name}, expected ISO format")
128
- return None
104
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
105
+ field_name,
106
+ f"Expected ISO format TIMESTAMP but got {value} of type {type(value).__name__}.")
129
107
  else:
130
- logger.warning(f"Invalid timestamp format for field {field_name}")
131
- return None
108
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
109
+ field_name,
110
+ f"Expected ISO format TIMESTAMP but got {value} of type {type(value).__name__}.")
132
111
 
133
- def check_and_truncate_length(field_name, value, max_length, logger):
112
+
113
+ def check_and_truncate_length(field_name, value, max_length):
134
114
  """Checks and truncates the length of string fields if they exceed the max length."""
135
115
  if isinstance(value, str) and len(value) > max_length:
136
- logger.warning(f"Field {field_name} exceeds max length of {max_length}. Truncating.")
137
- return value[:max_length]
138
- return value
116
+ return value[:max_length], create_data_check_notice(NoticeSeverity.WARNING_ACTION_RECOMMENDED,
117
+ field_name,
118
+ f"Field exceeds max length: {len(value)}/{max_length}. Truncating.")
119
+
120
+ return value, None
121
+
139
122
 
140
123
 
124
+ def handle_type_conversion(field_type, field_name, value):
125
+ if field_type == "STRING" and not isinstance(value, str):
126
+ return str(value), create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
127
+ field_name,
128
+ f"Expected STRING but got {value} of type {type(value).__name__}.")
129
+
130
+ if field_type == "INT64" and not isinstance(value, int):
131
+ try:
132
+ return int(value), None
133
+ except ValueError:
134
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
135
+ field_name,
136
+ f"Expected INTEGER, but got {value} of type {type(value).__name__}.")
137
+ if field_type == "FLOAT64" and not isinstance(value, float):
138
+ try:
139
+ return float(value), None
140
+ except ValueError:
141
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
142
+ field_name,
143
+ f"Expected FLOAT, but got {value} of type {type(value).__name__}.")
144
+ if field_type == "BOOL" and not isinstance(value, bool):
145
+ return bool(value), None
146
+
147
+ return value, None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ipulse_shared_core_ftredge
3
- Version: 2.33
3
+ Version: 2.36
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
@@ -1,6 +1,6 @@
1
- ipulse_shared_core_ftredge/__init__.py,sha256=Z8qv6nL-cXEGTHl3zTnL9vxGNZ94uCfJBgsSV7HAkcw,826
1
+ ipulse_shared_core_ftredge/__init__.py,sha256=snLFrVzGmYy6TmXM6-D7Yq4dkcJDRP3g9DeuJQDFPMc,895
2
2
  ipulse_shared_core_ftredge/utils_gcp.py,sha256=E8TvZ05fTjNr-VQXxSZNCiqT9PwPhtqeKOifIGhb2sg,6289
3
- ipulse_shared_core_ftredge/utils_templates_and_schemas.py,sha256=rYk547qbiRx7Q5a5pcb29lkwSArjS_F9Hf1JkX05mBU,5861
3
+ ipulse_shared_core_ftredge/utils_templates_and_schemas.py,sha256=UxRZnTOmV0VfjtrA-0YrTcKgJOMpa6kFiuLSdSUD_XA,6513
4
4
  ipulse_shared_core_ftredge/enums/__init__.py,sha256=PjxJiUConI2TuaG_Ushe2BaFVjBDw1rbq1E9Vt9nXvE,801
5
5
  ipulse_shared_core_ftredge/enums/enums_common_utils.py,sha256=ukChcm8R2QwlK4NAfM291mWryCAZvfg7bMpdScQQfok,4360
6
6
  ipulse_shared_core_ftredge/enums/enums_data_eng.py,sha256=A8_uiGGacd-_AZP09Zft-DX3rF8aVqqFzFak8s4MsfY,1801
@@ -17,8 +17,8 @@ ipulse_shared_core_ftredge/models/user_profile_update.py,sha256=oKK0XsQDKkgDvjFP
17
17
  ipulse_shared_core_ftredge/models/user_status.py,sha256=8TyRd8tBK9_xb0MPKbI5pn9-lX7ovKbeiuWYYPtIOiw,3202
18
18
  ipulse_shared_core_ftredge/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  ipulse_shared_core_ftredge/tests/test.py,sha256=0lS8HP5Quo_BqNoscU40qOH9aJRaa1Pfam5VUBmdld8,682
20
- ipulse_shared_core_ftredge-2.33.dist-info/LICENCE,sha256=YBtYAXNqCCOo9Mr2hfkbSPAM9CeAr2j1VZBSwQTrNwE,1060
21
- ipulse_shared_core_ftredge-2.33.dist-info/METADATA,sha256=nBXAyVU5_otXscH8TQ8DmeIGVkoR01wu8c6LnB6bBec,561
22
- ipulse_shared_core_ftredge-2.33.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
23
- ipulse_shared_core_ftredge-2.33.dist-info/top_level.txt,sha256=8sgYrptpexkA_6_HyGvho26cVFH9kmtGvaK8tHbsGHk,27
24
- ipulse_shared_core_ftredge-2.33.dist-info/RECORD,,
20
+ ipulse_shared_core_ftredge-2.36.dist-info/LICENCE,sha256=YBtYAXNqCCOo9Mr2hfkbSPAM9CeAr2j1VZBSwQTrNwE,1060
21
+ ipulse_shared_core_ftredge-2.36.dist-info/METADATA,sha256=vYm8146CUjDdbz9XOZGikiH2wfd29iIthI6zq608ShI,561
22
+ ipulse_shared_core_ftredge-2.36.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
23
+ ipulse_shared_core_ftredge-2.36.dist-info/top_level.txt,sha256=8sgYrptpexkA_6_HyGvho26cVFH9kmtGvaK8tHbsGHk,27
24
+ ipulse_shared_core_ftredge-2.36.dist-info/RECORD,,