sharedkernel 2.6.3__tar.gz → 2.7.0__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.
Files changed (54) hide show
  1. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/PKG-INFO +6 -2
  2. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/README.md +4 -0
  3. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/setup.py +3 -2
  4. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/config.py +2 -1
  5. sharedkernel-2.7.0/sharedkernel/database/cache/__init__.py +0 -0
  6. sharedkernel-2.7.0/sharedkernel/database/cache/cache_repository.py +37 -0
  7. sharedkernel-2.7.0/sharedkernel/database/cache/redis_generic_cache.py +88 -0
  8. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/ip_session_service.py +19 -18
  9. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/logger/logger_service.py +3 -2
  10. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel.egg-info/PKG-INFO +6 -2
  11. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel.egg-info/SOURCES.txt +3 -0
  12. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel.egg-info/requires.txt +1 -1
  13. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/setup.cfg +0 -0
  14. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/common.py +0 -0
  15. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/data_format_converter.py +0 -0
  16. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/database/__init__.py +0 -0
  17. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/database/audit_model.py +0 -0
  18. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/database/distributed_cache.py +0 -0
  19. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/database/mongo_generic_audit_repository.py +0 -0
  20. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/database/mongo_generic_repository.py +0 -0
  21. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/database/mongo_health_checker.py +0 -0
  22. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/database/pagination_response_dto.py +0 -0
  23. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/date_converter.py +0 -0
  24. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/diff_utils.py +0 -0
  25. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/enum/__init__.py +0 -0
  26. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/enum/error_code.py +0 -0
  27. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/enum/redis_mode_enum.py +0 -0
  28. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/enum/sort_order.py +0 -0
  29. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/exception/__init__.py +0 -0
  30. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/exception/exception.py +0 -0
  31. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/exception/exception_handlers.py +0 -0
  32. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/file_validation.py +0 -0
  33. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/jwt_service.py +0 -0
  34. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/logger/log_decorator.py +0 -0
  35. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/logger/log_dto.py +0 -0
  36. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/logger/log_enums.py +0 -0
  37. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/logger/log_info.py +0 -0
  38. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/logger/log_middlewares.py +0 -0
  39. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/multipart_upload.py +0 -0
  40. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/normalizer/__init__.py +0 -0
  41. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/normalizer/number_normalizer.py +0 -0
  42. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/normalizer/phone_number_normalizer.py +0 -0
  43. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/normalizer/string_normalizer.py +0 -0
  44. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/objects/__init__.py +0 -0
  45. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/objects/base_document.py +0 -0
  46. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/objects/json_string_model.py +0 -0
  47. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/objects/jwt_model.py +0 -0
  48. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/objects/result.py +0 -0
  49. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/objects/user_info.py +0 -0
  50. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/regex_masking.py +0 -0
  51. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/s3_uploader.py +0 -0
  52. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel/string_extentions.py +0 -0
  53. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel.egg-info/dependency_links.txt +0 -0
  54. {sharedkernel-2.6.3 → sharedkernel-2.7.0}/sharedkernel.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sharedkernel
3
- Version: 2.6.3
3
+ Version: 2.7.0
4
4
  Summary: sharekernel is a shared package between all python projects
5
5
  Author: Smilinno
6
6
  Description-Content-Type: text/markdown
@@ -20,7 +20,7 @@ Requires-Dist: markdown
20
20
  Requires-Dist: beautifulsoup4
21
21
  Requires-Dist: deepdiff
22
22
  Requires-Dist: kombu
23
- Requires-Dist: redis
23
+ Requires-Dist: redis==8.0.0
24
24
  Dynamic: author
25
25
  Dynamic: description
26
26
  Dynamic: description-content-type
@@ -31,6 +31,10 @@ Dynamic: summary
31
31
  this is a shared kernel package
32
32
 
33
33
  # Change Log
34
+ ### Version 2.7.0
35
+ - Add Redis and cache repository
36
+ ### Version 2.6.4
37
+ - Add Verbose to log
34
38
  ### Version 2.6.3
35
39
  - fix bug ip-header-name
36
40
  ### Version 2.6.2
@@ -2,6 +2,10 @@
2
2
  this is a shared kernel package
3
3
 
4
4
  # Change Log
5
+ ### Version 2.7.0
6
+ - Add Redis and cache repository
7
+ ### Version 2.6.4
8
+ - Add Verbose to log
5
9
  ### Version 2.6.3
6
10
  - fix bug ip-header-name
7
11
  ### Version 2.6.2
@@ -13,6 +13,7 @@ setup(
13
13
  packages=[
14
14
  "sharedkernel",
15
15
  "sharedkernel.database",
16
+ "sharedkernel.database.cache",
16
17
  "sharedkernel.enum",
17
18
  "sharedkernel.exception",
18
19
  "sharedkernel.objects",
@@ -37,10 +38,10 @@ setup(
37
38
  "beautifulsoup4",
38
39
  "deepdiff",
39
40
  "kombu",
40
- "redis",
41
+ "redis==8.0.0",
41
42
  ],
42
43
  # *strongly* suggested for sharing
43
- version="2.6.3",
44
+ version="2.7.0",
44
45
  description="sharekernel is a shared package between all python projects",
45
46
  long_description=long_description,
46
47
  long_description_content_type="text/markdown",
@@ -1,6 +1,7 @@
1
1
  import os
2
2
 
3
- VERBOSE = True if os.getenv("VERBOSE", "False").lower() == "true" else False
3
+ IP_SESSION_VERBOSE = True if os.getenv("IP_SESSION_VERBOSE", "False").lower() == "true" else False
4
+ LOG_VERBOSE = True if os.getenv("LOG_VERBOSE", "False").lower() == "true" else False
4
5
 
5
6
  # Log *******************************************************************************
6
7
  LOG_ENABLE = True if os.getenv("LOG_ENABLE", "False").lower() == "true" else False
@@ -0,0 +1,37 @@
1
+
2
+ from abc import ABC, abstractmethod
3
+ from typing import Generic, Optional, TypeVar
4
+ from pydantic import BaseModel
5
+
6
+ T = TypeVar("T", bound=BaseModel)
7
+
8
+
9
+ class CacheRepository(ABC, Generic[T]):
10
+ @abstractmethod
11
+ async def set(
12
+ self,
13
+ key: str,
14
+ value: T,
15
+ ttl_seconds: int | None = None,
16
+ ) -> None:
17
+ pass
18
+
19
+ @abstractmethod
20
+ async def get(self, key: str) -> Optional[T]:
21
+ pass
22
+
23
+ @abstractmethod
24
+ async def exists(self, key: str) -> bool:
25
+ pass
26
+
27
+ @abstractmethod
28
+ async def delete(self, key: str) -> int:
29
+ pass
30
+
31
+ @abstractmethod
32
+ async def delete_group(self, key_prefix: str) -> int:
33
+ pass
34
+
35
+ @abstractmethod
36
+ async def clear(self) -> int:
37
+ pass
@@ -0,0 +1,88 @@
1
+ from typing import Generic, Optional, Type, TypeVar
2
+ from pydantic import BaseModel
3
+ from redis.asyncio import Redis
4
+
5
+ from cache.cache_repository import CacheRepository
6
+
7
+ T = TypeVar("T", bound=BaseModel)
8
+
9
+
10
+ class RedisGenericCache(CacheRepository[T], Generic[T]):
11
+ def __init__(
12
+ self,
13
+ client: Redis,
14
+ namespace: str,
15
+ model: Type[T],
16
+ default_ttl_seconds: int | None = None,
17
+ ):
18
+ self.client = client
19
+ self.namespace = namespace
20
+ self.model = model
21
+ self.default_ttl_seconds = default_ttl_seconds
22
+
23
+ def _pref(self, key: str) -> str:
24
+ return f"{self.namespace}:{key}"
25
+
26
+ def _unpref(self, key: str) -> str:
27
+ prefix = f"{self.namespace}:"
28
+ return key.removeprefix(prefix)
29
+
30
+ def _serialize(self, value: T) -> str:
31
+ return value.model_dump_json()
32
+
33
+ def _deserialize(self, raw: str | bytes) -> T:
34
+ return self.model.model_validate_json(raw.decode())
35
+
36
+ async def set(
37
+ self,
38
+ key: str,
39
+ value: T,
40
+ ttl_seconds: int | None = None,
41
+ ) -> None:
42
+ if value is None:
43
+ return
44
+
45
+ redis_key = self._pref(key)
46
+ ttl = ttl_seconds if ttl_seconds else self.default_ttl_seconds
47
+
48
+ if ttl:
49
+ await self.client.set(redis_key, self._serialize(value), ex=ttl)
50
+ else:
51
+ await self.client.set(redis_key, self._serialize(value))
52
+
53
+ async def get(self, key: str) -> Optional[T]:
54
+ raw = await self.client.get(self._pref(key))
55
+ if raw is None:
56
+ return None
57
+ return self._deserialize(raw)
58
+
59
+ async def exists(self, key: str) -> bool:
60
+ return bool(await self.client.exists(self._pref(key)))
61
+
62
+ async def delete(self, key: str) -> int:
63
+ return await self.client.delete(self._pref(key))
64
+
65
+ async def delete_group(self, key_prefix: str) -> int:
66
+ pattern = self._pref(f"{key_prefix}*")
67
+ deleted = 0
68
+
69
+ async for key in self.client.scan_iter(match=pattern):
70
+ deleted += await self.client.delete(key)
71
+
72
+ return deleted
73
+
74
+ async def clear(self) -> int:
75
+ deleted = 0
76
+
77
+ async for key in self.client.scan_iter(match=f"{self.namespace}:*"):
78
+ deleted += await self.client.delete(key)
79
+
80
+ return deleted
81
+
82
+ async def get_all_ids(self) -> list[str]:
83
+ result: list[str] = []
84
+
85
+ async for raw in self.client.scan_iter(match=f"{self.namespace}:*"):
86
+ result.append(self._unpref(raw.decode()))
87
+
88
+ return result
@@ -78,88 +78,89 @@ class IPSessionAuth:
78
78
  def ip_session_auth(self, request: Request):
79
79
 
80
80
  if not config.IP_SESSION_AUTH_ENABLE:
81
- if config.VERBOSE:
81
+ if config.IP_SESSION_VERBOSE:
82
82
  print("IP_SESSION_AUTH | OK | IP Session Auth is disabled")
83
83
  return
84
84
 
85
- if config.VERBOSE:
86
- print("IP_SESSION_AUTH | INFO | Request Headers: ", request.headers)
85
+ if config.IP_SESSION_VERBOSE:
86
+ print("="*70)
87
+ print("IP_SESSION_AUTH | INFO | Request Headers:\n", request.headers)
87
88
 
88
89
  api_key = request.headers.get(config.APIKEY_HEADER_NAME)
89
90
 
90
91
  if api_key:
91
- if config.VERBOSE:
92
+ if config.IP_SESSION_VERBOSE:
92
93
  print("IP_SESSION_AUTH | OK | API Key is provided")
93
94
  return
94
95
 
95
96
  state = getattr(request.state, "decoded_token", None)
96
- if config.VERBOSE:
97
+ if config.IP_SESSION_VERBOSE:
97
98
  print("IP_SESSION_AUTH | INFO | State: ", state)
98
99
 
99
100
  if not state:
100
- if config.VERBOSE:
101
+ if config.IP_SESSION_VERBOSE:
101
102
  print("IP_SESSION_AUTH | ERROR | No state found")
102
103
  raise UnAuthorizedException()
103
104
 
104
105
  nameid = state.get("nameid")
105
106
  sessionid = state.get("sessionId")
106
- if config.VERBOSE:
107
+ if config.IP_SESSION_VERBOSE:
107
108
  print("IP_SESSION_AUTH | INFO | Nameid: ", nameid)
108
109
  print("IP_SESSION_AUTH | INFO | Sessionid: ", sessionid)
109
110
 
110
111
  if not nameid or not sessionid:
111
- if config.VERBOSE:
112
+ if config.IP_SESSION_VERBOSE:
112
113
  print("IP_SESSION_AUTH | ERROR | No nameid or sessionid found")
113
114
  raise UnAuthorizedException()
114
115
 
115
116
  request_ip = self._get_ip_from_request(request, config.IP_HEADER_NAME)
116
117
 
117
118
  if not request_ip:
118
- if config.VERBOSE:
119
+ if config.IP_SESSION_VERBOSE:
119
120
  print("IP_SESSION_AUTH | ERROR | No request ip found")
120
121
  raise UnAuthorizedException()
121
122
 
122
123
  request_ip = request_ip.strip()
123
- if config.VERBOSE:
124
+ if config.IP_SESSION_VERBOSE:
124
125
  print("IP_SESSION_AUTH | INFO | Request ip: ", request_ip)
125
126
 
126
127
  if self._is_ip_allowed(request_ip):
127
- if config.VERBOSE:
128
+ if config.IP_SESSION_VERBOSE:
128
129
  print("IP_SESSION_AUTH | OK | IP is in whitelist")
129
130
  return
130
131
 
131
132
  redis_key = f"userId:{nameid}:session:{sessionid}"
132
133
  user_data = self.redis.get(redis_key)
133
- if config.VERBOSE:
134
+ if config.IP_SESSION_VERBOSE:
134
135
  print("IP_SESSION_AUTH | INFO | User data: ", user_data)
135
136
 
136
137
  if not user_data:
137
- if config.VERBOSE:
138
+ if config.IP_SESSION_VERBOSE:
138
139
  print("IP_SESSION_AUTH | ERROR | No user data found")
139
140
  raise UnAuthorizedException()
140
141
 
141
142
  try:
142
143
  payload = json.loads(user_data.decode())
143
144
  except (ValueError, UnicodeDecodeError, TypeError):
144
- if config.VERBOSE:
145
+ if config.IP_SESSION_VERBOSE:
145
146
  print("IP_SESSION_AUTH | ERROR | Error decoding user data")
146
147
  raise UnAuthorizedException()
147
148
 
148
149
  stored_ip = payload.get("Ip")
149
- if config.VERBOSE:
150
+ if config.IP_SESSION_VERBOSE:
150
151
  print("IP_SESSION_AUTH | INFO | Stored ip: ", stored_ip)
151
152
 
152
153
  if not stored_ip:
153
- if config.VERBOSE:
154
+ if config.IP_SESSION_VERBOSE:
154
155
  print("IP_SESSION_AUTH | ERROR | No stored ip found")
155
156
  raise UnAuthorizedException()
156
157
 
157
158
  if stored_ip.strip() != request_ip:
158
- if config.VERBOSE:
159
+ if config.IP_SESSION_VERBOSE:
159
160
  print("IP_SESSION_AUTH | ERROR | Stored ip does not match request ip")
160
161
  raise UnAuthorizedException()
161
162
 
162
163
  lifetime_minutes = self._get_lifetime()
163
164
  self.redis.expire(redis_key, lifetime_minutes * 60)
164
- if config.VERBOSE:
165
+ if config.IP_SESSION_VERBOSE:
165
166
  print("IP_SESSION_AUTH | OK | IP session auth successful")
@@ -92,8 +92,9 @@ class LoggerService:
92
92
 
93
93
 
94
94
  def emit(self, log: LogDTO):
95
- # if config.VERBOSE:
96
- # print("LOGGER | INFO | Emitting log:\n", log)
95
+ if config.LOG_VERBOSE:
96
+ print("="*70)
97
+ print("LOGGER | INFO | Emitting log:\n", log)
97
98
  self.publish(log)
98
99
 
99
100
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sharedkernel
3
- Version: 2.6.3
3
+ Version: 2.7.0
4
4
  Summary: sharekernel is a shared package between all python projects
5
5
  Author: Smilinno
6
6
  Description-Content-Type: text/markdown
@@ -20,7 +20,7 @@ Requires-Dist: markdown
20
20
  Requires-Dist: beautifulsoup4
21
21
  Requires-Dist: deepdiff
22
22
  Requires-Dist: kombu
23
- Requires-Dist: redis
23
+ Requires-Dist: redis==8.0.0
24
24
  Dynamic: author
25
25
  Dynamic: description
26
26
  Dynamic: description-content-type
@@ -31,6 +31,10 @@ Dynamic: summary
31
31
  this is a shared kernel package
32
32
 
33
33
  # Change Log
34
+ ### Version 2.7.0
35
+ - Add Redis and cache repository
36
+ ### Version 2.6.4
37
+ - Add Verbose to log
34
38
  ### Version 2.6.3
35
39
  - fix bug ip-header-name
36
40
  ### Version 2.6.2
@@ -24,6 +24,9 @@ sharedkernel/database/mongo_generic_audit_repository.py
24
24
  sharedkernel/database/mongo_generic_repository.py
25
25
  sharedkernel/database/mongo_health_checker.py
26
26
  sharedkernel/database/pagination_response_dto.py
27
+ sharedkernel/database/cache/__init__.py
28
+ sharedkernel/database/cache/cache_repository.py
29
+ sharedkernel/database/cache/redis_generic_cache.py
27
30
  sharedkernel/enum/__init__.py
28
31
  sharedkernel/enum/error_code.py
29
32
  sharedkernel/enum/redis_mode_enum.py
@@ -14,4 +14,4 @@ markdown
14
14
  beautifulsoup4
15
15
  deepdiff
16
16
  kombu
17
- redis
17
+ redis==8.0.0
File without changes