ipulse-shared-core-ftredge 8.1.1__tar.gz → 10.1.1__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.

Files changed (34) hide show
  1. {ipulse_shared_core_ftredge-8.1.1/src/ipulse_shared_core_ftredge.egg-info → ipulse_shared_core_ftredge-10.1.1}/PKG-INFO +2 -2
  2. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/setup.py +2 -2
  3. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/models/base_api_response.py +12 -4
  4. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/models/subscription.py +44 -33
  5. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/models/user_profile.py +5 -5
  6. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/models/user_status.py +26 -16
  7. ipulse_shared_core_ftredge-10.1.1/src/ipulse_shared_core_ftredge/utils/custom_json_encoder.py +46 -0
  8. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1/src/ipulse_shared_core_ftredge.egg-info}/PKG-INFO +2 -2
  9. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge.egg-info/SOURCES.txt +1 -0
  10. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge.egg-info/requires.txt +1 -1
  11. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/LICENCE +0 -0
  12. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/README.md +0 -0
  13. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/pyproject.toml +0 -0
  14. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/setup.cfg +0 -0
  15. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/__init__.py +0 -0
  16. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/dependencies/__init__.py +0 -0
  17. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/dependencies/auth_firebase_token_validation.py +0 -0
  18. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/dependencies/auth_protected_router.py +0 -0
  19. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/dependencies/authz_for_apis.py +0 -0
  20. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/dependencies/firestore_client.py +0 -0
  21. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/models/__init__.py +0 -0
  22. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/models/base_data_model.py +0 -0
  23. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/models/organization_profile.py +0 -0
  24. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/models/user_auth.py +0 -0
  25. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/models/user_profile_update.py +0 -0
  26. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/services/__init__.py +0 -0
  27. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/services/base_firestore_service.py +0 -0
  28. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/services/base_service_exceptions.py +0 -0
  29. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/services/fastapiservicemon.py +0 -0
  30. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/services/servicemon.py +0 -0
  31. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/utils/__init__.py +0 -0
  32. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge/utils/json_encoder.py +0 -0
  33. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge.egg-info/dependency_links.txt +0 -0
  34. {ipulse_shared_core_ftredge-8.1.1 → ipulse_shared_core_ftredge-10.1.1}/src/ipulse_shared_core_ftredge.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ipulse_shared_core_ftredge
3
- Version: 8.1.1
3
+ Version: 10.1.1
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
@@ -13,7 +13,7 @@ Requires-Dist: pydantic[email]~=2.5
13
13
  Requires-Dist: python-dateutil~=2.8
14
14
  Requires-Dist: fastapi~=0.115.8
15
15
  Requires-Dist: pytest
16
- Requires-Dist: ipulse_shared_base_ftredge>=5.7.1
16
+ Requires-Dist: ipulse_shared_base_ftredge>=6.4.1
17
17
  Dynamic: author
18
18
  Dynamic: classifier
19
19
  Dynamic: home-page
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
3
3
 
4
4
  setup(
5
5
  name='ipulse_shared_core_ftredge',
6
- version='8.1.1',
6
+ version='10.1.1',
7
7
  package_dir={'': 'src'}, # Specify the source directory
8
8
  packages=find_packages(where='src'), # Look for packages in 'src'
9
9
  install_requires=[
@@ -12,7 +12,7 @@ setup(
12
12
  'python-dateutil~=2.8',
13
13
  'fastapi~=0.115.8',
14
14
  'pytest',
15
- 'ipulse_shared_base_ftredge>=5.7.1',
15
+ 'ipulse_shared_base_ftredge>=6.4.1',
16
16
  ],
17
17
  author='Russlan Ramdowar',
18
18
  description='Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.',
@@ -3,10 +3,7 @@ import datetime as dt
3
3
  import json
4
4
  from pydantic import BaseModel, ConfigDict
5
5
  from fastapi.responses import JSONResponse
6
- from ipulse_shared_core_ftredge.utils import CustomJSONEncoder
7
-
8
-
9
-
6
+ from ipulse_shared_core_ftredge.utils import CustomJSONEncoder
10
7
 
11
8
 
12
9
  T = TypeVar('T')
@@ -30,6 +27,17 @@ class PaginatedAPIResponse(BaseAPIResponse, Generic[T]):
30
27
 
31
28
  class CustomJSONResponse(JSONResponse):
32
29
  def render(self, content) -> bytes:
30
+ # Handle Pydantic models to exclude computed fields
31
+ if isinstance(content, dict) and "data" in content and hasattr(content["data"], "model_dump"):
32
+ # If content["data"] is a Pydantic model, use model_dump with exclude_unset=True
33
+ # and exclude_computed=True to prevent serialization of computed fields
34
+ content = dict(content) # Create a copy to avoid modifying the original
35
+ content["data"] = content["data"].model_dump(
36
+ exclude_unset=True,
37
+ exclude_computed=True
38
+ )
39
+
40
+ # Use the CustomJSONEncoder for serialization
33
41
  return json.dumps(
34
42
  content,
35
43
  ensure_ascii=False,
@@ -2,7 +2,7 @@ from datetime import datetime, timezone
2
2
  from dateutil.relativedelta import relativedelta
3
3
  import uuid
4
4
  from typing import Set, Optional, ClassVar, Dict, Any, List, Union
5
- from pydantic import Field, ConfigDict, computed_field
5
+ from pydantic import Field, ConfigDict
6
6
  from ipulse_shared_base_ftredge import Layer, Module, list_as_lower_strings, Subject, SubscriptionPlan, SubscriptionStatus
7
7
  from ipulse_shared_base_ftredge.enums.enums_iam import IAMUnitType
8
8
  from .base_data_model import BaseDataModel
@@ -21,7 +21,7 @@ class Subscription(BaseDataModel):
21
21
 
22
22
  model_config = ConfigDict(frozen=True, extra="forbid")
23
23
 
24
- VERSION: ClassVar[float] = 2.9 # Incremented version for new fields
24
+ VERSION: ClassVar[float] = 3.0 # Incremented version for direct fields instead of computed
25
25
  DOMAIN: ClassVar[str] = "_".join(list_as_lower_strings(Layer.PULSE_APP, Module.CORE.name, Subject.SUBSCRIPTION.name))
26
26
  OBJ_REF: ClassVar[str] = "subscription"
27
27
 
@@ -49,14 +49,11 @@ class Subscription(BaseDataModel):
49
49
  description="Version of the subscription plan"
50
50
  )
51
51
 
52
- @computed_field
53
- def plan_id(self) -> str:
54
- """
55
- Generate a plan identifier combining plan name and version.
56
- Format: {plan_name}_{plan_version}
57
- Example: "free_subscription_1"
58
- """
59
- return f"{self.plan_name.value}_{self.plan_version}"
52
+ # Direct field instead of computed
53
+ plan_id: str = Field(
54
+ ..., # Required field, no default
55
+ description="Combined plan identifier (plan_name_plan_version)"
56
+ )
60
57
 
61
58
  # Cycle duration fields
62
59
  cycle_start_date: datetime = Field(
@@ -64,7 +61,13 @@ class Subscription(BaseDataModel):
64
61
  description="Subscription Cycle Start Date"
65
62
  )
66
63
 
67
- # New fields for more flexible cycle management
64
+ # Direct field instead of computed
65
+ cycle_end_date: datetime = Field(
66
+ ..., # Required field, no default
67
+ description="Subscription Cycle End Date"
68
+ )
69
+
70
+ # Fields for cycle calculation
68
71
  validity_time_length: int = Field(
69
72
  ..., # Required field, no default
70
73
  description="Length of subscription validity period (e.g., 1, 3, 12)"
@@ -75,23 +78,6 @@ class Subscription(BaseDataModel):
75
78
  description="Unit of subscription validity ('minute', 'hour', 'day', 'week', 'month', 'year')"
76
79
  )
77
80
 
78
- # Computed cycle_end_date based on start date and validity
79
- @computed_field
80
- def cycle_end_date(self) -> datetime:
81
- """Calculate the end date based on start date and validity period."""
82
- if self.validity_time_unit == "minute":
83
- return self.cycle_start_date + relativedelta(minutes=self.validity_time_length)
84
- elif self.validity_time_unit == "hour":
85
- return self.cycle_start_date + relativedelta(hours=self.validity_time_length)
86
- elif self.validity_time_unit == "day":
87
- return self.cycle_start_date + relativedelta(days=self.validity_time_length)
88
- elif self.validity_time_unit == "week":
89
- return self.cycle_start_date + relativedelta(weeks=self.validity_time_length)
90
- elif self.validity_time_unit == "year":
91
- return self.cycle_start_date + relativedelta(years=self.validity_time_length)
92
- else: # Default to months
93
- return self.cycle_start_date + relativedelta(months=self.validity_time_length)
94
-
95
81
  # Renewal and status fields
96
82
  auto_renew: bool = Field(
97
83
  ..., # Required field, no default
@@ -103,9 +89,8 @@ class Subscription(BaseDataModel):
103
89
  description="Subscription Status (active, trial, pending_confirmation, etc.)"
104
90
  )
105
91
 
106
- # New fields for enhanced subscription management
107
- # Update the type definition to use string keys for IAMUnitType
108
- iam_domain_permissions: Dict[str, Dict[str, List[str]]] = Field(
92
+ # IAM permissions structure
93
+ default_iam_domain_permissions: Dict[str, Dict[str, List[str]]] = Field(
109
94
  ..., # Required field, no default
110
95
  description="IAM domain permissions granted by this subscription (domain -> IAM unit type -> list of unit references)"
111
96
  )
@@ -125,7 +110,7 @@ class Subscription(BaseDataModel):
125
110
  description="Reference to payment transaction"
126
111
  )
127
112
 
128
- # New fields moved from metadata to direct attributes
113
+ # Credit management fields
129
114
  subscription_based_insight_credits_per_update: int = Field(
130
115
  default=0,
131
116
  description="Number of insight credits to add on each update"
@@ -157,6 +142,23 @@ class Subscription(BaseDataModel):
157
142
  description="Additional metadata for the subscription"
158
143
  )
159
144
 
145
+ # Helper method to calculate cycle end date
146
+ @classmethod
147
+ def calculate_cycle_end_date(cls, start_date: datetime, validity_length: int, validity_unit: str) -> datetime:
148
+ """Calculate the end date based on start date and validity period."""
149
+ if validity_unit == "minute":
150
+ return start_date + relativedelta(minutes=validity_length)
151
+ elif validity_unit == "hour":
152
+ return start_date + relativedelta(hours=validity_length)
153
+ elif validity_unit == "day":
154
+ return start_date + relativedelta(days=validity_length)
155
+ elif validity_unit == "week":
156
+ return start_date + relativedelta(weeks=validity_length)
157
+ elif validity_unit == "year":
158
+ return start_date + relativedelta(years=validity_length)
159
+ else: # Default to months
160
+ return start_date + relativedelta(months=validity_length)
161
+
160
162
  # Methods for subscription management
161
163
  def is_active(self) -> bool:
162
164
  """Check if the subscription is currently active."""
@@ -176,4 +178,13 @@ class Subscription(BaseDataModel):
176
178
  now = datetime.now(timezone.utc)
177
179
  if now > self.cycle_end_date:
178
180
  return 0
179
- return (self.cycle_end_date - now).days
181
+
182
+ # Get time difference
183
+ time_diff = self.cycle_end_date - now
184
+
185
+ # If there's any time remaining but less than a day, return 1
186
+ if time_diff.days == 0 and time_diff.seconds > 0:
187
+ return 1
188
+
189
+ # Otherwise return the number of complete days
190
+ return time_diff.days
@@ -16,7 +16,7 @@ class UserProfile(BaseDataModel):
16
16
  model_config = ConfigDict(frozen=False, extra="forbid") # Allow field modification
17
17
 
18
18
  # Class constants
19
- VERSION: ClassVar[float] = 5.0 # Incremented version for primary_user_type addition
19
+ VERSION: ClassVar[float] = 5.0 # Incremented version for primary_usertype addition
20
20
  DOMAIN: ClassVar[str] = "_".join(list_as_lower_strings(Layer.PULSE_APP, Module.CORE.name, Subject.USER.name))
21
21
  OBJ_REF: ClassVar[str] = "userprofile"
22
22
 
@@ -36,14 +36,14 @@ class UserProfile(BaseDataModel):
36
36
  description="User UID from Firebase Auth"
37
37
  )
38
38
 
39
- # Added primary_user_type field for main role categorization
40
- primary_user_type: str = Field(
39
+ # Added primary_usertype field for main role categorization
40
+ primary_usertype: str = Field(
41
41
  ...,
42
42
  description="Primary user type (e.g., customer, internal, admin, superadmin)"
43
43
  )
44
44
 
45
- # Renamed user_types to secondary_user_types
46
- secondary_user_types: List[str] = Field(
45
+ # Renamed user_types to secondary_usertypes
46
+ secondary_usertypes: List[str] = Field(
47
47
  default_factory=list,
48
48
  description="List of secondary user types"
49
49
  )
@@ -47,7 +47,7 @@ class UserStatus(BaseDataModel):
47
47
  model_config = ConfigDict(frozen=False, extra="forbid")
48
48
 
49
49
  # Class constants
50
- VERSION: ClassVar[float] = 5.0 # Incremented version for primary_user_type addition
50
+ VERSION: ClassVar[float] = 5.1 # Incremented version for removing computed fields
51
51
  DOMAIN: ClassVar[str] = "_".join(list_as_lower_strings(Layer.PULSE_APP, Module.CORE.name, Subject.USER.name))
52
52
  OBJ_REF: ClassVar[str] = "userstatus"
53
53
 
@@ -68,14 +68,14 @@ class UserStatus(BaseDataModel):
68
68
  description="User UID from Firebase Auth"
69
69
  )
70
70
 
71
- # Added primary_user_type field for main role categorization
72
- primary_user_type: str = Field(
71
+ # Added primary_usertype field for main role categorization
72
+ primary_usertype: str = Field(
73
73
  ...,
74
74
  description="Primary user type (e.g., customer, internal, admin, superadmin)"
75
75
  )
76
76
 
77
- # Renamed user_types to secondary_user_types
78
- secondary_user_types: List[str] = Field(
77
+ # Renamed user_types to secondary_usertypes
78
+ secondary_usertypes: List[str] = Field(
79
79
  default_factory=list,
80
80
  description="List of secondary user types/roles"
81
81
  )
@@ -321,7 +321,7 @@ class UserStatus(BaseDataModel):
321
321
  """
322
322
  added_count = 0
323
323
 
324
- for domain, permissions_by_type in subscription.iam_domain_permissions.items():
324
+ for domain, permissions_by_type in subscription.default_iam_domain_permissions.items():
325
325
  for iam_unit_type_str, iam_unit_refs in permissions_by_type.items():
326
326
  # Convert string to enum if needed for internal processing
327
327
  try:
@@ -353,14 +353,14 @@ class UserStatus(BaseDataModel):
353
353
  """
354
354
  return self.update_iam_unit_refs_from_subscription(subscription)
355
355
 
356
- @computed_field
356
+ # Method instead of computed field
357
357
  def is_subscription_active(self) -> bool:
358
358
  """Check if the user has an active subscription."""
359
359
  if self.active_subscription:
360
360
  return self.active_subscription.is_active()
361
361
  return False
362
362
 
363
- @computed_field
363
+ # Method instead of computed field
364
364
  def subscription_expires_in_days(self) -> Optional[int]:
365
365
  """Get days until subscription expiration."""
366
366
  if self.active_subscription and self.active_subscription.is_active():
@@ -464,21 +464,31 @@ class UserStatus(BaseDataModel):
464
464
  if plan_version is None or validity_time_length is None or validity_time_unit is None:
465
465
  return
466
466
 
467
- # Create temporary subscription object with direct attributes instead of metadata
467
+ # Calculate directly assigned fields
468
+ plan_id = f"{plan_name_str}_{plan_version}"
469
+ cycle_start_date = datetime.now(timezone.utc)
470
+ cycle_end_date = Subscription.calculate_cycle_end_date(
471
+ cycle_start_date,
472
+ validity_time_length,
473
+ validity_time_unit
474
+ )
475
+
476
+ # Create subscription object with direct fields instead of computed
468
477
  subscription = Subscription(
469
478
  plan_name=plan_name,
470
479
  plan_version=plan_version,
471
- cycle_start_date=datetime.now(timezone.utc),
480
+ plan_id=plan_id,
481
+ cycle_start_date=cycle_start_date,
482
+ cycle_end_date=cycle_end_date,
472
483
  validity_time_length=validity_time_length,
473
484
  validity_time_unit=validity_time_unit,
474
- auto_renew=plan_data.get("plan_auto_renewal", False), # Default only for boolean fields
485
+ auto_renew=plan_data.get("plan_auto_renewal", False),
475
486
  status=SubscriptionStatus.ACTIVE,
476
- iam_domain_permissions=iam_domain_permissions,
487
+ default_iam_domain_permissions=iam_domain_permissions,
477
488
  fallback_plan_id=plan_data.get("fallback_plan_id_if_current_plan_expired"),
478
489
  price_paid_usd=plan_data.get("plan_per_cycle_price_usd") or 0.0,
479
490
  created_by=source,
480
491
  updated_by=source,
481
- # Direct attributes for credit-related fields
482
492
  subscription_based_insight_credits_per_update=plan_data.get("subscription_based_insight_credits_per_update") or 0,
483
493
  subscription_based_insight_credits_update_freq_h=plan_data.get("subscription_based_insight_credits_update_freq_h") or 24,
484
494
  extra_insight_credits_per_cycle=plan_data.get("extra_insight_credits_per_cycle") or 0,
@@ -491,14 +501,14 @@ class UserStatus(BaseDataModel):
491
501
 
492
502
  @staticmethod
493
503
  def fetch_user_status_defaults(firestore_client,
494
- primary_user_type: str,
504
+ primary_usertype: str,
495
505
  collection: str = "papp_core_configs_user") -> Dict[str, Any]:
496
506
  """
497
507
  Fetch user status defaults from Firestore.
498
508
 
499
509
  Args:
500
510
  firestore_client: Initialized Firestore client
501
- primary_user_type: Primary type of user (customer, internal, admin, etc)
511
+ primary_usertype: Primary type of user (customer, internal, admin, etc)
502
512
  collection: Collection name for user status defaults
503
513
 
504
514
  Returns:
@@ -521,7 +531,7 @@ class UserStatus(BaseDataModel):
521
531
 
522
532
  # Look for defaults with format "{user_type}_defaults_{version}"
523
533
  for key in data.keys():
524
- if key.startswith(f"{primary_user_type}_defaults_"):
534
+ if key.startswith(f"{primary_usertype}_defaults_"):
525
535
  try:
526
536
  version = int(key.split("_")[-1])
527
537
  if version > latest_version:
@@ -0,0 +1,46 @@
1
+ import json
2
+ import datetime
3
+ from typing import Any
4
+ from enum import Enum
5
+ from uuid import UUID
6
+ from decimal import Decimal
7
+ from pydantic import BaseModel
8
+
9
+ class CustomJSONEncoder(json.JSONEncoder):
10
+ """Custom JSON encoder to handle special types like datetimes, UUIDs, and Pydantic models."""
11
+
12
+ def default(self, obj: Any) -> Any:
13
+ # Handle datetime objects
14
+ if isinstance(obj, datetime.datetime):
15
+ return obj.isoformat()
16
+
17
+ # Handle date objects
18
+ elif isinstance(obj, datetime.date):
19
+ return obj.isoformat()
20
+
21
+ # Handle time objects
22
+ elif isinstance(obj, datetime.time):
23
+ return obj.isoformat()
24
+
25
+ # Handle UUID objects
26
+ elif isinstance(obj, UUID):
27
+ return str(obj)
28
+
29
+ # Handle Decimal objects
30
+ elif isinstance(obj, Decimal):
31
+ return float(obj)
32
+
33
+ # Handle Enum objects
34
+ elif isinstance(obj, Enum):
35
+ return obj.value
36
+
37
+ # Handle Pydantic models - exclude computed fields
38
+ elif isinstance(obj, BaseModel):
39
+ return obj.model_dump(exclude_computed=True)
40
+
41
+ # Handle sets by converting to sorted lists for consistent output
42
+ elif isinstance(obj, set):
43
+ return sorted(list(obj))
44
+
45
+ # For everything else, use the default encoder
46
+ return super().default(obj)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ipulse_shared_core_ftredge
3
- Version: 8.1.1
3
+ Version: 10.1.1
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
@@ -13,7 +13,7 @@ Requires-Dist: pydantic[email]~=2.5
13
13
  Requires-Dist: python-dateutil~=2.8
14
14
  Requires-Dist: fastapi~=0.115.8
15
15
  Requires-Dist: pytest
16
- Requires-Dist: ipulse_shared_base_ftredge>=5.7.1
16
+ Requires-Dist: ipulse_shared_base_ftredge>=6.4.1
17
17
  Dynamic: author
18
18
  Dynamic: classifier
19
19
  Dynamic: home-page
@@ -28,4 +28,5 @@ src/ipulse_shared_core_ftredge/services/base_service_exceptions.py
28
28
  src/ipulse_shared_core_ftredge/services/fastapiservicemon.py
29
29
  src/ipulse_shared_core_ftredge/services/servicemon.py
30
30
  src/ipulse_shared_core_ftredge/utils/__init__.py
31
+ src/ipulse_shared_core_ftredge/utils/custom_json_encoder.py
31
32
  src/ipulse_shared_core_ftredge/utils/json_encoder.py
@@ -2,4 +2,4 @@ pydantic[email]~=2.5
2
2
  python-dateutil~=2.8
3
3
  fastapi~=0.115.8
4
4
  pytest
5
- ipulse_shared_base_ftredge>=5.7.1
5
+ ipulse_shared_base_ftredge>=6.4.1