maleo-foundation 0.3.46__py3-none-any.whl → 0.3.48__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 +24 -13
- maleo_foundation/authorization.py +2 -1
- maleo_foundation/client/manager.py +22 -21
- maleo_foundation/client/services/__init__.py +16 -7
- maleo_foundation/client/services/encryption/__init__.py +13 -4
- maleo_foundation/client/services/encryption/aes.py +41 -36
- maleo_foundation/client/services/encryption/rsa.py +50 -50
- maleo_foundation/client/services/hash/__init__.py +19 -6
- maleo_foundation/client/services/hash/bcrypt.py +20 -18
- maleo_foundation/client/services/hash/hmac.py +20 -17
- maleo_foundation/client/services/hash/sha256.py +18 -15
- maleo_foundation/client/services/key.py +50 -42
- maleo_foundation/client/services/signature.py +46 -42
- maleo_foundation/client/services/token.py +49 -58
- maleo_foundation/constants.py +12 -19
- maleo_foundation/enums.py +14 -13
- maleo_foundation/expanded_types/__init__.py +2 -3
- maleo_foundation/expanded_types/client.py +30 -34
- maleo_foundation/expanded_types/encryption/__init__.py +2 -1
- maleo_foundation/expanded_types/encryption/aes.py +7 -5
- maleo_foundation/expanded_types/encryption/rsa.py +7 -5
- maleo_foundation/expanded_types/general.py +13 -11
- maleo_foundation/expanded_types/hash.py +7 -5
- maleo_foundation/expanded_types/key.py +8 -6
- maleo_foundation/expanded_types/service.py +30 -34
- maleo_foundation/expanded_types/signature.py +7 -5
- maleo_foundation/expanded_types/token.py +7 -5
- maleo_foundation/extended_types.py +4 -3
- maleo_foundation/managers/cache.py +2 -1
- maleo_foundation/managers/client/base.py +25 -12
- maleo_foundation/managers/client/google/base.py +11 -4
- maleo_foundation/managers/client/google/parameter.py +9 -11
- maleo_foundation/managers/client/google/secret.py +53 -35
- maleo_foundation/managers/client/google/storage.py +52 -22
- maleo_foundation/managers/client/google/subscription.py +37 -39
- maleo_foundation/managers/client/maleo.py +18 -23
- maleo_foundation/managers/configuration.py +5 -9
- maleo_foundation/managers/credential.py +14 -17
- maleo_foundation/managers/db.py +51 -40
- maleo_foundation/managers/middleware.py +9 -9
- maleo_foundation/managers/service.py +47 -54
- maleo_foundation/middlewares/authentication.py +29 -54
- maleo_foundation/middlewares/base.py +83 -72
- maleo_foundation/middlewares/cors.py +8 -7
- maleo_foundation/models/__init__.py +2 -1
- maleo_foundation/models/responses.py +57 -29
- maleo_foundation/models/schemas/__init__.py +2 -1
- maleo_foundation/models/schemas/encryption.py +5 -2
- maleo_foundation/models/schemas/general.py +38 -18
- maleo_foundation/models/schemas/hash.py +2 -1
- maleo_foundation/models/schemas/key.py +5 -2
- maleo_foundation/models/schemas/parameter.py +45 -15
- maleo_foundation/models/schemas/result.py +35 -20
- maleo_foundation/models/schemas/signature.py +5 -2
- maleo_foundation/models/schemas/token.py +5 -2
- maleo_foundation/models/table.py +33 -27
- maleo_foundation/models/transfers/__init__.py +2 -1
- maleo_foundation/models/transfers/general/__init__.py +2 -1
- maleo_foundation/models/transfers/general/configurations/__init__.py +10 -4
- maleo_foundation/models/transfers/general/configurations/cache/__init__.py +3 -2
- maleo_foundation/models/transfers/general/configurations/cache/redis.py +13 -5
- maleo_foundation/models/transfers/general/configurations/client/__init__.py +5 -1
- maleo_foundation/models/transfers/general/configurations/client/maleo.py +38 -12
- maleo_foundation/models/transfers/general/configurations/database.py +5 -2
- maleo_foundation/models/transfers/general/configurations/middleware.py +22 -15
- maleo_foundation/models/transfers/general/configurations/service.py +2 -1
- maleo_foundation/models/transfers/general/credentials.py +2 -1
- maleo_foundation/models/transfers/general/database.py +11 -4
- maleo_foundation/models/transfers/general/key.py +13 -4
- maleo_foundation/models/transfers/general/request.py +28 -9
- maleo_foundation/models/transfers/general/settings.py +12 -22
- maleo_foundation/models/transfers/general/signature.py +4 -2
- maleo_foundation/models/transfers/general/token.py +34 -27
- maleo_foundation/models/transfers/parameters/__init__.py +2 -1
- maleo_foundation/models/transfers/parameters/client.py +15 -19
- maleo_foundation/models/transfers/parameters/encryption/__init__.py +2 -1
- maleo_foundation/models/transfers/parameters/encryption/aes.py +7 -5
- maleo_foundation/models/transfers/parameters/encryption/rsa.py +7 -5
- maleo_foundation/models/transfers/parameters/general.py +15 -13
- maleo_foundation/models/transfers/parameters/hash/__init__.py +2 -1
- maleo_foundation/models/transfers/parameters/hash/bcrypt.py +5 -5
- maleo_foundation/models/transfers/parameters/hash/hmac.py +6 -6
- maleo_foundation/models/transfers/parameters/hash/sha256.py +5 -5
- maleo_foundation/models/transfers/parameters/key.py +9 -8
- maleo_foundation/models/transfers/parameters/service.py +42 -48
- maleo_foundation/models/transfers/parameters/signature.py +7 -4
- maleo_foundation/models/transfers/parameters/token.py +10 -10
- maleo_foundation/models/transfers/results/__init__.py +2 -1
- maleo_foundation/models/transfers/results/client/__init__.py +2 -1
- maleo_foundation/models/transfers/results/client/controllers/__init__.py +2 -1
- maleo_foundation/models/transfers/results/client/controllers/http.py +10 -7
- maleo_foundation/models/transfers/results/client/service.py +12 -6
- maleo_foundation/models/transfers/results/encryption/__init__.py +2 -1
- maleo_foundation/models/transfers/results/encryption/aes.py +13 -5
- maleo_foundation/models/transfers/results/encryption/rsa.py +12 -4
- maleo_foundation/models/transfers/results/hash.py +7 -3
- maleo_foundation/models/transfers/results/key.py +18 -6
- maleo_foundation/models/transfers/results/service/__init__.py +2 -3
- maleo_foundation/models/transfers/results/service/controllers/__init__.py +2 -1
- maleo_foundation/models/transfers/results/service/controllers/rest.py +14 -11
- maleo_foundation/models/transfers/results/service/general.py +16 -10
- maleo_foundation/models/transfers/results/signature.py +12 -4
- maleo_foundation/models/transfers/results/token.py +10 -4
- maleo_foundation/rest_controller_result.py +23 -21
- maleo_foundation/types.py +15 -14
- maleo_foundation/utils/__init__.py +2 -1
- maleo_foundation/utils/cache.py +10 -13
- maleo_foundation/utils/client.py +25 -12
- maleo_foundation/utils/controller.py +59 -37
- maleo_foundation/utils/dependencies/__init__.py +2 -1
- maleo_foundation/utils/dependencies/auth.py +5 -12
- maleo_foundation/utils/dependencies/context.py +3 -4
- maleo_foundation/utils/exceptions.py +50 -28
- maleo_foundation/utils/extractor.py +18 -6
- maleo_foundation/utils/formatter/__init__.py +2 -1
- maleo_foundation/utils/formatter/case.py +5 -4
- maleo_foundation/utils/loaders/__init__.py +2 -1
- maleo_foundation/utils/loaders/credential/__init__.py +2 -1
- maleo_foundation/utils/loaders/credential/google.py +29 -15
- maleo_foundation/utils/loaders/json.py +3 -2
- maleo_foundation/utils/loaders/key/__init__.py +2 -1
- maleo_foundation/utils/loaders/key/rsa.py +26 -13
- maleo_foundation/utils/loaders/yaml.py +2 -1
- maleo_foundation/utils/logging.py +70 -46
- maleo_foundation/utils/merger.py +7 -9
- maleo_foundation/utils/query.py +41 -34
- maleo_foundation/utils/repository.py +29 -16
- maleo_foundation/utils/searcher.py +4 -6
- {maleo_foundation-0.3.46.dist-info → maleo_foundation-0.3.48.dist-info}/METADATA +14 -1
- maleo_foundation-0.3.48.dist-info/RECORD +137 -0
- maleo_foundation/expanded_types/repository.py +0 -68
- maleo_foundation/models/transfers/results/service/repository.py +0 -39
- maleo_foundation-0.3.46.dist-info/RECORD +0 -139
- {maleo_foundation-0.3.46.dist-info → maleo_foundation-0.3.48.dist-info}/WHEEL +0 -0
- {maleo_foundation-0.3.46.dist-info → maleo_foundation-0.3.48.dist-info}/top_level.txt +0 -0
@@ -5,11 +5,10 @@ from google.oauth2.service_account import Credentials
|
|
5
5
|
from pathlib import Path
|
6
6
|
from typing import Optional, Union
|
7
7
|
|
8
|
+
|
8
9
|
class GoogleCredentialsLoader:
|
9
10
|
@staticmethod
|
10
|
-
def load(
|
11
|
-
credentials_path: Optional[Union[Path, str]] = None
|
12
|
-
) -> Credentials:
|
11
|
+
def load(credentials_path: Optional[Union[Path, str]] = None) -> Credentials:
|
13
12
|
"""
|
14
13
|
Load Google service account credentials with guaranteed project_id.
|
15
14
|
Priority:
|
@@ -49,26 +48,37 @@ class GoogleCredentialsLoader:
|
|
49
48
|
"""Load credentials from a service account file."""
|
50
49
|
try:
|
51
50
|
# First, read and validate the service account file
|
52
|
-
with open(credentials_path,
|
51
|
+
with open(credentials_path, "r") as f:
|
53
52
|
service_account_info = json.load(f)
|
54
53
|
|
55
54
|
# Ensure project_id is present in the file
|
56
|
-
if
|
57
|
-
|
55
|
+
if (
|
56
|
+
"project_id" not in service_account_info
|
57
|
+
or not service_account_info["project_id"]
|
58
|
+
):
|
59
|
+
raise ValueError(
|
60
|
+
f"Service account file {credentials_path} does not contain project_id"
|
61
|
+
)
|
58
62
|
|
59
63
|
# Load credentials from the file
|
60
64
|
credentials = Credentials.from_service_account_file(str(credentials_path))
|
61
65
|
|
62
66
|
# Double-check that project_id is available in the credentials object
|
63
67
|
if not credentials.project_id:
|
64
|
-
raise ValueError(
|
68
|
+
raise ValueError(
|
69
|
+
f"Loaded credentials from {credentials_path} do not have project_id"
|
70
|
+
)
|
65
71
|
|
66
72
|
return credentials
|
67
73
|
|
68
74
|
except json.JSONDecodeError as e:
|
69
|
-
raise ValueError(
|
75
|
+
raise ValueError(
|
76
|
+
f"Invalid JSON in credentials file {credentials_path}: {str(e)}"
|
77
|
+
)
|
70
78
|
except Exception as e:
|
71
|
-
raise ValueError(
|
79
|
+
raise ValueError(
|
80
|
+
f"Failed to load credentials from file {credentials_path}: {str(e)}"
|
81
|
+
)
|
72
82
|
|
73
83
|
@staticmethod
|
74
84
|
def _load_from_default() -> Credentials:
|
@@ -110,10 +120,10 @@ class GoogleCredentialsLoader:
|
|
110
120
|
def _get_project_id_from_env() -> str:
|
111
121
|
"""Get project_id from environment variables."""
|
112
122
|
project_id = (
|
113
|
-
os.getenv("GOOGLE_CLOUD_PROJECT")
|
114
|
-
os.getenv("GCLOUD_PROJECT")
|
115
|
-
os.getenv("GCP_PROJECT")
|
116
|
-
os.getenv("PROJECT_ID")
|
123
|
+
os.getenv("GOOGLE_CLOUD_PROJECT")
|
124
|
+
or os.getenv("GCLOUD_PROJECT")
|
125
|
+
or os.getenv("GCP_PROJECT")
|
126
|
+
or os.getenv("PROJECT_ID")
|
117
127
|
)
|
118
128
|
|
119
129
|
if not project_id:
|
@@ -129,10 +139,14 @@ class GoogleCredentialsLoader:
|
|
129
139
|
def validate_credentials(credentials: Credentials) -> None:
|
130
140
|
"""Validate that credentials are service account credentials with project_id."""
|
131
141
|
if not isinstance(credentials, Credentials):
|
132
|
-
raise ValueError(
|
142
|
+
raise ValueError(
|
143
|
+
"Credentials must be google.oauth2.service_account.Credentials"
|
144
|
+
)
|
133
145
|
|
134
146
|
if not credentials.project_id:
|
135
147
|
raise ValueError("Service account credentials must have project_id")
|
136
148
|
|
137
149
|
if not credentials.service_account_email:
|
138
|
-
raise ValueError(
|
150
|
+
raise ValueError(
|
151
|
+
"Service account credentials must have service_account_email"
|
152
|
+
)
|
@@ -2,6 +2,7 @@ import json
|
|
2
2
|
from typing import Dict, List, Union, Any
|
3
3
|
from pathlib import Path
|
4
4
|
|
5
|
+
|
5
6
|
class JSONLoader:
|
6
7
|
@staticmethod
|
7
8
|
def load_from_path(path: Union[Path, str]) -> Union[Dict[str, Any], List[Any]]:
|
@@ -10,9 +11,9 @@ class JSONLoader:
|
|
10
11
|
if not file_path.is_file():
|
11
12
|
raise FileNotFoundError(f"File not found: {file_path}")
|
12
13
|
|
13
|
-
with open(file_path,
|
14
|
+
with open(file_path, "r") as f:
|
14
15
|
return json.load(f)
|
15
16
|
|
16
17
|
@staticmethod
|
17
18
|
def load_from_string(string: str) -> Dict:
|
18
|
-
return json.loads(string)
|
19
|
+
return json.loads(string)
|
@@ -5,21 +5,27 @@ from typing import Optional, Union
|
|
5
5
|
from maleo_foundation.enums import BaseEnums
|
6
6
|
from maleo_foundation.types import BaseTypes
|
7
7
|
|
8
|
+
|
8
9
|
class RSAKeyLoader:
|
9
10
|
@staticmethod
|
10
11
|
def load_with_cryptography(
|
11
|
-
type:BaseEnums.KeyType,
|
12
|
-
data:Optional[Union[bytes, str]] = None,
|
13
|
-
path:Optional[Union[str, Path]] = None,
|
14
|
-
password:Optional[Union[bytes, str]] = None,
|
15
|
-
format:BaseEnums.KeyFormatType = BaseEnums.KeyFormatType.STRING,
|
12
|
+
type: BaseEnums.KeyType,
|
13
|
+
data: Optional[Union[bytes, str]] = None,
|
14
|
+
path: Optional[Union[str, Path]] = None,
|
15
|
+
password: Optional[Union[bytes, str]] = None,
|
16
|
+
format: BaseEnums.KeyFormatType = BaseEnums.KeyFormatType.STRING,
|
16
17
|
) -> Union[bytes, str]:
|
17
18
|
if not isinstance(type, BaseEnums.KeyType):
|
18
19
|
raise TypeError("Invalid key type")
|
19
20
|
|
21
|
+
if data is None and path is None:
|
22
|
+
raise ValueError("Either data or path must be provided")
|
23
|
+
|
20
24
|
if data is not None and path is not None:
|
21
25
|
raise ValueError("Only either data or path will be accepted as parameters")
|
22
26
|
|
27
|
+
key_data: Optional[bytes] = None
|
28
|
+
|
23
29
|
if data is not None:
|
24
30
|
if isinstance(data, bytes):
|
25
31
|
key_data = data
|
@@ -36,6 +42,9 @@ class RSAKeyLoader:
|
|
36
42
|
|
37
43
|
key_data = file_path.read_bytes()
|
38
44
|
|
45
|
+
if key_data is None:
|
46
|
+
raise ValueError("Key data is required")
|
47
|
+
|
39
48
|
if password is not None and not isinstance(password, (str, bytes)):
|
40
49
|
raise TypeError("Invalid passsword type")
|
41
50
|
|
@@ -50,7 +59,7 @@ class RSAKeyLoader:
|
|
50
59
|
private_key_bytes = private_key.private_bytes(
|
51
60
|
encoding=serialization.Encoding.PEM,
|
52
61
|
format=serialization.PrivateFormat.PKCS8,
|
53
|
-
encryption_algorithm=serialization.NoEncryption()
|
62
|
+
encryption_algorithm=serialization.NoEncryption(),
|
54
63
|
)
|
55
64
|
if format == BaseEnums.KeyFormatType.BYTES:
|
56
65
|
return private_key_bytes
|
@@ -61,7 +70,7 @@ class RSAKeyLoader:
|
|
61
70
|
public_key = serialization.load_pem_public_key(key_data)
|
62
71
|
public_key_bytes = public_key.public_bytes(
|
63
72
|
encoding=serialization.Encoding.PEM,
|
64
|
-
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
73
|
+
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
65
74
|
)
|
66
75
|
if format == BaseEnums.KeyFormatType.BYTES:
|
67
76
|
return public_key_bytes
|
@@ -70,9 +79,9 @@ class RSAKeyLoader:
|
|
70
79
|
|
71
80
|
@staticmethod
|
72
81
|
def load_with_pycryptodome(
|
73
|
-
type:BaseEnums.KeyType,
|
74
|
-
extern_key:Union[bytes, str],
|
75
|
-
passphrase:BaseTypes.OptionalString = None,
|
82
|
+
type: BaseEnums.KeyType,
|
83
|
+
extern_key: Union[bytes, str],
|
84
|
+
passphrase: BaseTypes.OptionalString = None,
|
76
85
|
) -> RSA.RsaKey:
|
77
86
|
if not isinstance(type, BaseEnums.KeyType):
|
78
87
|
raise TypeError("Invalid key type")
|
@@ -83,11 +92,15 @@ class RSAKeyLoader:
|
|
83
92
|
if type == BaseEnums.KeyType.PRIVATE:
|
84
93
|
private_key = RSA.import_key(extern_key=extern_key, passphrase=passphrase)
|
85
94
|
if not private_key.has_private():
|
86
|
-
raise TypeError(
|
95
|
+
raise TypeError(
|
96
|
+
"Invalid chosen key type, the private key did not has private inside it"
|
97
|
+
)
|
87
98
|
return private_key
|
88
99
|
|
89
100
|
if type == BaseEnums.KeyType.PUBLIC:
|
90
101
|
public_key = RSA.import_key(extern_key=extern_key)
|
91
102
|
if public_key.has_private():
|
92
|
-
raise TypeError(
|
93
|
-
|
103
|
+
raise TypeError(
|
104
|
+
"Invalid chosen key type, the public key did has private inside it"
|
105
|
+
)
|
106
|
+
return public_key
|
@@ -2,6 +2,7 @@ import yaml
|
|
2
2
|
from pathlib import Path
|
3
3
|
from typing import Dict, Union
|
4
4
|
|
5
|
+
|
5
6
|
class YAMLLoader:
|
6
7
|
@staticmethod
|
7
8
|
def load_from_path(path: Union[Path, str]) -> Dict:
|
@@ -15,4 +16,4 @@ class YAMLLoader:
|
|
15
16
|
|
16
17
|
@staticmethod
|
17
18
|
def load_from_string(string: str) -> Dict:
|
18
|
-
return yaml.safe_load(string)
|
19
|
+
return yaml.safe_load(string)
|
@@ -11,21 +11,25 @@ from maleo_foundation.enums import BaseEnums
|
|
11
11
|
from maleo_foundation.types import BaseTypes
|
12
12
|
from maleo_foundation.utils.loaders.credential.google import GoogleCredentialsLoader
|
13
13
|
|
14
|
+
|
14
15
|
class GoogleCloudLogging:
|
15
|
-
def __init__(
|
16
|
-
self
|
17
|
-
|
18
|
-
|
19
|
-
self._credentials = GoogleCredentialsLoader.load(credentials_path=credentials_path)
|
16
|
+
def __init__(self, credentials_path: Optional[Union[Path, str]] = None) -> None:
|
17
|
+
self._credentials = GoogleCredentialsLoader.load(
|
18
|
+
credentials_path=credentials_path
|
19
|
+
)
|
20
20
|
self._client = Client(credentials=self._credentials)
|
21
21
|
self._client.setup_logging()
|
22
22
|
|
23
23
|
@property
|
24
24
|
def credentials(self) -> Credentials:
|
25
|
+
if self._credentials is None:
|
26
|
+
raise ValueError("Credentials have not been initialized.")
|
25
27
|
return self._credentials
|
26
28
|
|
27
29
|
@property
|
28
30
|
def client(self) -> Client:
|
31
|
+
if self._client is None:
|
32
|
+
raise ValueError("Client has not been initialized.")
|
29
33
|
return self._client
|
30
34
|
|
31
35
|
def dispose(self) -> None:
|
@@ -34,18 +38,21 @@ class GoogleCloudLogging:
|
|
34
38
|
if self._client is not None:
|
35
39
|
self._client = None
|
36
40
|
|
37
|
-
def create_handler(
|
38
|
-
self,
|
39
|
-
name: str
|
40
|
-
) -> CloudLoggingHandler:
|
41
|
+
def create_handler(self, name: str) -> CloudLoggingHandler:
|
41
42
|
return CloudLoggingHandler(client=self._client, name=name)
|
42
43
|
|
44
|
+
|
43
45
|
class SimpleConfig(BaseModel):
|
44
46
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
45
47
|
|
46
48
|
dir: str = Field(..., description="Log's directory")
|
47
|
-
level: BaseEnums.LoggerLevel = Field(
|
48
|
-
|
49
|
+
level: BaseEnums.LoggerLevel = Field(
|
50
|
+
BaseEnums.LoggerLevel.INFO, description="Log's level"
|
51
|
+
)
|
52
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = Field(
|
53
|
+
default_factory=GoogleCloudLogging, description="Google cloud logging"
|
54
|
+
)
|
55
|
+
|
49
56
|
|
50
57
|
class BaseLogger(logging.Logger):
|
51
58
|
def __init__(
|
@@ -55,50 +62,58 @@ class BaseLogger(logging.Logger):
|
|
55
62
|
service_key: BaseTypes.OptionalString = None,
|
56
63
|
client_key: BaseTypes.OptionalString = None,
|
57
64
|
level: BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
58
|
-
google_cloud_logging: Optional[GoogleCloudLogging] = None
|
65
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = None,
|
59
66
|
):
|
60
|
-
self._type = type
|
67
|
+
self._type = type # * Declare logger type
|
61
68
|
|
62
|
-
|
69
|
+
# * Ensure service_key exists
|
63
70
|
self._service_key = service_key or os.getenv("SERVICE_KEY")
|
64
71
|
if self._service_key is None:
|
65
|
-
raise ValueError(
|
72
|
+
raise ValueError(
|
73
|
+
"SERVICE_KEY environment variable must be set if 'service_key' is set to None"
|
74
|
+
)
|
66
75
|
|
67
|
-
self._client_key = client_key
|
76
|
+
self._client_key = client_key # * Declare client key
|
68
77
|
|
69
|
-
|
78
|
+
# * Ensure client_key is valid if logger type is a client
|
70
79
|
if self._type == BaseEnums.LoggerType.CLIENT and self._client_key is None:
|
71
|
-
raise ValueError(
|
80
|
+
raise ValueError(
|
81
|
+
"'client_key' parameter must be provided if 'logger_type' is 'client'"
|
82
|
+
)
|
72
83
|
|
73
|
-
|
84
|
+
# * Define logger name
|
74
85
|
if self._type == BaseEnums.LoggerType.CLIENT:
|
75
86
|
self._name = f"{self._service_key} - {self._type} - {self._client_key}"
|
76
87
|
else:
|
77
88
|
self._name = f"{self._service_key} - {self._type}"
|
78
89
|
|
79
|
-
super().__init__(self._name, level)
|
90
|
+
super().__init__(self._name, level) # * Init the superclass's logger
|
80
91
|
|
81
|
-
|
92
|
+
# * Clear existing handlers to prevent duplicates
|
82
93
|
for handler in list(self.handlers):
|
83
94
|
self.removeHandler(handler)
|
84
95
|
handler.close()
|
85
96
|
|
86
|
-
|
87
|
-
formatter = logging.Formatter(
|
97
|
+
# * Formatter for logs
|
98
|
+
formatter = logging.Formatter(
|
99
|
+
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
100
|
+
)
|
88
101
|
|
89
|
-
|
102
|
+
# * Console handler
|
90
103
|
console_handler = logging.StreamHandler()
|
91
104
|
console_handler.setFormatter(formatter)
|
92
105
|
self.addHandler(console_handler)
|
93
106
|
|
94
|
-
|
107
|
+
# * Google Cloud Logging handler (If enabled)
|
95
108
|
if google_cloud_logging is not None:
|
96
|
-
cloud_logging_handler = google_cloud_logging.create_handler(
|
109
|
+
cloud_logging_handler = google_cloud_logging.create_handler(
|
110
|
+
name=self._name.replace(" ", "")
|
111
|
+
)
|
97
112
|
self.addHandler(cloud_logging_handler)
|
98
113
|
else:
|
99
114
|
self.info("Cloud logging is not configured.")
|
100
115
|
|
101
|
-
|
116
|
+
# * Define log directory
|
102
117
|
if self._type == BaseEnums.LoggerType.CLIENT:
|
103
118
|
log_dir = f"{self._type}/{self._client_key}"
|
104
119
|
else:
|
@@ -106,11 +121,11 @@ class BaseLogger(logging.Logger):
|
|
106
121
|
self._log_dir = os.path.join(dir, log_dir)
|
107
122
|
os.makedirs(self._log_dir, exist_ok=True)
|
108
123
|
|
109
|
-
|
124
|
+
# * Generate timestamped filename
|
110
125
|
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
111
126
|
log_filename = os.path.join(self._log_dir, f"{timestamp}.log")
|
112
127
|
|
113
|
-
|
128
|
+
# * File handler
|
114
129
|
file_handler = logging.FileHandler(log_filename, mode="a")
|
115
130
|
file_handler.setFormatter(formatter)
|
116
131
|
self.addHandler(file_handler)
|
@@ -121,6 +136,8 @@ class BaseLogger(logging.Logger):
|
|
121
136
|
|
122
137
|
@property
|
123
138
|
def service(self) -> str:
|
139
|
+
if self._service_key is None:
|
140
|
+
raise ValueError("Service key has not been initialized.")
|
124
141
|
return self._service_key
|
125
142
|
|
126
143
|
@property
|
@@ -142,13 +159,14 @@ class BaseLogger(logging.Logger):
|
|
142
159
|
handler.close()
|
143
160
|
self.handlers.clear()
|
144
161
|
|
162
|
+
|
145
163
|
class ApplicationLogger(BaseLogger):
|
146
164
|
def __init__(
|
147
165
|
self,
|
148
166
|
dir: str,
|
149
167
|
service_key: BaseTypes.OptionalString = None,
|
150
168
|
level: BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
151
|
-
google_cloud_logging: Optional[GoogleCloudLogging] = None
|
169
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = None,
|
152
170
|
):
|
153
171
|
super().__init__(
|
154
172
|
dir=dir,
|
@@ -156,16 +174,17 @@ class ApplicationLogger(BaseLogger):
|
|
156
174
|
service_key=service_key,
|
157
175
|
client_key=None,
|
158
176
|
level=level,
|
159
|
-
google_cloud_logging=google_cloud_logging
|
177
|
+
google_cloud_logging=google_cloud_logging,
|
160
178
|
)
|
161
179
|
|
180
|
+
|
162
181
|
class CacheLogger(BaseLogger):
|
163
182
|
def __init__(
|
164
183
|
self,
|
165
184
|
dir: str,
|
166
185
|
service_key: BaseTypes.OptionalString = None,
|
167
186
|
level: BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
168
|
-
google_cloud_logging: Optional[GoogleCloudLogging] = None
|
187
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = None,
|
169
188
|
):
|
170
189
|
super().__init__(
|
171
190
|
dir=dir,
|
@@ -173,9 +192,10 @@ class CacheLogger(BaseLogger):
|
|
173
192
|
service_key=service_key,
|
174
193
|
client_key=None,
|
175
194
|
level=level,
|
176
|
-
google_cloud_logging=google_cloud_logging
|
195
|
+
google_cloud_logging=google_cloud_logging,
|
177
196
|
)
|
178
197
|
|
198
|
+
|
179
199
|
class ClientLogger(BaseLogger):
|
180
200
|
def __init__(
|
181
201
|
self,
|
@@ -183,7 +203,7 @@ class ClientLogger(BaseLogger):
|
|
183
203
|
client_key: str,
|
184
204
|
service_key: BaseTypes.OptionalString = None,
|
185
205
|
level: BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
186
|
-
google_cloud_logging: Optional[GoogleCloudLogging] = None
|
206
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = None,
|
187
207
|
):
|
188
208
|
super().__init__(
|
189
209
|
dir=dir,
|
@@ -191,16 +211,17 @@ class ClientLogger(BaseLogger):
|
|
191
211
|
service_key=service_key,
|
192
212
|
client_key=client_key,
|
193
213
|
level=level,
|
194
|
-
google_cloud_logging=google_cloud_logging
|
214
|
+
google_cloud_logging=google_cloud_logging,
|
195
215
|
)
|
196
216
|
|
217
|
+
|
197
218
|
class DatabaseLogger(BaseLogger):
|
198
219
|
def __init__(
|
199
220
|
self,
|
200
221
|
dir: str,
|
201
222
|
service_key: BaseTypes.OptionalString = None,
|
202
|
-
level
|
203
|
-
google_cloud_logging
|
223
|
+
level=BaseEnums.LoggerLevel.INFO,
|
224
|
+
google_cloud_logging=None,
|
204
225
|
):
|
205
226
|
super().__init__(
|
206
227
|
dir=dir,
|
@@ -208,16 +229,17 @@ class DatabaseLogger(BaseLogger):
|
|
208
229
|
service_key=service_key,
|
209
230
|
client_key=None,
|
210
231
|
level=level,
|
211
|
-
google_cloud_logging=google_cloud_logging
|
232
|
+
google_cloud_logging=google_cloud_logging,
|
212
233
|
)
|
213
234
|
|
235
|
+
|
214
236
|
class MiddlewareLogger(BaseLogger):
|
215
237
|
def __init__(
|
216
238
|
self,
|
217
239
|
dir: str,
|
218
240
|
service_key: BaseTypes.OptionalString = None,
|
219
|
-
level
|
220
|
-
google_cloud_logging
|
241
|
+
level=BaseEnums.LoggerLevel.INFO,
|
242
|
+
google_cloud_logging=None,
|
221
243
|
):
|
222
244
|
super().__init__(
|
223
245
|
dir=dir,
|
@@ -225,16 +247,17 @@ class MiddlewareLogger(BaseLogger):
|
|
225
247
|
service_key=service_key,
|
226
248
|
client_key=None,
|
227
249
|
level=level,
|
228
|
-
google_cloud_logging=google_cloud_logging
|
250
|
+
google_cloud_logging=google_cloud_logging,
|
229
251
|
)
|
230
252
|
|
253
|
+
|
231
254
|
class RepositoryLogger(BaseLogger):
|
232
255
|
def __init__(
|
233
256
|
self,
|
234
257
|
dir: str,
|
235
258
|
service_key: BaseTypes.OptionalString = None,
|
236
259
|
level: BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
237
|
-
google_cloud_logging: Optional[GoogleCloudLogging] = None
|
260
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = None,
|
238
261
|
):
|
239
262
|
super().__init__(
|
240
263
|
dir=dir,
|
@@ -242,16 +265,17 @@ class RepositoryLogger(BaseLogger):
|
|
242
265
|
service_key=service_key,
|
243
266
|
client_key=None,
|
244
267
|
level=level,
|
245
|
-
google_cloud_logging=google_cloud_logging
|
268
|
+
google_cloud_logging=google_cloud_logging,
|
246
269
|
)
|
247
270
|
|
271
|
+
|
248
272
|
class ServiceLogger(BaseLogger):
|
249
273
|
def __init__(
|
250
274
|
self,
|
251
275
|
dir: str,
|
252
276
|
service_key: BaseTypes.OptionalString = None,
|
253
277
|
level: BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
|
254
|
-
google_cloud_logging: Optional[GoogleCloudLogging] = None
|
278
|
+
google_cloud_logging: Optional[GoogleCloudLogging] = None,
|
255
279
|
):
|
256
280
|
super().__init__(
|
257
281
|
dir=dir,
|
@@ -259,5 +283,5 @@ class ServiceLogger(BaseLogger):
|
|
259
283
|
service_key=service_key,
|
260
284
|
client_key=None,
|
261
285
|
level=level,
|
262
|
-
google_cloud_logging=google_cloud_logging
|
263
|
-
)
|
286
|
+
google_cloud_logging=google_cloud_logging,
|
287
|
+
)
|
maleo_foundation/utils/merger.py
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
from collections.abc import Mapping
|
2
|
-
from typing import Dict
|
2
|
+
from typing import Dict, Any
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
) -> Dict:
|
9
|
-
result = dict(a)
|
4
|
+
|
5
|
+
def deep_merge(*obj: Dict[str, Any]) -> Dict[str, Any]:
|
6
|
+
def merge_dicts(a: Mapping[str, Any], b: Mapping[str, Any]) -> Dict[str, Any]:
|
7
|
+
result = dict(a) # create a mutable copy
|
10
8
|
for key, value in b.items():
|
11
9
|
if (
|
12
10
|
key in result
|
@@ -18,7 +16,7 @@ def deep_merge(*obj: Dict) -> Dict:
|
|
18
16
|
result[key] = value
|
19
17
|
return result
|
20
18
|
|
21
|
-
merged = {}
|
19
|
+
merged: Dict[str, Any] = {}
|
22
20
|
for ob in obj:
|
23
21
|
merged = merge_dicts(merged, ob)
|
24
|
-
return merged
|
22
|
+
return merged
|