maleo-foundation 0.1.42__tar.gz → 0.1.44__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 (79) hide show
  1. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/PKG-INFO +1 -1
  2. maleo_foundation-0.1.44/maleo_foundation/managers/client/base.py +42 -0
  3. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/managers/client/google/base.py +3 -8
  4. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/managers/client/google/secret.py +4 -16
  5. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/managers/client/google/storage.py +5 -18
  6. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/managers/client/maleo.py +6 -10
  7. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/managers/db.py +22 -1
  8. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/managers/service.py +12 -171
  9. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/__init__.py +2 -0
  10. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/logging.py +15 -43
  11. maleo_foundation-0.1.44/maleo_foundation/utils/mergers.py +23 -0
  12. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation.egg-info/PKG-INFO +1 -1
  13. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation.egg-info/SOURCES.txt +1 -0
  14. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/pyproject.toml +1 -1
  15. maleo_foundation-0.1.42/maleo_foundation/managers/client/base.py +0 -52
  16. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/README.md +0 -0
  17. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/__init__.py +0 -0
  18. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/authentication.py +0 -0
  19. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/constants.py +0 -0
  20. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/enums.py +0 -0
  21. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/expanded_types/__init__.py +0 -0
  22. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/expanded_types/client.py +0 -0
  23. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/expanded_types/general.py +0 -0
  24. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/expanded_types/query.py +0 -0
  25. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/expanded_types/service.py +0 -0
  26. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/expanded_types/token.py +0 -0
  27. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/extended_types.py +0 -0
  28. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/managers/__init__.py +0 -0
  29. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/managers/client/__init__.py +0 -0
  30. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/managers/client/google/__init__.py +0 -0
  31. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/managers/middleware.py +0 -0
  32. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/middlewares/__init__.py +0 -0
  33. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/middlewares/authentication.py +0 -0
  34. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/middlewares/base.py +0 -0
  35. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/middlewares/cors.py +0 -0
  36. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/__init__.py +0 -0
  37. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/responses.py +0 -0
  38. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/schemas/__init__.py +0 -0
  39. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/schemas/general.py +0 -0
  40. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/schemas/parameter.py +0 -0
  41. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/schemas/result.py +0 -0
  42. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/schemas/token.py +0 -0
  43. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/table.py +0 -0
  44. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/__init__.py +0 -0
  45. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/general/__init__.py +0 -0
  46. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/general/token.py +0 -0
  47. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/parameters/__init__.py +0 -0
  48. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/parameters/client.py +0 -0
  49. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/parameters/general.py +0 -0
  50. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/parameters/service.py +0 -0
  51. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/parameters/token.py +0 -0
  52. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/__init__.py +0 -0
  53. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/client/__init__.py +0 -0
  54. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/client/controllers/__init__.py +0 -0
  55. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/client/controllers/http.py +0 -0
  56. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/client/service.py +0 -0
  57. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/service/__init__.py +0 -0
  58. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/service/controllers/__init__.py +0 -0
  59. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/service/controllers/rest.py +0 -0
  60. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/service/general.py +0 -0
  61. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/service/query.py +0 -0
  62. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/models/transfers/results/token.py +0 -0
  63. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/services/__init__.py +0 -0
  64. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/services/token.py +0 -0
  65. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/types.py +0 -0
  66. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/controller.py +0 -0
  67. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/exceptions.py +0 -0
  68. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/extractor.py +0 -0
  69. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/formatter/__init__.py +0 -0
  70. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/formatter/case.py +0 -0
  71. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/loaders/__init__.py +0 -0
  72. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/loaders/json.py +0 -0
  73. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/loaders/key.py +0 -0
  74. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/loaders/yaml.py +0 -0
  75. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation/utils/query.py +0 -0
  76. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation.egg-info/dependency_links.txt +0 -0
  77. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation.egg-info/requires.txt +0 -0
  78. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/maleo_foundation.egg-info/top_level.txt +0 -0
  79. {maleo_foundation-0.1.42 → maleo_foundation-0.1.44}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo_foundation
3
- Version: 0.1.42
3
+ Version: 0.1.44
4
4
  Summary: Foundation package for Maleo
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: MIT
@@ -0,0 +1,42 @@
1
+ from maleo_foundation.utils.logging import ClientLogger
2
+ from maleo_foundation.managers.service import ServiceManager
3
+
4
+ class ClientManager:
5
+ def __init__(
6
+ self,
7
+ key:str,
8
+ name:str,
9
+ service_manager:ServiceManager
10
+ ) -> None:
11
+ self._key = key
12
+ self._name = name
13
+ self._service_manager = service_manager
14
+ self._initialize_logger()
15
+ self._logger.info("Initializing client manager")
16
+
17
+ def _initialize_logger(self) -> None:
18
+ self._logger = ClientLogger(client_key=self._key, service_key=self._service_manager.configs.service.key, **self._service_manager.log_config.model_dump())
19
+
20
+ @property
21
+ def key(self) -> str:
22
+ return self._key
23
+
24
+ @property
25
+ def name(self) -> str:
26
+ return self._name
27
+
28
+ @property
29
+ def service_manager(self) -> ServiceManager:
30
+ return self._service_manager
31
+
32
+ @property
33
+ def logger(self) -> ClientLogger:
34
+ return self._logger
35
+
36
+ @property
37
+ def credentials(self):
38
+ raise NotImplementedError()
39
+
40
+ @property
41
+ def client(self):
42
+ raise NotImplementedError()
@@ -1,24 +1,19 @@
1
1
  import os
2
2
  from google.auth import default
3
3
  from google.oauth2 import service_account
4
- from typing import Optional
5
- from maleo_foundation.enums import BaseEnums
6
4
  from maleo_foundation.types import BaseTypes
7
5
  from maleo_foundation.managers.client.base import ClientManager
8
- from maleo_foundation.utils.logging import GoogleCloudLogging
6
+ from maleo_foundation.managers.service import ServiceManager
9
7
 
10
8
  class GoogleClientManager(ClientManager):
11
9
  def __init__(
12
10
  self,
13
11
  key:str,
14
12
  name:str,
15
- logs_dir:str,
16
- service_key:BaseTypes.OptionalString=None,
17
- level:BaseEnums.LoggerLevel=BaseEnums.LoggerLevel.INFO,
18
- google_cloud_logging:Optional[GoogleCloudLogging]=None,
13
+ service_manager:ServiceManager,
19
14
  credentials_path:BaseTypes.OptionalString=None
20
15
  ) -> None:
21
- super().__init__(key, name, logs_dir, service_key, level, google_cloud_logging)
16
+ super().__init__(key, name, service_manager)
22
17
  credentials_path = credentials_path or os.getenv("GOOGLE_CREDENTIALS_PATH")
23
18
  try:
24
19
  if credentials_path is not None:
@@ -2,31 +2,19 @@ from google.api_core import retry
2
2
  from google.api_core.exceptions import NotFound
3
3
  from google.cloud import secretmanager
4
4
  from typing import Optional
5
- from maleo_foundation.enums import BaseEnums
6
5
  from maleo_foundation.types import BaseTypes
7
- from maleo_foundation.utils.logging import GoogleCloudLogging
6
+ from maleo_foundation.managers.service import ServiceManager
8
7
  from .base import GoogleClientManager
9
8
 
10
9
  class GoogleSecretManager(GoogleClientManager):
11
10
  def __init__(
12
11
  self,
13
- logs_dir:str,
14
- service_key:BaseTypes.OptionalString = None,
15
- level:BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
16
- google_cloud_logging:Optional[GoogleCloudLogging] = None,
17
- credentials_path:BaseTypes.OptionalString=None
12
+ service_manager:ServiceManager,
13
+ credentials_path:BaseTypes.OptionalString = None
18
14
  ) -> None:
19
15
  key = "google-secret-manager"
20
16
  name = "GoogleSecretManager"
21
- super().__init__(
22
- key=key,
23
- name=name,
24
- logs_dir=logs_dir,
25
- service_key=service_key,
26
- level=level,
27
- google_cloud_logging=google_cloud_logging,
28
- credentials_path=credentials_path
29
- )
17
+ super().__init__(key, name, service_manager, credentials_path)
30
18
  self._client = secretmanager.SecretManagerServiceClient(credentials=self._credentials)
31
19
  self._logger.info("Client manager initialized successfully")
32
20
 
@@ -1,33 +1,20 @@
1
1
  import os
2
2
  from datetime import timedelta
3
3
  from google.cloud.storage import Bucket, Client
4
- from typing import Optional
5
- from maleo_foundation.enums import BaseEnums
6
4
  from maleo_foundation.types import BaseTypes
7
- from maleo_foundation.utils.logging import GoogleCloudLogging
5
+ from maleo_foundation.managers.service import ServiceManager
8
6
  from .base import GoogleClientManager
9
7
 
10
8
  class GoogleCloudStorage(GoogleClientManager):
11
9
  def __init__(
12
10
  self,
13
- logs_dir:str,
14
- service_key:BaseTypes.OptionalString = None,
15
- level:BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
16
- google_cloud_logging:Optional[GoogleCloudLogging] = None,
17
- credentials_path:BaseTypes.OptionalString=None,
18
- bucket_name:BaseTypes.OptionalString=None
11
+ service_manager:ServiceManager,
12
+ credentials_path:BaseTypes.OptionalString = None,
13
+ bucket_name:BaseTypes.OptionalString = None
19
14
  ) -> None:
20
15
  key = "google-cloud-storage"
21
16
  name = "GoogleCloudStorage"
22
- super().__init__(
23
- key=key,
24
- name=name,
25
- logs_dir=logs_dir,
26
- service_key=service_key,
27
- level=level,
28
- google_cloud_logging=google_cloud_logging,
29
- credentials_path=credentials_path
30
- )
17
+ super().__init__(key, name, service_manager, credentials_path)
31
18
  self._client = Client(credentials=self._credentials)
32
19
  self._bucket_name = bucket_name or os.getenv("GCS_BUCKET_NAME")
33
20
  if self._bucket_name is None:
@@ -1,11 +1,10 @@
1
1
  import httpx
2
2
  from contextlib import asynccontextmanager
3
3
  from pydantic import BaseModel, Field
4
- from typing import AsyncGenerator, Optional
5
- from maleo_foundation.enums import BaseEnums
6
- from maleo_foundation.types import BaseTypes
7
- from maleo_foundation.utils.logging import GoogleCloudLogging, ClientLogger
4
+ from typing import AsyncGenerator
5
+ from maleo_foundation.utils.logging import ClientLogger
8
6
  from maleo_foundation.managers.client.base import ClientManager
7
+ from maleo_foundation.managers.service import ServiceManager
9
8
 
10
9
  class URL(BaseModel):
11
10
  base:str = Field(..., description="Base URL")
@@ -93,13 +92,10 @@ class MaleoClientManager(ClientManager):
93
92
  self,
94
93
  key:str,
95
94
  name:str,
96
- logs_dir:str,
97
- service_key:BaseTypes.OptionalString=None,
98
- level:BaseEnums.LoggerLevel=BaseEnums.LoggerLevel.INFO,
99
- google_cloud_logging:Optional[GoogleCloudLogging]=None,
100
- url:BaseTypes.OptionalString = None
95
+ url:str,
96
+ service_manager:ServiceManager
101
97
  ):
102
- super().__init__(key, name, logs_dir, service_key, level, google_cloud_logging)
98
+ super().__init__(key, name, service_manager)
103
99
  self._url = url
104
100
 
105
101
  def _initialize_controllers(self) -> None:
@@ -1,11 +1,12 @@
1
1
  import os
2
2
  from contextlib import contextmanager
3
+ from pydantic import BaseModel, Field, model_validator
3
4
  from sqlalchemy import MetaData
4
5
  from sqlalchemy.engine import Engine, create_engine
5
6
  from sqlalchemy.exc import SQLAlchemyError
6
7
  from sqlalchemy.ext.declarative import DeclarativeMeta
7
8
  from sqlalchemy.orm import sessionmaker, Session, declarative_base
8
- from typing import Generator
9
+ from typing import Dict, Generator
9
10
  from maleo_foundation.types import BaseTypes
10
11
  from maleo_foundation.utils.logging import ServiceLogger
11
12
 
@@ -57,6 +58,26 @@ class SessionManager:
57
58
  self._logger.info("SessionManager disposed successfully")
58
59
  self._logger = None
59
60
 
61
+ class DatabaseConfigurations(BaseModel):
62
+ username:str = Field("postgres", description="Database user's username")
63
+ password:str = Field(..., description="Database user's password")
64
+ host:str = Field(..., description="Database's host")
65
+ port:int = Field(5432, description="Database's port")
66
+ database:str = Field(..., description="Database")
67
+
68
+ @model_validator(mode='before')
69
+ @classmethod
70
+ def populate_password(cls, values:Dict):
71
+ env_value = os.getenv("DB_PASSWORD")
72
+ if env_value is None:
73
+ raise ValueError("'DB_PASSWORD' environmet variable must be set.")
74
+ values["password"] = env_value
75
+ return values
76
+
77
+ @property
78
+ def url(self) -> str:
79
+ return f"postgresql://{self.username}:{self.password}@{self.host}:{self.port}/{self.database}"
80
+
60
81
  class DatabaseManager:
61
82
  def __init__(
62
83
  self,
@@ -1,36 +1,24 @@
1
- import json
2
- import os
3
1
  from fastapi import FastAPI, APIRouter
4
2
  from fastapi.exceptions import RequestValidationError
5
3
  from starlette.exceptions import HTTPException
6
4
  from starlette.types import Lifespan, AppType
7
5
  from pydantic_settings import BaseSettings
8
- from pydantic import BaseModel, Field, model_validator
6
+ from pydantic import BaseModel, Field
9
7
  from sqlalchemy import MetaData
10
- from typing import Dict, Optional, Type
8
+ from typing import Optional
11
9
  from maleo_foundation.enums import BaseEnums
12
10
  from maleo_foundation.models.transfers.general.token import BaseTokenGeneralTransfers
13
11
  from maleo_foundation.models.transfers.parameters.token import BaseTokenParametersTransfers
14
- from maleo_foundation.managers.client.google.secret import GoogleSecretManager
15
- from maleo_foundation.managers.client.google.storage import GoogleCloudStorage
16
- from maleo_foundation.managers.client.maleo import MaleoClientManager
17
- from maleo_foundation.managers.db import DatabaseManager
12
+ from maleo_foundation.managers.db import DatabaseConfigurations, DatabaseManager
18
13
  from maleo_foundation.managers.middleware import MiddlewareConfigurations, BaseMiddlewareConfigurations, CORSMiddlewareConfigurations, GeneralMiddlewareConfigurations, MiddlewareLoggers, MiddlewareManager
19
14
  from maleo_foundation.middlewares.base import RequestProcessor
20
15
  from maleo_foundation.services.token import BaseTokenService
21
- from maleo_foundation.types import BaseTypes
22
16
  from maleo_foundation.utils.exceptions import BaseExceptions
23
17
  from maleo_foundation.utils.loaders.json import JSONLoader
24
18
  from maleo_foundation.utils.loaders.key import KeyLoader
25
19
  from maleo_foundation.utils.loaders.yaml import YAMLLoader
26
- from maleo_foundation.utils.logging import GoogleCloudLogging, ServiceLogger, MiddlewareLogger
27
-
28
- class LogConfig(BaseModel):
29
- logs_dir:str = Field(..., description="Logs directory")
30
- google_cloud_logging:GoogleCloudLogging = Field(..., description="Google cloud's logging")
31
-
32
- class Config:
33
- arbitrary_types_allowed=True
20
+ from maleo_foundation.utils.logging import SimpleConfig, ServiceLogger, MiddlewareLogger
21
+ from maleo_foundation.utils.mergers import BaseMergers
34
22
 
35
23
  class Settings(BaseSettings):
36
24
  ENVIRONMENT:BaseEnums.EnvironmentType = Field(..., description="Environment")
@@ -86,26 +74,6 @@ class ServiceConfigurations(BaseModel):
86
74
  host:str = Field(..., description="Service's host")
87
75
  port:int = Field(..., description="Service's port")
88
76
 
89
- class DatabaseConfigurations(BaseModel):
90
- username:str = Field("postgres", description="Database user's username")
91
- password:str = Field(..., description="Database user's password")
92
- host:str = Field(..., description="Database's host")
93
- port:int = Field(5432, description="Database's port")
94
- database:str = Field(..., description="Database")
95
-
96
- @model_validator(mode='before')
97
- @classmethod
98
- def populate_password(cls, values:Dict):
99
- env_value = os.getenv("DB_PASSWORD")
100
- if env_value is None:
101
- raise ValueError("'DB_PASSWORD' environmet variable must be set.")
102
- values["password"] = env_value
103
- return values
104
-
105
- @property
106
- def url(self) -> str:
107
- return f"postgresql://{self.username}:{self.password}@{self.host}:{self.port}/{self.database}"
108
-
109
77
  class RuntimeConfigurations(BaseModel):
110
78
  service:ServiceConfigurations = Field(..., description="Service's configurations")
111
79
  middleware:MiddlewareRuntimeConfigurations = Field(..., description="Middleware's runtime configurations")
@@ -180,71 +148,14 @@ class Loggers(BaseModel):
180
148
  class Config:
181
149
  arbitrary_types_allowed=True
182
150
 
183
- class GoogleClientManagers(BaseModel):
184
- secret:GoogleSecretManager = Field(..., description="Google secret manager client manager")
185
- storage:GoogleCloudStorage = Field(..., description="Google cloud storage client manager")
186
-
187
- class Config:
188
- arbitrary_types_allowed=True
189
-
190
- class MaleoClientManagerClasses(BaseModel):
191
- metadata:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoMetadata client manager")
192
- security:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoSecurity client manager")
193
- storage:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoStorage client manager")
194
- identity:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoIdentity client manager")
195
- access:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoAccess client manager")
196
- soapie:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoSOAPIE client manager")
197
- fhir:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoFHIR client manager")
198
- dicom:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoDICOM client manager")
199
- scribe:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoScribe client manager")
200
- cds:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoCDS client manager")
201
- imaging:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoImaging client manager")
202
- mcu:Optional[Type[MaleoClientManager]] = Field(None, description="MaleoMCU client manager")
203
-
204
- class Config:
205
- arbitrary_types_allowed=True
206
-
207
- class MaleoClientManagers(BaseModel):
208
- metadata:Optional[MaleoClientManager] = Field(None, description="MaleoMetadata client manager")
209
- security:Optional[MaleoClientManager] = Field(None, description="MaleoSecurity client manager")
210
- storage:Optional[MaleoClientManager] = Field(None, description="MaleoStorage client manager")
211
- identity:Optional[MaleoClientManager] = Field(None, description="MaleoIdentity client manager")
212
- access:Optional[MaleoClientManager] = Field(None, description="MaleoAccess client manager")
213
- soapie:Optional[MaleoClientManager] = Field(None, description="MaleoSOAPIE client manager")
214
- fhir:Optional[MaleoClientManager] = Field(None, description="MaleoFHIR client manager")
215
- dicom:Optional[MaleoClientManager] = Field(None, description="MaleoDICOM client manager")
216
- scribe:Optional[MaleoClientManager] = Field(None, description="MaleoScribe client manager")
217
- cds:Optional[MaleoClientManager] = Field(None, description="MaleoCDS client manager")
218
- imaging:Optional[MaleoClientManager] = Field(None, description="MaleoImaging client manager")
219
- mcu:Optional[MaleoClientManager] = Field(None, description="MaleoMCU client manager")
220
-
221
- class Config:
222
- arbitrary_types_allowed=True
223
-
224
- class ClientManagers(BaseModel):
225
- google:GoogleClientManagers = Field(..., description="Google client's managers")
226
- maleo:MaleoClientManagers = Field(..., description="Maleo client's managers")
227
-
228
- class Config:
229
- arbitrary_types_allowed=True
230
-
231
151
  class ServiceManager:
232
152
  def __init__(
233
153
  self,
234
154
  db_metadata:MetaData,
235
- base_dir:BaseTypes.OptionalString = None,
236
- settings:Optional[Settings] = None,
237
- google_cloud_logging:Optional[GoogleCloudLogging] = None,
238
- maleo_client_manager_classes:Optional[MaleoClientManagerClasses] = None
155
+ log_config:SimpleConfig,
156
+ settings:Optional[Settings] = None
239
157
  ):
240
- self._db_metadata = db_metadata
241
-
242
- if base_dir is None:
243
- self._base_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
244
- else:
245
- self._base_dir = base_dir
246
-
247
- self._logs_dir = os.path.join(self._base_dir, "logs")
158
+ self._db_metadata = db_metadata #* Declare DB Metadata
248
159
 
249
160
  #* Initialize settings
250
161
  if settings is None:
@@ -252,42 +163,15 @@ class ServiceManager:
252
163
  else:
253
164
  self._settings = settings
254
165
 
255
- #* Load configs
256
166
  self._load_configs()
257
-
258
- #* Initialize google cloud logging
259
- if google_cloud_logging is None:
260
- self._google_cloud_logging = GoogleCloudLogging()
261
- else:
262
- self._google_cloud_logging = google_cloud_logging
263
-
264
- self._log_config = LogConfig(
265
- logs_dir=self._logs_dir,
266
- google_cloud_logging=self._google_cloud_logging
267
- )
268
-
167
+ self._log_config = log_config #* Declare log config
269
168
  self._initialize_loggers()
270
169
  self._load_credentials()
271
170
  self._parse_keys()
272
171
  self._initialize_db()
273
172
 
274
- #* Initialize maleo client managers
275
- if maleo_client_manager_classes is None:
276
- self._maleo_client_manager_classes = MaleoClientManagerClasses()
277
- else:
278
- self._maleo_client_manager_classes = maleo_client_manager_classes
279
- self._initialize_clients()
280
-
281
- @property
282
- def base_dir(self) -> str:
283
- return self._base_dir
284
-
285
- @property
286
- def logs_dir(self) -> str:
287
- return self._logs_dir
288
-
289
173
  @property
290
- def log_config(self) -> LogConfig:
174
+ def log_config(self) -> SimpleConfig:
291
175
  return self._log_config
292
176
 
293
177
  @property
@@ -299,7 +183,8 @@ class ServiceManager:
299
183
  self._static_configs = StaticConfigurations.model_validate(static_configurations)
300
184
  runtime_configurations = YAMLLoader.load(self._settings.RUNTIME_CONFIGURATIONS_PATH)
301
185
  self._runtime_configs = RuntimeConfigurations.model_validate(runtime_configurations)
302
- self._configs = Configurations.model_validate(self._static_configs.model_dump() | self._runtime_configs.model_dump())
186
+ merged_configs = BaseMergers.deep_merge(self._static_configs.model_dump(), self._runtime_configs.model_dump())
187
+ self._configs = Configurations.model_validate(merged_configs)
303
188
 
304
189
  @property
305
190
  def configs(self) -> Configurations:
@@ -359,46 +244,6 @@ class ServiceManager:
359
244
  def database(self) -> DatabaseManager:
360
245
  return self._database
361
246
 
362
- def _initialize_clients(self) -> None:
363
- #* Initialize google clients
364
- secret = GoogleSecretManager(
365
- **self._log_config.model_dump(),
366
- service_key=self._configs.service.key,
367
- credentials_path=self._settings.GOOGLE_CREDENTIALS_PATH
368
- )
369
- storage = GoogleCloudStorage(
370
- **self._log_config.model_dump(),
371
- service_key=self._configs.service.key,
372
- credentials_path=self._settings.GOOGLE_CREDENTIALS_PATH,
373
- bucket_name=self._configs.client.google.storage.bucket_name
374
- )
375
- self._google_clients = GoogleClientManagers(secret=secret, storage=storage)
376
- #* Initialize maleo clients
377
- self._maleo_clients = MaleoClientManagers()
378
- for client in self._maleo_client_manager_classes.__class__.__annotations__:
379
- client_cls = getattr(self._maleo_client_manager_classes, client)
380
- if client_cls is not None and issubclass(client_cls, MaleoClientManager):
381
- cfg:MaleoClientConfiguration = getattr(self._configs.client.maleo, client)
382
- client_instance = client_cls(
383
- **cfg.model_dump(),
384
- **self._log_config.model_dump(),
385
- service_key=self._configs.service.key
386
- )
387
- setattr(self._maleo_clients, client, client_instance)
388
- self._clients = ClientManagers(google=self._google_clients, maleo=self._maleo_clients)
389
-
390
- @property
391
- def google_clients(self) -> GoogleClientManagers:
392
- return self._google_clients
393
-
394
- @property
395
- def maleo_clients(self) -> MaleoClientManagers:
396
- return self._maleo_clients
397
-
398
- @property
399
- def clients(self) -> ClientManagers:
400
- return self._clients
401
-
402
247
  @property
403
248
  def token(self) -> str:
404
249
  payload = BaseTokenGeneralTransfers.BaseEncodePayload(
@@ -453,10 +298,6 @@ class ServiceManager:
453
298
  if self._clients is not None:
454
299
  self._clients.google.storage.dispose()
455
300
  self._clients.google.secret.dispose()
456
- for client in self._maleo_clients.__class__.__annotations__:
457
- client_instance = getattr(self._maleo_clients, client)
458
- if client_instance is not None and isinstance(client_instance, MaleoClientManager):
459
- await client_instance.dispose()
460
301
  self._loggers.application.info("Service manager disposed successfully")
461
302
  if self._loggers is not None:
462
303
  self._loggers.application.info("Disposing logger")
@@ -3,6 +3,7 @@ from .formatter import BaseFormatter
3
3
  from .exceptions import BaseExceptions
4
4
  from .extractor import BaseExtractors
5
5
  from .loaders import BaseLoaders
6
+ from .mergers import BaseMergers
6
7
  from .controller import BaseControllerUtils
7
8
  from .query import BaseQueryUtils
8
9
 
@@ -11,5 +12,6 @@ class BaseUtils:
11
12
  Exceptions = BaseExceptions
12
13
  Extractors = BaseExtractors
13
14
  Loaders = BaseLoaders
15
+ Mergers = BaseMergers
14
16
  Controller = BaseControllerUtils
15
17
  Query = BaseQueryUtils
@@ -5,6 +5,7 @@ from google.auth import default
5
5
  from google.cloud.logging import Client
6
6
  from google.cloud.logging.handlers import CloudLoggingHandler
7
7
  from google.oauth2 import service_account
8
+ from pydantic import BaseModel, Field
8
9
  from typing import Optional
9
10
  from maleo_foundation.enums import BaseEnums
10
11
  from maleo_foundation.types import BaseTypes
@@ -39,10 +40,15 @@ class GoogleCloudLogging:
39
40
  def create_handler(self, name:str) -> CloudLoggingHandler:
40
41
  return CloudLoggingHandler(client=self._client, name=name)
41
42
 
43
+ class SimpleConfig(BaseModel):
44
+ dir:str = Field(..., description="Log's directory")
45
+ level:BaseEnums.LoggerLevel = Field(BaseEnums.LoggerLevel.INFO, description="Log's level")
46
+ google_cloud_logging:GoogleCloudLogging = Field(default_factory=GoogleCloudLogging, description="Google cloud logging")
47
+
42
48
  class BaseLogger(logging.Logger):
43
49
  def __init__(
44
50
  self,
45
- logs_dir:str,
51
+ dir:str,
46
52
  type:BaseEnums.LoggerType,
47
53
  service_key:BaseTypes.OptionalString = None,
48
54
  middleware_type:Optional[BaseEnums.MiddlewareLoggerType] = None,
@@ -50,17 +56,6 @@ class BaseLogger(logging.Logger):
50
56
  level:BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
51
57
  google_cloud_logging:Optional[GoogleCloudLogging] = None
52
58
  ):
53
- """
54
- Custom extended logger with file, console, and Google Cloud Logging.
55
-
56
- - Logs are stored in `logs_dir/logs/{type}`
57
- - Uses Google Cloud Logging if configured
58
-
59
- Args:
60
- logs_dir (str): Base directory for logs (e.g., "/path/to/service")
61
- type (str): Log type (e.g., "application", "middleware")
62
- service_key (str): The service name (e.g., "service")
63
- """
64
59
  self._type = type #* Declare logger type
65
60
 
66
61
  #* Ensure service_key exists
@@ -122,7 +117,7 @@ class BaseLogger(logging.Logger):
122
117
  log_dir = f"{self._type}/{self._client_key}"
123
118
  else:
124
119
  log_dir = f"{self._type}"
125
- self._log_dir = os.path.join(logs_dir, log_dir)
120
+ self._log_dir = os.path.join(dir, log_dir)
126
121
  os.makedirs(self._log_dir, exist_ok=True)
127
122
 
128
123
  #* Generate timestamped filename
@@ -164,14 +159,14 @@ class BaseLogger(logging.Logger):
164
159
  class MiddlewareLogger(BaseLogger):
165
160
  def __init__(
166
161
  self,
167
- logs_dir:str,
162
+ dir:str,
168
163
  service_key:BaseTypes.OptionalString = None,
169
164
  middleware_type = None,
170
165
  level = BaseEnums.LoggerLevel.INFO,
171
166
  google_cloud_logging = None
172
167
  ):
173
168
  super().__init__(
174
- logs_dir=logs_dir,
169
+ dir=dir,
175
170
  type=BaseEnums.LoggerType.MIDDLEWARE,
176
171
  service_key=service_key,
177
172
  middleware_type=middleware_type,
@@ -183,14 +178,14 @@ class MiddlewareLogger(BaseLogger):
183
178
  class ServiceLogger(BaseLogger):
184
179
  def __init__(
185
180
  self,
186
- logs_dir:str,
181
+ dir:str,
187
182
  type:BaseEnums.ServiceLoggerType,
188
183
  service_key:BaseTypes.OptionalString = None,
189
184
  level:BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
190
185
  google_cloud_logging:Optional[GoogleCloudLogging] = None
191
186
  ):
192
187
  super().__init__(
193
- logs_dir=logs_dir,
188
+ dir=dir,
194
189
  type=type,
195
190
  service_key=service_key,
196
191
  middleware_type=None,
@@ -202,41 +197,18 @@ class ServiceLogger(BaseLogger):
202
197
  class ClientLogger(BaseLogger):
203
198
  def __init__(
204
199
  self,
205
- logs_dir:str,
200
+ dir:str,
206
201
  client_key:str,
207
202
  service_key:BaseTypes.OptionalString = None,
208
203
  level:BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
209
204
  google_cloud_logging:Optional[GoogleCloudLogging] = None
210
205
  ):
211
206
  super().__init__(
212
- logs_dir=logs_dir,
207
+ dir=dir,
213
208
  type=BaseEnums.LoggerType.CLIENT,
214
209
  service_key=service_key,
215
210
  middleware_type=None,
216
211
  client_key=client_key,
217
212
  level=level,
218
213
  google_cloud_logging=google_cloud_logging
219
- )
220
-
221
- class ClientLoggerManager:
222
- _logger:Optional[ClientLogger] = None
223
-
224
- @classmethod
225
- def initialize(
226
- cls,
227
- logs_dir:str,
228
- client_key:str,
229
- service_key:BaseTypes.OptionalString = None,
230
- level:BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
231
- google_cloud_logging:Optional[GoogleCloudLogging] = None
232
- ) -> None:
233
- """Initialize client logger if not already initialized."""
234
- if cls._logger is None:
235
- cls.logger = ClientLogger(logs_dir=logs_dir, client_key=client_key, service_key=service_key, level=level, google_cloud_logging=google_cloud_logging)
236
-
237
- @classmethod
238
- def get(cls) -> ClientLogger:
239
- """Return client logger (if exist) or raise Runtime Error"""
240
- if cls._logger is None:
241
- raise RuntimeError("Logger has not been initialized. Initialize it first.")
242
- return cls._logger
214
+ )
@@ -0,0 +1,23 @@
1
+ from collections.abc import Mapping
2
+ from typing import Dict
3
+
4
+ class BaseMergers:
5
+ @staticmethod
6
+ def deep_merge(*obj:Dict) -> Dict:
7
+ def merge_dicts(a:Dict, b:Dict) -> Dict:
8
+ result = dict(a)
9
+ for key, value in b.items():
10
+ if (
11
+ key in result
12
+ and isinstance(result[key], Mapping)
13
+ and isinstance(value, Mapping)
14
+ ):
15
+ result[key] = merge_dicts(result[key], value)
16
+ else:
17
+ result[key] = value
18
+ return result
19
+
20
+ merged = {}
21
+ for ob in obj:
22
+ merged = merge_dicts(merged, ob)
23
+ return merged
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo_foundation
3
- Version: 0.1.42
3
+ Version: 0.1.44
4
4
  Summary: Foundation package for Maleo
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: MIT
@@ -66,6 +66,7 @@ maleo_foundation/utils/controller.py
66
66
  maleo_foundation/utils/exceptions.py
67
67
  maleo_foundation/utils/extractor.py
68
68
  maleo_foundation/utils/logging.py
69
+ maleo_foundation/utils/mergers.py
69
70
  maleo_foundation/utils/query.py
70
71
  maleo_foundation/utils/formatter/__init__.py
71
72
  maleo_foundation/utils/formatter/case.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "maleo_foundation"
7
- version = "0.1.42"
7
+ version = "0.1.44"
8
8
  description = "Foundation package for Maleo"
9
9
  authors = [
10
10
  { name = "Agra Bima Yuda", email = "agra@nexmedis.com" }
@@ -1,52 +0,0 @@
1
- from typing import Optional
2
- from maleo_foundation.enums import BaseEnums
3
- from maleo_foundation.types import BaseTypes
4
- from maleo_foundation.utils.logging import GoogleCloudLogging, ClientLogger
5
-
6
- class ClientManager:
7
- def __init__(
8
- self,
9
- key:str,
10
- name:str,
11
- logs_dir:str,
12
- service_key:BaseTypes.OptionalString = None,
13
- level:BaseEnums.LoggerLevel = BaseEnums.LoggerLevel.INFO,
14
- google_cloud_logging:Optional[GoogleCloudLogging] = None
15
- ) -> None:
16
- self._key = key
17
- self._name = name
18
- self._logs_dir = logs_dir
19
- self._service_key = service_key
20
- self._level = level
21
- self._google_cloud_logging = google_cloud_logging
22
- self._initialize_logger()
23
- self._logger.info("Initializing client manager")
24
-
25
- def _initialize_logger(self) -> None:
26
- self._logger = ClientLogger(
27
- logs_dir=self._logs_dir,
28
- client_key=self._key,
29
- service_key=self._service_key,
30
- level=self._level,
31
- google_cloud_logging=self._google_cloud_logging
32
- )
33
-
34
- @property
35
- def key(self) -> str:
36
- return self._key
37
-
38
- @property
39
- def name(self) -> str:
40
- return self._name
41
-
42
- @property
43
- def logger(self) -> ClientLogger:
44
- return self._logger
45
-
46
- @property
47
- def credentials(self):
48
- raise NotImplementedError()
49
-
50
- @property
51
- def client(self):
52
- raise NotImplementedError()