ipulse-shared-core-ftredge 2.32__py3-none-any.whl → 2.35__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.

@@ -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,
@@ -33,8 +33,8 @@ class FincCoreSubCategory(Enum):
33
33
  class FinCoreRecordsCategory(Enum):
34
34
  PRICE="pric"
35
35
  PRICE_SPOT= "pric.s"
36
- PRICE_OHCLVA="pric.ohlcva"
37
- PRICE_OHCLV="pric.ohlcv"
36
+ PRICE_OHLCVA="pric.ohlcva"
37
+ PRICE_OHLCV="pric.ohlcv"
38
38
  PRICE_OPEN="pric.o"
39
39
  PRICE_HIGH="pric.h"
40
40
  PRICE_LOW="pric.l"
@@ -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 = []
@@ -18,123 +26,124 @@ def create_bigquery_schema_from_json(json_schema):
18
26
 
19
27
 
20
28
  def update_check_with_schema_template(updates, schema, logger, dt_ts_to_str=True, check_max_length=True):
21
-
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]
89
-
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)
67
+ notice=create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
68
+ field_name,
69
+ f"Required field '{field_name}' is missing in the updates.")
98
70
 
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")
106
- elif isinstance(value, str):
80
+ return value.strftime("%Y-%m-%d"), None
81
+
82
+ if isinstance(value, str):
107
83
  try:
108
84
  datetime.datetime.strptime(value, "%Y-%m-%d")
109
85
  return value
110
86
  except ValueError:
111
- logger.warning(f"Invalid date format for field {field_name}, expected YYYY-MM-DD")
112
- return None
87
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
88
+ field_name,
89
+ f"Expected a DATE or YYYY-MM-DD str format but got {value} of type {type(value).__name__}.")
113
90
  else:
114
- logger.warning(f"Invalid date format for field {field_name}")
115
- return None
116
-
91
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
92
+ field_name,
93
+ f"Expected a DATE or YYYY-MM-DD str format but got {value} of type {type(value).__name__}.")
117
94
 
118
- def handle_timestamp_fields(field_name, value, logger):
95
+
96
+ def handle_timestamp_fields(field_name, value):
119
97
  """Handles timestamp fields, ensuring they are in the correct format."""
120
98
  if isinstance(value, datetime.datetime):
121
- return value.isoformat()
122
- elif isinstance(value, str):
99
+ return value.isoformat(), None
100
+
101
+ if isinstance(value, str):
123
102
  try:
124
103
  datetime.datetime.fromisoformat(value)
125
104
  return value
126
105
  except ValueError:
127
- logger.warning(f"Invalid timestamp format for field {field_name}, expected ISO format")
128
- return None
106
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
107
+ field_name,
108
+ f"Expected ISO format TIMESTAMP but got {value} of type {type(value).__name__}.")
129
109
  else:
130
- logger.warning(f"Invalid timestamp format for field {field_name}")
131
- return None
110
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
111
+ field_name,
112
+ f"Expected ISO format TIMESTAMP but got {value} of type {type(value).__name__}.")
132
113
 
133
- def check_and_truncate_length(field_name, value, max_length, logger):
114
+
115
+ def check_and_truncate_length(field_name, value, max_length):
134
116
  """Checks and truncates the length of string fields if they exceed the max length."""
135
117
  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
118
+ return value[:max_length], create_data_check_notice(NoticeSeverity.WARNING_ACTION_RECOMMENDED,
119
+ field_name,
120
+ f"Field exceeds max length: {len(value)}/{max_length}. Truncating.")
121
+
122
+ return value, None
123
+
139
124
 
140
125
 
126
+ def handle_type_conversion(field_type, field_name, value):
127
+ if field_type == "STRING" and not isinstance(value, str):
128
+ return str(value), create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
129
+ field_name,
130
+ f"Expected STRING but got {value} of type {type(value).__name__}.")
131
+
132
+ if field_type == "INT64" and not isinstance(value, int):
133
+ try:
134
+ return int(value), None
135
+ except ValueError:
136
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
137
+ field_name,
138
+ f"Expected INTEGER, but got {value} of type {type(value).__name__}.")
139
+ if field_type == "FLOAT64" and not isinstance(value, float):
140
+ try:
141
+ return float(value), None
142
+ except ValueError:
143
+ return None, create_data_check_notice(NoticeSeverity.WARNING_ACTION_REQUIRED,
144
+ field_name,
145
+ f"Expected FLOAT, but got {value} of type {type(value).__name__}.")
146
+ if field_type == "BOOL" and not isinstance(value, bool):
147
+ return bool(value), None
148
+
149
+ return value, None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ipulse_shared_core_ftredge
3
- Version: 2.32
3
+ Version: 2.35
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,10 +1,10 @@
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=VjwZb5Dhe5Yww6loesaETsN4dI3t17_KZ91JC0UcYaQ,6519
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
7
- ipulse_shared_core_ftredge/enums/enums_module_fincore.py,sha256=5-n7YuXPNQMKrZTrswf6Ni6HpwsiRFY8mt9Wc9_QYxc,1374
7
+ ipulse_shared_core_ftredge/enums/enums_module_fincore.py,sha256=MuqQg249clrWUOBb1S-iPsoOldN2_F3ohRQizbjhwG0,1374
8
8
  ipulse_shared_core_ftredge/enums/enums_modules.py,sha256=AyXUoNmR75DZLaEHi3snV6LngR25LeZRqzrLDaAupbY,1244
9
9
  ipulse_shared_core_ftredge/models/__init__.py,sha256=gE22Gzhil0RYQa7YLtdtT44_AsWqklcDfRtgLAQc1dI,200
10
10
  ipulse_shared_core_ftredge/models/audit_log_firestore.py,sha256=5AwO6NHuOncq65n400eqM8QPrS2EGGaP3Z_6l2rxdBE,261
@@ -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.32.dist-info/LICENCE,sha256=YBtYAXNqCCOo9Mr2hfkbSPAM9CeAr2j1VZBSwQTrNwE,1060
21
- ipulse_shared_core_ftredge-2.32.dist-info/METADATA,sha256=HPBzWocEMmgNTxaKVvsGCjtHv6Ei13rTFIBHYY610OQ,561
22
- ipulse_shared_core_ftredge-2.32.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
23
- ipulse_shared_core_ftredge-2.32.dist-info/top_level.txt,sha256=8sgYrptpexkA_6_HyGvho26cVFH9kmtGvaK8tHbsGHk,27
24
- ipulse_shared_core_ftredge-2.32.dist-info/RECORD,,
20
+ ipulse_shared_core_ftredge-2.35.dist-info/LICENCE,sha256=YBtYAXNqCCOo9Mr2hfkbSPAM9CeAr2j1VZBSwQTrNwE,1060
21
+ ipulse_shared_core_ftredge-2.35.dist-info/METADATA,sha256=ccTBc5Ut5az1JaepXI6ldPCZfdP8IA8Wq9XDyhWciq8,561
22
+ ipulse_shared_core_ftredge-2.35.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
23
+ ipulse_shared_core_ftredge-2.35.dist-info/top_level.txt,sha256=8sgYrptpexkA_6_HyGvho26cVFH9kmtGvaK8tHbsGHk,27
24
+ ipulse_shared_core_ftredge-2.35.dist-info/RECORD,,