ipulse-shared-core-ftredge 6.8.1__tar.gz → 7.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 (35) hide show
  1. {ipulse_shared_core_ftredge-6.8.1/src/ipulse_shared_core_ftredge.egg-info → ipulse_shared_core_ftredge-7.1.1}/PKG-INFO +9 -3
  2. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/setup.py +9 -3
  3. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/__init__.py +3 -2
  4. ipulse_shared_core_ftredge-7.1.1/src/ipulse_shared_core_ftredge/dependencies/__init__.py +1 -0
  5. ipulse_shared_core_ftredge-6.8.1/src/ipulse_shared_core_ftredge/dependencies/token_validation.py → ipulse_shared_core_ftredge-7.1.1/src/ipulse_shared_core_ftredge/dependencies/auth_firebase_token_validation.py +5 -5
  6. ipulse_shared_core_ftredge-6.8.1/src/ipulse_shared_core_ftredge/dependencies/auth_router.py → ipulse_shared_core_ftredge-7.1.1/src/ipulse_shared_core_ftredge/dependencies/auth_protected_router.py +1 -1
  7. ipulse_shared_core_ftredge-6.8.1/src/ipulse_shared_core_ftredge/dependencies/authorization_api.py → ipulse_shared_core_ftredge-7.1.1/src/ipulse_shared_core_ftredge/dependencies/authz_for_apis.py +11 -6
  8. ipulse_shared_core_ftredge-6.8.1/src/ipulse_shared_core_ftredge/dependencies/database.py → ipulse_shared_core_ftredge-7.1.1/src/ipulse_shared_core_ftredge/dependencies/firestore_client.py +5 -3
  9. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/models/__init__.py +1 -1
  10. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/models/base_api_response.py +1 -1
  11. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/services/__init__.py +1 -1
  12. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/services/base_firestore_service.py +16 -16
  13. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1/src/ipulse_shared_core_ftredge.egg-info}/PKG-INFO +9 -3
  14. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge.egg-info/SOURCES.txt +5 -5
  15. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge.egg-info/requires.txt +2 -2
  16. ipulse_shared_core_ftredge-6.8.1/src/ipulse_shared_core_ftredge/dependencies/__init__.py +0 -1
  17. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/LICENCE +0 -0
  18. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/README.md +0 -0
  19. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/pyproject.toml +0 -0
  20. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/setup.cfg +0 -0
  21. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/models/base_data_model.py +0 -0
  22. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/models/organization_profile.py +0 -0
  23. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/models/resource_catalog_item.py +0 -0
  24. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/models/subscription.py +0 -0
  25. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/models/user_auth.py +0 -0
  26. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/models/user_profile.py +0 -0
  27. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/models/user_profile_update.py +0 -0
  28. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/models/user_status.py +0 -0
  29. /ipulse_shared_core_ftredge-6.8.1/src/ipulse_shared_core_ftredge/services/base_exceptions.py → /ipulse_shared_core_ftredge-7.1.1/src/ipulse_shared_core_ftredge/services/base_service_exceptions.py +0 -0
  30. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/services/fastapiservicemon.py +0 -0
  31. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/services/servicemon.py +0 -0
  32. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/utils/__init__.py +0 -0
  33. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge/utils/json_encoder.py +0 -0
  34. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge.egg-info/dependency_links.txt +0 -0
  35. {ipulse_shared_core_ftredge-6.8.1 → ipulse_shared_core_ftredge-7.1.1}/src/ipulse_shared_core_ftredge.egg-info/top_level.txt +0 -0
@@ -1,16 +1,22 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ipulse_shared_core_ftredge
3
- Version: 6.8.1
3
+ Version: 7.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
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.11
7
11
  License-File: LICENCE
8
12
  Requires-Dist: pydantic[email]~=2.5
9
13
  Requires-Dist: python-dateutil~=2.8
10
14
  Requires-Dist: fastapi~=0.115.8
11
- Requires-Dist: pytest~=7.1
12
- Requires-Dist: ipulse_shared_base_ftredge>=5.6.1
15
+ Requires-Dist: pytest
16
+ Requires-Dist: ipulse_shared_base_ftredge>=5.7.1
13
17
  Dynamic: author
18
+ Dynamic: classifier
14
19
  Dynamic: home-page
15
20
  Dynamic: requires-dist
21
+ Dynamic: requires-python
16
22
  Dynamic: summary
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
3
3
 
4
4
  setup(
5
5
  name='ipulse_shared_core_ftredge',
6
- version='6.8.1',
6
+ version='7.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=[
@@ -11,11 +11,17 @@ setup(
11
11
  'pydantic[email]~=2.5',
12
12
  'python-dateutil~=2.8',
13
13
  'fastapi~=0.115.8',
14
- 'pytest~=7.1',
15
- 'ipulse_shared_base_ftredge>=5.6.1',
14
+ 'pytest',
15
+ 'ipulse_shared_base_ftredge>=5.7.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.',
19
19
  url='https://github.com/TheFutureEdge/ipulse_shared_core',
20
20
 
21
+ classifiers=[
22
+ 'Programming Language :: Python :: 3',
23
+ 'License :: OSI Approved :: MIT License',
24
+ 'Operating System :: OS Independent',
25
+ ],
26
+ python_requires='>=3.11',
21
27
  )
@@ -1,11 +1,12 @@
1
1
  # pylint: disable=missing-module-docstring
2
2
  from .models import ( UserAuth, UserProfile,Subscription,
3
3
  UserStatus, UserProfileUpdate,
4
- OrganizationProfile, BaseAPIResponse, CustomJSONResponse )
4
+ OrganizationProfile, BaseAPIResponse,
5
+ CustomJSONResponse )
5
6
 
6
7
 
7
8
 
8
9
  from .services import (BaseFirestoreService,BaseServiceException, ResourceNotFoundError, AuthorizationError,
9
10
  ValidationError)
10
11
 
11
- from .utils import (CustomJSONEncoder)
12
+ from .utils import (CustomJSONEncoder)
@@ -0,0 +1 @@
1
+ # from .auth_firebase_token_validation import verify_firebase_token
@@ -22,7 +22,7 @@ async def verify_firebase_token(
22
22
  """
23
23
  # Get token from either x-forwarded-authorization or authorization header
24
24
  token = x_forwarded_authorization or authorization
25
-
25
+
26
26
  if not token:
27
27
  raise HTTPException(
28
28
  status_code=401,
@@ -34,7 +34,7 @@ async def verify_firebase_token(
34
34
  token = token.replace("Bearer ", "")
35
35
  # Verify the token
36
36
  decoded_token = auth.verify_id_token(token)
37
-
37
+
38
38
  # Create AuthenticatedUser instance
39
39
  user = AuthenticatedUser(
40
40
  uid=decoded_token.get('uid'),
@@ -42,17 +42,17 @@ async def verify_firebase_token(
42
42
  email_verified=decoded_token.get('email_verified', False),
43
43
  usertypes=decoded_token.get('usertypes', [])
44
44
  )
45
-
45
+
46
46
  # Store user in request state for use in other parts of the application
47
47
  request.state.user = decoded_token
48
-
48
+
49
49
  return user
50
50
 
51
51
  except Exception as e:
52
52
  raise HTTPException(
53
53
  status_code=401,
54
54
  detail=f"Invalid token: {str(e)}"
55
- )
55
+ ) from e
56
56
 
57
57
  # Type alias for dependency injection
58
58
  AuthUser = Annotated[AuthenticatedUser, Depends(verify_firebase_token)]
@@ -1,6 +1,6 @@
1
1
  from typing import Callable, Optional, List
2
2
  from fastapi import APIRouter, Depends
3
- from .token_validation import verify_firebase_token
3
+ from .auth_firebase_token_validation import verify_firebase_token
4
4
 
5
5
  def create_protected_router(
6
6
  *,
@@ -126,27 +126,32 @@ def _validate_resource_fields(fields: Dict[str, Any]) -> List[str]:
126
126
  async def extract_request_fields(request: Request) -> Optional[List[str]]:
127
127
  """
128
128
  Extract fields from request body for both PATCH and POST methods.
129
+ For GET and DELETE methods, return None as they typically don't have a body.
129
130
  """
131
+ # Skip body extraction for GET and DELETE requests
132
+ if request.method.upper() in ["GET", "DELETE", "HEAD", "OPTIONS"]:
133
+ return None
134
+
130
135
  try:
131
136
  body = await request.json()
132
137
  if isinstance(body, dict):
133
- if request.method == "PATCH":
138
+ if request.method.upper() == "PATCH":
134
139
  return _validate_resource_fields(body)
135
- if request.method == "POST":
140
+ if request.method.upper() == "POST":
136
141
  # For POST, we want to include all fields being set
137
142
  return list(body.keys())
138
143
  elif hasattr(body, 'model_dump'):
139
144
  data = body.model_dump(exclude_unset=True)
140
- if request.method == "PATCH":
145
+ if request.method.upper() == "PATCH":
141
146
  return _validate_resource_fields(data)
142
- if request.method == "POST":
147
+ if request.method.upper() == "POST":
143
148
  return list(data.keys())
144
149
 
145
150
  return None
146
151
 
147
152
  except Exception as e:
148
- logger.error(f"Error extracting fields from request body: {str(e)}")
149
- return None
153
+ logger.warning(f"Could not extract fields from request body: {str(e)}")
154
+ return None # Return None instead of raising an error
150
155
 
151
156
  async def authorizeAPIRequest(
152
157
  request: Request,
@@ -1,8 +1,9 @@
1
1
  from typing import Annotated
2
2
  from fastapi import Depends
3
- from google.cloud import firestore
4
3
  from functools import lru_cache
5
4
  import logging
5
+ from google.cloud import firestore
6
+
6
7
 
7
8
  logger = logging.getLogger(__name__)
8
9
 
@@ -10,10 +11,11 @@ logger = logging.getLogger(__name__)
10
11
  def get_db() -> firestore.Client:
11
12
  """
12
13
  Dependency function to inject the Firestore client.
13
- Each service implementing this should override this function with their own Firebase initialization.
14
+ !!! THIS IS JUST AN EXAMPLE !!!
15
+ !!! Each service implementing this should override this function with their own Firebase initialization. !!!
14
16
  """
15
17
  logger.info("Base get_db dependency called - this should be overridden by the implementing service")
16
18
  return firestore.Client()
17
19
 
18
20
  # Base type for dependency injection that services will implement
19
- FirestoreDB = Annotated[firestore.Client, Depends(get_db)]
21
+ FirestoreDBClient = Annotated[firestore.Client, Depends(get_db)]
@@ -4,7 +4,7 @@ from .user_status import UserStatus
4
4
  from .user_profile_update import UserProfileUpdate
5
5
  from .user_auth import UserAuth
6
6
  from .organization_profile import OrganizationProfile
7
- from .base_api_response import BaseAPIResponse, CustomJSONResponse
7
+ from .base_api_response import BaseAPIResponse , CustomJSONResponse
8
8
 
9
9
 
10
10
 
@@ -3,7 +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 import CustomJSONEncoder
6
+ from ipulse_shared_core_ftredge.utils import CustomJSONEncoder
7
7
 
8
8
 
9
9
 
@@ -1,6 +1,6 @@
1
1
  from .base_firestore_service import BaseFirestoreService
2
2
 
3
- from .base_exceptions import (BaseServiceException, ResourceNotFoundError, AuthorizationError,
3
+ from .base_service_exceptions import (BaseServiceException, ResourceNotFoundError, AuthorizationError,
4
4
  ValidationError ,ServiceError)
5
5
  from .servicemon import Servicemon
6
6
  from .fastapiservicemon import FastAPIServiceMon
@@ -4,13 +4,13 @@ import logging
4
4
  from datetime import datetime, timezone
5
5
  from pydantic import BaseModel
6
6
  from google.cloud import firestore
7
- from .base_exceptions import ResourceNotFoundError, ValidationError, ServiceError
7
+ from .base_service_exceptions import ResourceNotFoundError, ValidationError, ServiceError
8
8
 
9
9
  T = TypeVar('T', bound=BaseModel)
10
10
 
11
11
  class BaseFirestoreService(Generic[T]):
12
12
  """Base class for Firestore services with common CRUD operations"""
13
-
13
+
14
14
  def __init__(self, db: firestore.Client, collection_name: str, resource_type: str, logger: logging.Logger):
15
15
  self.db = db
16
16
  self.collection_name = collection_name
@@ -22,7 +22,7 @@ class BaseFirestoreService(Generic[T]):
22
22
  try:
23
23
  current_time = datetime.now(timezone.utc)
24
24
  doc_data = data.model_dump(mode='json')
25
-
25
+
26
26
  # Add audit fields
27
27
  doc_data.update({
28
28
  'creat_date': current_time.isoformat(),
@@ -33,7 +33,7 @@ class BaseFirestoreService(Generic[T]):
33
33
 
34
34
  doc_ref = self.db.collection(self.collection_name).document(doc_id)
35
35
  doc_ref.set(doc_data)
36
-
36
+
37
37
  self.logger.info(f"Created {self.resource_type}: {doc_id}")
38
38
  return doc_data
39
39
 
@@ -61,7 +61,7 @@ class BaseFirestoreService(Generic[T]):
61
61
  'updt_date': current_time.isoformat(),
62
62
  'updt_by_user': creator_uid
63
63
  })
64
-
64
+
65
65
  doc_ref = self.db.collection(self.collection_name).document(doc_data.get('id'))
66
66
  batch.set(doc_ref, doc_data)
67
67
  created_docs.append(doc_data)
@@ -83,39 +83,39 @@ class BaseFirestoreService(Generic[T]):
83
83
  """Get a document by ID with standardized error handling"""
84
84
  doc_ref = self.db.collection(self.collection_name).document(doc_id)
85
85
  doc = doc_ref.get()
86
-
86
+
87
87
  if not doc.exists:
88
88
  raise ResourceNotFoundError(
89
89
  resource_type=self.resource_type,
90
90
  resource_id=doc_id,
91
91
  additional_info={"collection": self.collection_name}
92
92
  )
93
-
93
+
94
94
  return doc.to_dict()
95
95
 
96
96
  async def update_document(self, doc_id: str, update_data: Dict[str, Any], updater_uid: str) -> Dict[str, Any]:
97
97
  """Standard update method with validation and audit fields"""
98
98
  try:
99
99
  doc_ref = self.db.collection(self.collection_name).document(doc_id)
100
-
100
+
101
101
  if not doc_ref.get().exists:
102
102
  raise ResourceNotFoundError(
103
103
  resource_type=self.resource_type,
104
104
  resource_id=doc_id,
105
105
  additional_info={"collection": self.collection_name}
106
106
  )
107
-
107
+
108
108
  valid_fields = self._validate_update_fields(update_data)
109
-
109
+
110
110
  # Add audit fields
111
111
  valid_fields.update({
112
112
  'updt_date': datetime.now(timezone.utc).isoformat(),
113
113
  'updt_by_user': updater_uid
114
114
  })
115
-
115
+
116
116
  doc_ref.update(valid_fields)
117
117
  return doc_ref.get().to_dict()
118
-
118
+
119
119
  except (ResourceNotFoundError, ValidationError):
120
120
  raise
121
121
  except Exception as e:
@@ -136,7 +136,7 @@ class BaseFirestoreService(Generic[T]):
136
136
  resource_type=self.resource_type,
137
137
  resource_id=doc_id
138
138
  )
139
-
139
+
140
140
  doc_ref.delete()
141
141
  self.logger.info(f"Deleted {self.resource_type}: {doc_id}")
142
142
 
@@ -155,17 +155,17 @@ class BaseFirestoreService(Generic[T]):
155
155
  """Centralized update fields validation"""
156
156
  if not isinstance(update_data, dict):
157
157
  update_data = update_data.model_dump(exclude_unset=True)
158
-
158
+
159
159
  valid_fields = {
160
160
  k: v for k, v in update_data.items()
161
161
  if v is not None and not (isinstance(v, (list, dict, set)) and len(v) == 0)
162
162
  }
163
-
163
+
164
164
  if not valid_fields:
165
165
  raise ValidationError(
166
166
  resource_type=self.resource_type,
167
167
  detail="No valid fields to update",
168
168
  resource_id=None
169
169
  )
170
-
170
+
171
171
  return valid_fields
@@ -1,16 +1,22 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ipulse_shared_core_ftredge
3
- Version: 6.8.1
3
+ Version: 7.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
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.11
7
11
  License-File: LICENCE
8
12
  Requires-Dist: pydantic[email]~=2.5
9
13
  Requires-Dist: python-dateutil~=2.8
10
14
  Requires-Dist: fastapi~=0.115.8
11
- Requires-Dist: pytest~=7.1
12
- Requires-Dist: ipulse_shared_base_ftredge>=5.6.1
15
+ Requires-Dist: pytest
16
+ Requires-Dist: ipulse_shared_base_ftredge>=5.7.1
13
17
  Dynamic: author
18
+ Dynamic: classifier
14
19
  Dynamic: home-page
15
20
  Dynamic: requires-dist
21
+ Dynamic: requires-python
16
22
  Dynamic: summary
@@ -9,10 +9,10 @@ src/ipulse_shared_core_ftredge.egg-info/dependency_links.txt
9
9
  src/ipulse_shared_core_ftredge.egg-info/requires.txt
10
10
  src/ipulse_shared_core_ftredge.egg-info/top_level.txt
11
11
  src/ipulse_shared_core_ftredge/dependencies/__init__.py
12
- src/ipulse_shared_core_ftredge/dependencies/auth_router.py
13
- src/ipulse_shared_core_ftredge/dependencies/authorization_api.py
14
- src/ipulse_shared_core_ftredge/dependencies/database.py
15
- src/ipulse_shared_core_ftredge/dependencies/token_validation.py
12
+ src/ipulse_shared_core_ftredge/dependencies/auth_firebase_token_validation.py
13
+ src/ipulse_shared_core_ftredge/dependencies/auth_protected_router.py
14
+ src/ipulse_shared_core_ftredge/dependencies/authz_for_apis.py
15
+ src/ipulse_shared_core_ftredge/dependencies/firestore_client.py
16
16
  src/ipulse_shared_core_ftredge/models/__init__.py
17
17
  src/ipulse_shared_core_ftredge/models/base_api_response.py
18
18
  src/ipulse_shared_core_ftredge/models/base_data_model.py
@@ -24,8 +24,8 @@ src/ipulse_shared_core_ftredge/models/user_profile.py
24
24
  src/ipulse_shared_core_ftredge/models/user_profile_update.py
25
25
  src/ipulse_shared_core_ftredge/models/user_status.py
26
26
  src/ipulse_shared_core_ftredge/services/__init__.py
27
- src/ipulse_shared_core_ftredge/services/base_exceptions.py
28
27
  src/ipulse_shared_core_ftredge/services/base_firestore_service.py
28
+ src/ipulse_shared_core_ftredge/services/base_service_exceptions.py
29
29
  src/ipulse_shared_core_ftredge/services/fastapiservicemon.py
30
30
  src/ipulse_shared_core_ftredge/services/servicemon.py
31
31
  src/ipulse_shared_core_ftredge/utils/__init__.py
@@ -1,5 +1,5 @@
1
1
  pydantic[email]~=2.5
2
2
  python-dateutil~=2.8
3
3
  fastapi~=0.115.8
4
- pytest~=7.1
5
- ipulse_shared_base_ftredge>=5.6.1
4
+ pytest
5
+ ipulse_shared_base_ftredge>=5.7.1
@@ -1 +0,0 @@
1
- from .token_validation import verify_firebase_token