maleo-foundation 0.2.96__py3-none-any.whl → 0.2.97__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.
- maleo_foundation/authentication.py +9 -9
- maleo_foundation/authorization.py +2 -2
- maleo_foundation/client/manager.py +11 -2
- maleo_foundation/client/services/encryption/aes.py +2 -2
- maleo_foundation/client/services/encryption/rsa.py +2 -2
- maleo_foundation/client/services/key.py +6 -3
- maleo_foundation/client/services/signature.py +2 -2
- maleo_foundation/client/services/token.py +2 -2
- maleo_foundation/constants.py +7 -7
- maleo_foundation/managers/cache/base.py +5 -1
- maleo_foundation/managers/cache/redis.py +12 -12
- maleo_foundation/managers/client/base.py +8 -8
- maleo_foundation/managers/client/google/base.py +6 -6
- maleo_foundation/managers/client/google/parameter.py +12 -5
- maleo_foundation/managers/client/google/secret.py +22 -7
- maleo_foundation/managers/client/google/storage.py +17 -17
- maleo_foundation/managers/client/maleo.py +9 -9
- maleo_foundation/managers/db.py +12 -12
- maleo_foundation/managers/middleware.py +22 -22
- maleo_foundation/managers/service.py +52 -52
- maleo_foundation/middlewares/authentication.py +11 -8
- maleo_foundation/middlewares/base.py +68 -64
- maleo_foundation/middlewares/cors.py +6 -6
- maleo_foundation/models/responses.py +37 -37
- maleo_foundation/models/schemas/encryption.py +5 -5
- maleo_foundation/models/schemas/general.py +33 -33
- maleo_foundation/models/schemas/hash.py +4 -4
- maleo_foundation/models/schemas/key.py +4 -4
- maleo_foundation/models/schemas/parameter.py +15 -15
- maleo_foundation/models/schemas/result.py +47 -47
- maleo_foundation/models/schemas/signature.py +5 -5
- maleo_foundation/models/schemas/token.py +4 -4
- maleo_foundation/models/transfers/general/__init__.py +63 -18
- maleo_foundation/models/transfers/general/key.py +4 -4
- maleo_foundation/models/transfers/general/token.py +71 -20
- maleo_foundation/models/transfers/parameters/token.py +1 -1
- maleo_foundation/models/transfers/results/client/controllers/http.py +4 -4
- maleo_foundation/models/transfers/results/encryption/aes.py +2 -2
- maleo_foundation/models/transfers/results/encryption/rsa.py +2 -2
- maleo_foundation/models/transfers/results/hash.py +2 -2
- maleo_foundation/models/transfers/results/key.py +3 -3
- maleo_foundation/models/transfers/results/signature.py +2 -2
- maleo_foundation/models/transfers/results/token.py +2 -2
- maleo_foundation/utils/cleaner.py +22 -0
- maleo_foundation/utils/client.py +6 -6
- maleo_foundation/utils/controller.py +8 -8
- maleo_foundation/utils/dependencies/auth.py +2 -2
- maleo_foundation/utils/dependencies/context.py +1 -1
- maleo_foundation/utils/exceptions.py +10 -10
- maleo_foundation/utils/extractor.py +2 -2
- maleo_foundation/utils/formatter/case.py +4 -4
- maleo_foundation/utils/loaders/credential/google.py +3 -1
- maleo_foundation/utils/loaders/json.py +2 -2
- maleo_foundation/utils/loaders/yaml.py +2 -2
- maleo_foundation/utils/logging.py +30 -24
- maleo_foundation/utils/merger.py +5 -2
- maleo_foundation/utils/query.py +48 -44
- maleo_foundation/utils/repository.py +8 -8
- maleo_foundation/utils/searcher.py +4 -1
- {maleo_foundation-0.2.96.dist-info → maleo_foundation-0.2.97.dist-info}/METADATA +1 -1
- {maleo_foundation-0.2.96.dist-info → maleo_foundation-0.2.97.dist-info}/RECORD +63 -62
- {maleo_foundation-0.2.96.dist-info → maleo_foundation-0.2.97.dist-info}/WHEEL +0 -0
- {maleo_foundation-0.2.96.dist-info → maleo_foundation-0.2.97.dist-info}/top_level.txt +0 -0
@@ -4,10 +4,10 @@ from pydantic import BaseModel, Field, model_validator
|
|
4
4
|
from typing import Any
|
5
5
|
|
6
6
|
class BaseClientHTTPControllerResults(BaseModel):
|
7
|
-
response:Response = Field(..., description="Client's HTTP Controller response")
|
8
|
-
status_code:int = Field(..., description="Client's HTTP Controller response status code")
|
9
|
-
content:Any = Field(..., description="Client's HTTP Controller response content")
|
10
|
-
success:bool = Field(..., description="Client's HTTP Controller success status")
|
7
|
+
response: Response = Field(..., description="Client's HTTP Controller response")
|
8
|
+
status_code: int = Field(..., description="Client's HTTP Controller response status code")
|
9
|
+
content: Any = Field(..., description="Client's HTTP Controller response content")
|
10
|
+
success: bool = Field(..., description="Client's HTTP Controller success status")
|
11
11
|
|
12
12
|
class Config:
|
13
13
|
arbitrary_types_allowed=True
|
@@ -12,7 +12,7 @@ class MaleoFoundationAESEncryptionResultsTransfers:
|
|
12
12
|
class Fail(BaseServiceGeneralResultsTransfers.Fail): pass
|
13
13
|
|
14
14
|
class Encrypt(BaseServiceGeneralResultsTransfers.SingleData):
|
15
|
-
data:EncryptData = Field(..., description="Single encryption data")
|
15
|
+
data: EncryptData = Field(..., description="Single encryption data")
|
16
16
|
|
17
17
|
class Decrypt(BaseServiceGeneralResultsTransfers.SingleData):
|
18
|
-
data:MaleoFoundationEncryptionSchemas.Plaintext = Field(..., description="Single decryption data")
|
18
|
+
data: MaleoFoundationEncryptionSchemas.Plaintext = Field(..., description="Single decryption data")
|
@@ -6,7 +6,7 @@ class MaleoFoundationRSAEncryptionResultsTransfers:
|
|
6
6
|
class Fail(BaseServiceGeneralResultsTransfers.Fail): pass
|
7
7
|
|
8
8
|
class Encrypt(BaseServiceGeneralResultsTransfers.SingleData):
|
9
|
-
data:MaleoFoundationEncryptionSchemas.Ciphertext = Field(..., description="Single encryption data")
|
9
|
+
data: MaleoFoundationEncryptionSchemas.Ciphertext = Field(..., description="Single encryption data")
|
10
10
|
|
11
11
|
class Decrypt(BaseServiceGeneralResultsTransfers.SingleData):
|
12
|
-
data:MaleoFoundationEncryptionSchemas.Plaintext = Field(..., description="Single decryption data")
|
12
|
+
data: MaleoFoundationEncryptionSchemas.Plaintext = Field(..., description="Single decryption data")
|
@@ -7,7 +7,7 @@ class MaleoFoundationHashResultsTransfers:
|
|
7
7
|
class Fail(BaseServiceGeneralResultsTransfers.Fail): pass
|
8
8
|
|
9
9
|
class Hash(BaseServiceGeneralResultsTransfers.SingleData):
|
10
|
-
data:MaleoFoundationHashSchemas.Hash = Field(..., description="Hash data")
|
10
|
+
data: MaleoFoundationHashSchemas.Hash = Field(..., description="Hash data")
|
11
11
|
|
12
12
|
class Verify(BaseServiceGeneralResultsTransfers.SingleData):
|
13
|
-
data:MaleoFoundationHashSchemas.IsValid = Field(..., description="Verify data")
|
13
|
+
data: MaleoFoundationHashSchemas.IsValid = Field(..., description="Verify data")
|
@@ -7,10 +7,10 @@ class MaleoFoundationKeyResultsTransfers:
|
|
7
7
|
class Fail(BaseServiceGeneralResultsTransfers.Fail): pass
|
8
8
|
|
9
9
|
class CreatePrivate(BaseServiceGeneralResultsTransfers.SingleData):
|
10
|
-
data:MaleoFoundationKeyGeneralTransfers.PrivateKey = Field(..., description="Private key data")
|
10
|
+
data: MaleoFoundationKeyGeneralTransfers.PrivateKey = Field(..., description="Private key data")
|
11
11
|
|
12
12
|
class CreatePublic(BaseServiceGeneralResultsTransfers.SingleData):
|
13
|
-
data:MaleoFoundationKeyGeneralTransfers.PublicKey = Field(..., description="Private key data")
|
13
|
+
data: MaleoFoundationKeyGeneralTransfers.PublicKey = Field(..., description="Private key data")
|
14
14
|
|
15
15
|
class CreatePair(BaseServiceGeneralResultsTransfers.SingleData):
|
16
|
-
data:MaleoFoundationKeyGeneralTransfers.KeyPair = Field(..., description="Key pair data")
|
16
|
+
data: MaleoFoundationKeyGeneralTransfers.KeyPair = Field(..., description="Key pair data")
|
@@ -6,7 +6,7 @@ class MaleoFoundationSignatureResultsTransfers:
|
|
6
6
|
class Fail(BaseServiceGeneralResultsTransfers.Fail): pass
|
7
7
|
|
8
8
|
class Sign(BaseServiceGeneralResultsTransfers.SingleData):
|
9
|
-
data:MaleoFoundationSignatureSchemas.Signature = Field(..., description="Single signature data")
|
9
|
+
data: MaleoFoundationSignatureSchemas.Signature = Field(..., description="Single signature data")
|
10
10
|
|
11
11
|
class Verify(BaseServiceGeneralResultsTransfers.SingleData):
|
12
|
-
data:MaleoFoundationSignatureSchemas.IsValid = Field(..., description="Single verify data")
|
12
|
+
data: MaleoFoundationSignatureSchemas.IsValid = Field(..., description="Single verify data")
|
@@ -6,7 +6,7 @@ class MaleoFoundationTokenResultsTransfers:
|
|
6
6
|
class Fail(BaseServiceGeneralResultsTransfers.Fail): pass
|
7
7
|
|
8
8
|
class Encode(BaseServiceGeneralResultsTransfers.SingleData):
|
9
|
-
data:MaleoFoundationTokenSchemas.Token
|
9
|
+
data: MaleoFoundationTokenSchemas.Token
|
10
10
|
|
11
11
|
class Decode(BaseServiceGeneralResultsTransfers.SingleData):
|
12
|
-
data:MaleoFoundationTokenGeneralTransfers.DecodePayload
|
12
|
+
data: MaleoFoundationTokenGeneralTransfers.DecodePayload
|
@@ -0,0 +1,22 @@
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
2
|
+
|
3
|
+
def clean_pubsub_message(
|
4
|
+
msg:Dict[str, Any],
|
5
|
+
enums:Optional[List[str]] = None
|
6
|
+
) -> Dict[str, Any]:
|
7
|
+
for k, v in msg.items():
|
8
|
+
# Clean enums
|
9
|
+
if isinstance(v, dict) and len(v) == 1:
|
10
|
+
only_key = next(iter(v))
|
11
|
+
if enums is not None and only_key in enums:
|
12
|
+
msg[k] = v[only_key]
|
13
|
+
|
14
|
+
# Clean "map"
|
15
|
+
if isinstance(v, dict) and "map" in v and isinstance(v["map"], dict):
|
16
|
+
msg[k] = v["map"]
|
17
|
+
|
18
|
+
# Clean "array"
|
19
|
+
if isinstance(v, dict) and "array" in v and isinstance(v["array"], list):
|
20
|
+
msg[k] = v["array"]
|
21
|
+
|
22
|
+
return msg
|
maleo_foundation/utils/client.py
CHANGED
@@ -9,17 +9,17 @@ from maleo_foundation.models.transfers.results.client.service import \
|
|
9
9
|
class BaseClientUtils:
|
10
10
|
@staticmethod
|
11
11
|
def result_processor(
|
12
|
-
fail_class:Type[BaseClientServiceResultsTransfers.Fail],
|
13
|
-
data_found_class:Union[
|
12
|
+
fail_class: Type[BaseClientServiceResultsTransfers.Fail],
|
13
|
+
data_found_class: Union[
|
14
14
|
Type[BaseClientServiceResultsTransfers.SingleData],
|
15
15
|
Type[BaseClientServiceResultsTransfers.UnpaginatedMultipleData],
|
16
16
|
Type[BaseClientServiceResultsTransfers.PaginatedMultipleData]
|
17
17
|
],
|
18
|
-
no_data_class:Optional[Type[BaseClientServiceResultsTransfers.NoData]] = None,
|
18
|
+
no_data_class: Optional[Type[BaseClientServiceResultsTransfers.NoData]] = None,
|
19
19
|
):
|
20
20
|
"""Decorator to handle repository-related exceptions consistently."""
|
21
21
|
def decorator(func):
|
22
|
-
def _processor(result:BaseTypes.StringToAnyDict):
|
22
|
+
def _processor(result: BaseTypes.StringToAnyDict):
|
23
23
|
if "success" not in result and "data" not in result:
|
24
24
|
raise ValueError("Result did not have both 'success' and 'data' field")
|
25
25
|
success:bool = result.get("success")
|
@@ -40,7 +40,7 @@ class BaseClientUtils:
|
|
40
40
|
@wraps(func)
|
41
41
|
async def async_wrapper(*args, **kwargs):
|
42
42
|
try:
|
43
|
-
result:BaseTypes.StringToAnyDict = await func(*args, **kwargs)
|
43
|
+
result: BaseTypes.StringToAnyDict = await func(*args, **kwargs)
|
44
44
|
return _processor(result=result)
|
45
45
|
except ValidationError as e:
|
46
46
|
raise
|
@@ -51,7 +51,7 @@ class BaseClientUtils:
|
|
51
51
|
@wraps(func)
|
52
52
|
def sync_wrapper(*args, **kwargs):
|
53
53
|
try:
|
54
|
-
result:BaseTypes.StringToAnyDict = func(*args, **kwargs)
|
54
|
+
result: BaseTypes.StringToAnyDict = func(*args, **kwargs)
|
55
55
|
return _processor(result=result)
|
56
56
|
except ValidationError as e:
|
57
57
|
raise
|
@@ -13,8 +13,8 @@ from maleo_foundation.expanded_types.general import BaseGeneralExpandedTypes
|
|
13
13
|
class BaseControllerUtils:
|
14
14
|
@staticmethod
|
15
15
|
def field_expansion_handler(
|
16
|
-
expandable_fields_dependencies_map:BaseTypes.OptionalStringToListOfStringDict = None,
|
17
|
-
field_expansion_processors:BaseGeneralExpandedTypes.OptionalListOfFieldExpansionProcessor = None
|
16
|
+
expandable_fields_dependencies_map: BaseTypes.OptionalStringToListOfStringDict = None,
|
17
|
+
field_expansion_processors: BaseGeneralExpandedTypes.OptionalListOfFieldExpansionProcessor = None
|
18
18
|
):
|
19
19
|
"""
|
20
20
|
Decorator to handle expandable fields validation and processing.
|
@@ -23,7 +23,7 @@ class BaseControllerUtils:
|
|
23
23
|
expandable_fields_dependencies_map: Dictionary where keys are dependency fields and values are lists of dependent fields
|
24
24
|
field_expansion_processors: List of processor functions that handle that field's data
|
25
25
|
"""
|
26
|
-
def decorator(func:Callable[..., Awaitable[BaseServiceRESTControllerResults]]):
|
26
|
+
def decorator(func: Callable[..., Awaitable[BaseServiceRESTControllerResults]]):
|
27
27
|
@wraps(func)
|
28
28
|
async def wrapper(*args, **kwargs):
|
29
29
|
sig = inspect.signature(func)
|
@@ -31,7 +31,7 @@ class BaseControllerUtils:
|
|
31
31
|
bound.apply_defaults()
|
32
32
|
|
33
33
|
parameters = bound.arguments.get("parameters")
|
34
|
-
expand:BaseTypes.OptionalListOfStrings = getattr(parameters, 'expand', None)
|
34
|
+
expand: BaseTypes.OptionalListOfStrings = getattr(parameters, 'expand', None)
|
35
35
|
|
36
36
|
#* Validate expandable fields dependencies
|
37
37
|
if expand is not None and expandable_fields_dependencies_map is not None:
|
@@ -54,7 +54,7 @@ class BaseControllerUtils:
|
|
54
54
|
return result
|
55
55
|
|
56
56
|
#* Recursive function to apply expansion processors
|
57
|
-
def recursive_expand(data:Union[Dict, List], expand:BaseTypes.OptionalListOfStrings):
|
57
|
+
def recursive_expand(data: Union[Dict, List], expand: BaseTypes.OptionalListOfStrings):
|
58
58
|
if isinstance(data, list):
|
59
59
|
for idx, item in enumerate(data):
|
60
60
|
data[idx] = recursive_expand(item, expand)
|
@@ -93,7 +93,7 @@ class BaseControllerUtils:
|
|
93
93
|
|
94
94
|
@staticmethod
|
95
95
|
def field_modification_handler(
|
96
|
-
field_modification_processors:BaseGeneralExpandedTypes.OptionalListOfFieldModificationProcessor = None
|
96
|
+
field_modification_processors: BaseGeneralExpandedTypes.OptionalListOfFieldModificationProcessor = None
|
97
97
|
):
|
98
98
|
"""
|
99
99
|
Decorator to handle expandable fields validation and processing.
|
@@ -102,7 +102,7 @@ class BaseControllerUtils:
|
|
102
102
|
expandable_fields_dependencies_map: Dictionary where keys are dependency fields and values are lists of dependent fields
|
103
103
|
field_modification_processors: List of processor functions that handle that field's data
|
104
104
|
"""
|
105
|
-
def decorator(func:Callable[..., Awaitable[BaseServiceRESTControllerResults]]):
|
105
|
+
def decorator(func: Callable[..., Awaitable[BaseServiceRESTControllerResults]]):
|
106
106
|
@wraps(func)
|
107
107
|
async def wrapper(*args, **kwargs):
|
108
108
|
#* Call the original function
|
@@ -112,7 +112,7 @@ class BaseControllerUtils:
|
|
112
112
|
return result
|
113
113
|
|
114
114
|
#* Recursive function to apply modification processors
|
115
|
-
def recursive_modify(data:Union[Dict, List]):
|
115
|
+
def recursive_modify(data: Union[Dict, List]):
|
116
116
|
if isinstance(data, list):
|
117
117
|
for idx, item in enumerate(data):
|
118
118
|
data[idx] = recursive_modify(item)
|
@@ -7,7 +7,7 @@ from maleo_foundation.authorization import TOKEN_SCHEME, Authorization
|
|
7
7
|
class AuthDependencies:
|
8
8
|
@staticmethod
|
9
9
|
def authentication(
|
10
|
-
request:Request
|
10
|
+
request: Request
|
11
11
|
) -> Authentication:
|
12
12
|
return Authentication(
|
13
13
|
credentials=request.auth,
|
@@ -16,7 +16,7 @@ class AuthDependencies:
|
|
16
16
|
|
17
17
|
@staticmethod
|
18
18
|
def authorization(
|
19
|
-
token:HTTPAuthorizationCredentials = Security(TOKEN_SCHEME)
|
19
|
+
token: HTTPAuthorizationCredentials = Security(TOKEN_SCHEME)
|
20
20
|
) -> Authorization:
|
21
21
|
return Authorization(
|
22
22
|
scheme=token.scheme,
|
@@ -17,14 +17,14 @@ from maleo_foundation.utils.logging import BaseLogger
|
|
17
17
|
|
18
18
|
class BaseExceptions:
|
19
19
|
@staticmethod
|
20
|
-
def authentication_error_handler(request:Request, exc:Exception):
|
20
|
+
def authentication_error_handler(request: Request, exc: Exception):
|
21
21
|
return JSONResponse(
|
22
22
|
content=BaseResponses.Unauthorized(other=str(exc)).model_dump(mode="json"),
|
23
23
|
status_code=status.HTTP_401_UNAUTHORIZED
|
24
24
|
)
|
25
25
|
|
26
26
|
@staticmethod
|
27
|
-
async def validation_exception_handler(request:Request, exc:RequestValidationError):
|
27
|
+
async def validation_exception_handler(request: Request, exc: RequestValidationError):
|
28
28
|
serialized_error = jsonable_encoder(exc.errors())
|
29
29
|
return JSONResponse(
|
30
30
|
content=BaseResponses.ValidationError(other=serialized_error).model_dump(mode="json"),
|
@@ -32,7 +32,7 @@ class BaseExceptions:
|
|
32
32
|
)
|
33
33
|
|
34
34
|
@staticmethod
|
35
|
-
async def http_exception_handler(request:Request, exc:StarletteHTTPException):
|
35
|
+
async def http_exception_handler(request: Request, exc: StarletteHTTPException):
|
36
36
|
if exc.status_code in BaseResponses.other_responses:
|
37
37
|
return JSONResponse(
|
38
38
|
content=BaseResponses.other_responses[exc.status_code]["model"]().model_dump(mode="json"),
|
@@ -46,13 +46,13 @@ class BaseExceptions:
|
|
46
46
|
|
47
47
|
@staticmethod
|
48
48
|
def repository_exception_handler(
|
49
|
-
operation:str,
|
50
|
-
logger:Optional[BaseLogger] = None,
|
51
|
-
fail_result_class:type[BaseServiceRepositoryResultsTransfers.Fail] = BaseServiceRepositoryResultsTransfers.Fail
|
49
|
+
operation: str,
|
50
|
+
logger: Optional[BaseLogger] = None,
|
51
|
+
fail_result_class: type[BaseServiceRepositoryResultsTransfers.Fail] = BaseServiceRepositoryResultsTransfers.Fail
|
52
52
|
):
|
53
53
|
"""Decorator to handle repository-related exceptions consistently for sync and async functions."""
|
54
54
|
def decorator(func):
|
55
|
-
def _handler(e:Exception, category:str, description:str):
|
55
|
+
def _handler(e: Exception, category: str, description: str):
|
56
56
|
if logger:
|
57
57
|
logger.error(
|
58
58
|
f"{category} occurred while {operation}: '{str(e)}'",
|
@@ -115,9 +115,9 @@ class BaseExceptions:
|
|
115
115
|
|
116
116
|
@staticmethod
|
117
117
|
def service_exception_handler(
|
118
|
-
operation:str,
|
119
|
-
logger:Optional[BaseLogger] = None,
|
120
|
-
fail_result_class:type[BaseServiceGeneralResultsTransfers.Fail] = BaseServiceGeneralResultsTransfers.Fail
|
118
|
+
operation: str,
|
119
|
+
logger: Optional[BaseLogger] = None,
|
120
|
+
fail_result_class: type[BaseServiceGeneralResultsTransfers.Fail] = BaseServiceGeneralResultsTransfers.Fail
|
121
121
|
):
|
122
122
|
"""Decorator to handle service-related exceptions consistently."""
|
123
123
|
def decorator(func):
|
@@ -4,7 +4,7 @@ from starlette.requests import HTTPConnection
|
|
4
4
|
from uuid import uuid4
|
5
5
|
from maleo_foundation.models.transfers.general import RequestContextTransfers
|
6
6
|
|
7
|
-
def extract_client_ip(conn:HTTPConnection) -> str:
|
7
|
+
def extract_client_ip(conn: HTTPConnection) -> str:
|
8
8
|
"""Extract client IP with more robust handling of proxies"""
|
9
9
|
#* Check for X-Forwarded-For header (common when behind proxy/load balancer)
|
10
10
|
x_forwarded_for = conn.headers.get("X-Forwarded-For")
|
@@ -21,7 +21,7 @@ def extract_client_ip(conn:HTTPConnection) -> str:
|
|
21
21
|
#* Fall back to direct client connection
|
22
22
|
return conn.client.host if conn.client else "unknown"
|
23
23
|
|
24
|
-
def extract_request_context(request:Request) -> RequestContextTransfers:
|
24
|
+
def extract_request_context(request: Request) -> RequestContextTransfers:
|
25
25
|
headers = request.headers
|
26
26
|
|
27
27
|
request_id = headers.get("x-request-id")
|
@@ -8,24 +8,24 @@ class CaseFormatter:
|
|
8
8
|
SNAKE = "snake"
|
9
9
|
|
10
10
|
@staticmethod
|
11
|
-
def to_camel_case(text:str) -> str:
|
11
|
+
def to_camel_case(text: str) -> str:
|
12
12
|
"""Converts snake_case or PascalCase to camelCase."""
|
13
13
|
words = re.split(r'[_\s]', text) # Handle snake_case and spaces
|
14
14
|
return words[0].lower() + "".join(word.capitalize() for word in words[1:])
|
15
15
|
|
16
16
|
@staticmethod
|
17
|
-
def to_pascal_case(text:str) -> str:
|
17
|
+
def to_pascal_case(text: str) -> str:
|
18
18
|
"""Converts snake_case or camelCase to PascalCase."""
|
19
19
|
words = re.split(r'[_\s]', text)
|
20
20
|
return "".join(word.capitalize() for word in words)
|
21
21
|
|
22
22
|
@staticmethod
|
23
|
-
def to_snake_case(text:str) -> str:
|
23
|
+
def to_snake_case(text: str) -> str:
|
24
24
|
"""Converts camelCase or PascalCase to snake_case."""
|
25
25
|
return re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', text).lower()
|
26
26
|
|
27
27
|
@staticmethod
|
28
|
-
def convert(text:str, target:Case) -> str:
|
28
|
+
def convert(text: str, target: Case) -> str:
|
29
29
|
"""Converts text to the specified case format."""
|
30
30
|
if target == CaseFormatter.Case.CAMEL:
|
31
31
|
return CaseFormatter.to_camel_case(text)
|
@@ -6,7 +6,9 @@ from typing import Optional, Union
|
|
6
6
|
|
7
7
|
class GoogleCredentialsLoader:
|
8
8
|
@staticmethod
|
9
|
-
def load(
|
9
|
+
def load(
|
10
|
+
credentials_path: Optional[Union[Path, str]] = None
|
11
|
+
) -> Credentials:
|
10
12
|
"""
|
11
13
|
Load Google credentials either from a service account file or from the default credentials.
|
12
14
|
Priority:
|
@@ -4,7 +4,7 @@ from pathlib import Path
|
|
4
4
|
|
5
5
|
class JSONLoader:
|
6
6
|
@staticmethod
|
7
|
-
def load_from_path(path:Union[Path, str]) -> Union[Dict[str, Any], List[Any]]:
|
7
|
+
def load_from_path(path: Union[Path, str]) -> Union[Dict[str, Any], List[Any]]:
|
8
8
|
file_path = Path(path)
|
9
9
|
|
10
10
|
if not file_path.is_file():
|
@@ -14,5 +14,5 @@ class JSONLoader:
|
|
14
14
|
return json.load(f)
|
15
15
|
|
16
16
|
@staticmethod
|
17
|
-
def load_from_string(string:str) -> Dict:
|
17
|
+
def load_from_string(string: str) -> Dict:
|
18
18
|
return json.loads(string)
|
@@ -4,7 +4,7 @@ from typing import Dict, Union
|
|
4
4
|
|
5
5
|
class YAMLLoader:
|
6
6
|
@staticmethod
|
7
|
-
def load_from_path(path:Union[Path, str]) -> Dict:
|
7
|
+
def load_from_path(path: Union[Path, str]) -> Dict:
|
8
8
|
file_path = Path(path)
|
9
9
|
|
10
10
|
if not file_path.exists() or not file_path.is_file():
|
@@ -14,5 +14,5 @@ class YAMLLoader:
|
|
14
14
|
return yaml.safe_load(f)
|
15
15
|
|
16
16
|
@staticmethod
|
17
|
-
def load_from_string(string:str) -> Dict:
|
17
|
+
def load_from_string(string: str) -> Dict:
|
18
18
|
return yaml.safe_load(string)
|
@@ -12,7 +12,10 @@ from maleo_foundation.types import BaseTypes
|
|
12
12
|
from maleo_foundation.utils.loaders.credential.google import GoogleCredentialsLoader
|
13
13
|
|
14
14
|
class GoogleCloudLogging:
|
15
|
-
def __init__(
|
15
|
+
def __init__(
|
16
|
+
self,
|
17
|
+
credentials_path: Optional[Union[Path, str]] = None
|
18
|
+
) -> None:
|
16
19
|
self._credentials = GoogleCredentialsLoader.load(credentials_path=credentials_path)
|
17
20
|
self._client = Client(credentials=self._credentials)
|
18
21
|
self._client.setup_logging()
|
@@ -31,13 +34,16 @@ class GoogleCloudLogging:
|
|
31
34
|
if self._client is not None:
|
32
35
|
self._client = None
|
33
36
|
|
34
|
-
def create_handler(
|
37
|
+
def create_handler(
|
38
|
+
self,
|
39
|
+
name: str
|
40
|
+
) -> CloudLoggingHandler:
|
35
41
|
return CloudLoggingHandler(client=self._client, name=name)
|
36
42
|
|
37
43
|
class SimpleConfig(BaseModel):
|
38
|
-
dir:str = Field(..., description="Log's directory")
|
39
|
-
level:BaseEnums.LoggerLevel = Field(BaseEnums.LoggerLevel.INFO, description="Log's level")
|
40
|
-
google_cloud_logging:Optional[GoogleCloudLogging] = Field(default_factory=GoogleCloudLogging, description="Google cloud logging")
|
44
|
+
dir: str = Field(..., description="Log's directory")
|
45
|
+
level: BaseEnums.LoggerLevel = Field(BaseEnums.LoggerLevel.INFO, description="Log's level")
|
46
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = Field(default_factory=GoogleCloudLogging, description="Google cloud logging")
|
41
47
|
|
42
48
|
class Config:
|
43
49
|
arbitrary_types_allowed=True
|
@@ -45,13 +51,13 @@ class SimpleConfig(BaseModel):
|
|
45
51
|
class BaseLogger(logging.Logger):
|
46
52
|
def __init__(
|
47
53
|
self,
|
48
|
-
dir:str,
|
49
|
-
type:BaseEnums.LoggerType,
|
50
|
-
service_key:BaseTypes.OptionalString = None,
|
51
|
-
middleware_type:Optional[BaseEnums.MiddlewareLoggerType] = None,
|
52
|
-
client_key:BaseTypes.OptionalString = None,
|
53
|
-
level:BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
54
|
-
google_cloud_logging:Optional[GoogleCloudLogging] = None
|
54
|
+
dir: str,
|
55
|
+
type: BaseEnums.LoggerType,
|
56
|
+
service_key: BaseTypes.OptionalString = None,
|
57
|
+
middleware_type: Optional[BaseEnums.MiddlewareLoggerType] = None,
|
58
|
+
client_key: BaseTypes.OptionalString = None,
|
59
|
+
level: BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
60
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = None
|
55
61
|
):
|
56
62
|
self._type = type #* Declare logger type
|
57
63
|
|
@@ -156,8 +162,8 @@ class BaseLogger(logging.Logger):
|
|
156
162
|
class MiddlewareLogger(BaseLogger):
|
157
163
|
def __init__(
|
158
164
|
self,
|
159
|
-
dir:str,
|
160
|
-
service_key:BaseTypes.OptionalString = None,
|
165
|
+
dir: str,
|
166
|
+
service_key: BaseTypes.OptionalString = None,
|
161
167
|
middleware_type = None,
|
162
168
|
level = BaseEnums.LoggerLevel.INFO,
|
163
169
|
google_cloud_logging = None
|
@@ -175,11 +181,11 @@ class MiddlewareLogger(BaseLogger):
|
|
175
181
|
class ServiceLogger(BaseLogger):
|
176
182
|
def __init__(
|
177
183
|
self,
|
178
|
-
dir:str,
|
179
|
-
type:BaseEnums.ServiceLoggerType,
|
180
|
-
service_key:BaseTypes.OptionalString = None,
|
181
|
-
level:BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
182
|
-
google_cloud_logging:Optional[GoogleCloudLogging] = None
|
184
|
+
dir: str,
|
185
|
+
type: BaseEnums.ServiceLoggerType,
|
186
|
+
service_key: BaseTypes.OptionalString = None,
|
187
|
+
level: BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
188
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = None
|
183
189
|
):
|
184
190
|
super().__init__(
|
185
191
|
dir=dir,
|
@@ -194,11 +200,11 @@ class ServiceLogger(BaseLogger):
|
|
194
200
|
class ClientLogger(BaseLogger):
|
195
201
|
def __init__(
|
196
202
|
self,
|
197
|
-
dir:str,
|
198
|
-
client_key:str,
|
199
|
-
service_key:BaseTypes.OptionalString = None,
|
200
|
-
level:BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
201
|
-
google_cloud_logging:Optional[GoogleCloudLogging] = None
|
203
|
+
dir: str,
|
204
|
+
client_key: str,
|
205
|
+
service_key: BaseTypes.OptionalString = None,
|
206
|
+
level: BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
207
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = None
|
202
208
|
):
|
203
209
|
super().__init__(
|
204
210
|
dir=dir,
|
maleo_foundation/utils/merger.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
from collections.abc import Mapping
|
2
2
|
from typing import Dict
|
3
3
|
|
4
|
-
def deep_merge(*obj:Dict) -> Dict:
|
5
|
-
def merge_dicts(
|
4
|
+
def deep_merge(*obj: Dict) -> Dict:
|
5
|
+
def merge_dicts(
|
6
|
+
a: Dict,
|
7
|
+
b: Dict
|
8
|
+
) -> Dict:
|
6
9
|
result = dict(a)
|
7
10
|
for key, value in b.items():
|
8
11
|
if (
|