maleo-foundation 0.1.35__tar.gz → 0.1.36__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.
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/PKG-INFO +1 -1
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/db.py +4 -5
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/service.py +0 -1
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/utils/exceptions.py +1 -13
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation.egg-info/PKG-INFO +1 -1
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation.egg-info/SOURCES.txt +1 -20
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/pyproject.toml +1 -1
- maleo_foundation-0.1.35/maleo_foundation/clients/__init__.py +0 -7
- maleo_foundation-0.1.35/maleo_foundation/clients/general/__init__.py +0 -4
- maleo_foundation-0.1.35/maleo_foundation/clients/general/http.py +0 -50
- maleo_foundation-0.1.35/maleo_foundation/clients/google/__init__.py +0 -4
- maleo_foundation-0.1.35/maleo_foundation/clients/google/base.py +0 -32
- maleo_foundation-0.1.35/maleo_foundation/clients/google/cloud/__init__.py +0 -8
- maleo_foundation-0.1.35/maleo_foundation/clients/google/cloud/base.py +0 -32
- maleo_foundation-0.1.35/maleo_foundation/clients/google/cloud/logging.py +0 -63
- maleo_foundation-0.1.35/maleo_foundation/clients/google/cloud/secret.py +0 -149
- maleo_foundation-0.1.35/maleo_foundation/clients/google/cloud/storage.py +0 -110
- maleo_foundation-0.1.35/maleo_foundation/clients/google/secret.py +0 -61
- maleo_foundation-0.1.35/maleo_foundation/clients/google/storage.py +0 -57
- maleo_foundation-0.1.35/maleo_foundation/clients/utils/__init__.py +0 -5
- maleo_foundation-0.1.35/maleo_foundation/clients/utils/logger.py +0 -54
- maleo_foundation-0.1.35/maleo_foundation/db/__init__.py +0 -4
- maleo_foundation-0.1.35/maleo_foundation/db/engine.py +0 -76
- maleo_foundation-0.1.35/maleo_foundation/db/manager.py +0 -122
- maleo_foundation-0.1.35/maleo_foundation/db/session.py +0 -111
- maleo_foundation-0.1.35/maleo_foundation/utils/logger.py +0 -92
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/README.md +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/authentication.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/constants.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/enums.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/expanded_types/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/expanded_types/client.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/expanded_types/general.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/expanded_types/query.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/expanded_types/service.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/expanded_types/token.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/extended_types.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/client/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/client/base.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/client/google/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/client/google/base.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/client/google/secret.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/client/google/storage.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/client/maleo.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/managers/middleware.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/middlewares/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/middlewares/authentication.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/middlewares/base.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/middlewares/cors.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/responses.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/schemas/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/schemas/general.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/schemas/parameter.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/schemas/result.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/schemas/token.py +0 -0
- {maleo_foundation-0.1.35/maleo_foundation/db → maleo_foundation-0.1.36/maleo_foundation/models}/table.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/general/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/general/token.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/parameters/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/parameters/client.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/parameters/general.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/parameters/service.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/parameters/token.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/client/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/client/controllers/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/client/controllers/http.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/client/service.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/service/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/service/controllers/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/service/controllers/rest.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/service/general.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/service/query.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/models/transfers/results/token.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/services/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/services/token.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/types.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/utils/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/utils/controller.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/utils/extractor.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/utils/formatter/__init__.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/utils/formatter/case.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/utils/keyloader.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/utils/logging.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation/utils/query.py +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation.egg-info/dependency_links.txt +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation.egg-info/requires.txt +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/maleo_foundation.egg-info/top_level.txt +0 -0
- {maleo_foundation-0.1.35 → maleo_foundation-0.1.36}/setup.cfg +0 -0
@@ -5,17 +5,16 @@ from sqlalchemy.engine import Engine, create_engine
|
|
5
5
|
from sqlalchemy.exc import SQLAlchemyError
|
6
6
|
from sqlalchemy.ext.declarative import DeclarativeMeta
|
7
7
|
from sqlalchemy.orm import sessionmaker, Session, declarative_base
|
8
|
-
from typing import Generator
|
8
|
+
from typing import Generator
|
9
9
|
from maleo_foundation.types import BaseTypes
|
10
|
-
from maleo_foundation.utils.
|
11
|
-
from maleo_foundation.db.table import BaseTable
|
10
|
+
from maleo_foundation.utils.logging import ServiceLogger
|
12
11
|
|
13
12
|
class MetadataManager:
|
14
13
|
Base:DeclarativeMeta = declarative_base()
|
15
14
|
metadata:MetaData = Base.metadata
|
16
15
|
|
17
16
|
class SessionManager:
|
18
|
-
def __init__(self, logger:
|
17
|
+
def __init__(self, logger:ServiceLogger, engine:Engine):
|
19
18
|
self._logger = logger
|
20
19
|
self._logger.info("Initializing SessionMaker")
|
21
20
|
self._sessionmaker:sessionmaker[Session] = sessionmaker(bind=engine, expire_on_commit=False)
|
@@ -62,7 +61,7 @@ class DatabaseManager:
|
|
62
61
|
def __init__(
|
63
62
|
self,
|
64
63
|
metadata:MetaData,
|
65
|
-
logger:
|
64
|
+
logger:ServiceLogger,
|
66
65
|
url:BaseTypes.OptionalString = None
|
67
66
|
):
|
68
67
|
self._metadata = metadata #* Define database metadata
|
@@ -8,7 +8,7 @@ from typing import Optional
|
|
8
8
|
from maleo_foundation.models.responses import BaseResponses
|
9
9
|
from maleo_foundation.models.transfers.results.service.general import BaseServiceGeneralResultsTransfers
|
10
10
|
from maleo_foundation.models.transfers.results.service.query import BaseServiceQueryResultsTransfers
|
11
|
-
from maleo_foundation.utils.
|
11
|
+
from maleo_foundation.utils.logging import BaseLogger
|
12
12
|
|
13
13
|
class BaseExceptions:
|
14
14
|
@staticmethod
|
@@ -27,15 +27,9 @@ class BaseExceptions:
|
|
27
27
|
def database_exception_handler(
|
28
28
|
operation:str,
|
29
29
|
logger:Optional[BaseLogger] = None,
|
30
|
-
logger_factory:Optional[LoggerFactory] = None,
|
31
30
|
fail_result_class:type[BaseServiceQueryResultsTransfers.Fail] = BaseServiceQueryResultsTransfers.Fail
|
32
31
|
):
|
33
32
|
"""Decorator to handle database-related exceptions consistently."""
|
34
|
-
if logger is not None and logger_factory is not None:
|
35
|
-
raise RuntimeError("Only one of 'logger' or 'logger_factory' should be provided, not both.")
|
36
|
-
if logger is None and logger_factory is None:
|
37
|
-
raise RuntimeError("One of 'logger' or 'logger_factory' must be provided.")
|
38
|
-
logger = logger or logger_factory()
|
39
33
|
def decorator(func):
|
40
34
|
@wraps(func)
|
41
35
|
def wrapper(*args, **kwargs):
|
@@ -62,15 +56,9 @@ class BaseExceptions:
|
|
62
56
|
def service_exception_handler(
|
63
57
|
operation:str,
|
64
58
|
logger:Optional[BaseLogger] = None,
|
65
|
-
logger_factory:Optional[LoggerFactory] = None,
|
66
59
|
fail_result_class:type[BaseServiceGeneralResultsTransfers.Fail] = BaseServiceGeneralResultsTransfers.Fail
|
67
60
|
):
|
68
61
|
"""Decorator to handle service-related exceptions consistently."""
|
69
|
-
if logger is not None and logger_factory is not None:
|
70
|
-
raise RuntimeError("Only one of 'logger' or 'logger_factory' should be provided, not both.")
|
71
|
-
if logger is None and logger_factory is None:
|
72
|
-
raise RuntimeError("One of 'logger' or 'logger_factory' must be provided.")
|
73
|
-
logger = logger or logger_factory()
|
74
62
|
def decorator(func):
|
75
63
|
@wraps(func)
|
76
64
|
def wrapper(*args, **kwargs):
|
@@ -11,25 +11,6 @@ maleo_foundation.egg-info/SOURCES.txt
|
|
11
11
|
maleo_foundation.egg-info/dependency_links.txt
|
12
12
|
maleo_foundation.egg-info/requires.txt
|
13
13
|
maleo_foundation.egg-info/top_level.txt
|
14
|
-
maleo_foundation/clients/__init__.py
|
15
|
-
maleo_foundation/clients/general/__init__.py
|
16
|
-
maleo_foundation/clients/general/http.py
|
17
|
-
maleo_foundation/clients/google/__init__.py
|
18
|
-
maleo_foundation/clients/google/base.py
|
19
|
-
maleo_foundation/clients/google/secret.py
|
20
|
-
maleo_foundation/clients/google/storage.py
|
21
|
-
maleo_foundation/clients/google/cloud/__init__.py
|
22
|
-
maleo_foundation/clients/google/cloud/base.py
|
23
|
-
maleo_foundation/clients/google/cloud/logging.py
|
24
|
-
maleo_foundation/clients/google/cloud/secret.py
|
25
|
-
maleo_foundation/clients/google/cloud/storage.py
|
26
|
-
maleo_foundation/clients/utils/__init__.py
|
27
|
-
maleo_foundation/clients/utils/logger.py
|
28
|
-
maleo_foundation/db/__init__.py
|
29
|
-
maleo_foundation/db/engine.py
|
30
|
-
maleo_foundation/db/manager.py
|
31
|
-
maleo_foundation/db/session.py
|
32
|
-
maleo_foundation/db/table.py
|
33
14
|
maleo_foundation/expanded_types/__init__.py
|
34
15
|
maleo_foundation/expanded_types/client.py
|
35
16
|
maleo_foundation/expanded_types/general.py
|
@@ -53,6 +34,7 @@ maleo_foundation/middlewares/base.py
|
|
53
34
|
maleo_foundation/middlewares/cors.py
|
54
35
|
maleo_foundation/models/__init__.py
|
55
36
|
maleo_foundation/models/responses.py
|
37
|
+
maleo_foundation/models/table.py
|
56
38
|
maleo_foundation/models/schemas/__init__.py
|
57
39
|
maleo_foundation/models/schemas/general.py
|
58
40
|
maleo_foundation/models/schemas/parameter.py
|
@@ -84,7 +66,6 @@ maleo_foundation/utils/controller.py
|
|
84
66
|
maleo_foundation/utils/exceptions.py
|
85
67
|
maleo_foundation/utils/extractor.py
|
86
68
|
maleo_foundation/utils/keyloader.py
|
87
|
-
maleo_foundation/utils/logger.py
|
88
69
|
maleo_foundation/utils/logging.py
|
89
70
|
maleo_foundation/utils/query.py
|
90
71
|
maleo_foundation/utils/formatter/__init__.py
|
@@ -1,50 +0,0 @@
|
|
1
|
-
import httpx
|
2
|
-
from contextlib import asynccontextmanager
|
3
|
-
from typing import AsyncGenerator, Optional
|
4
|
-
|
5
|
-
class HTTPClientManager:
|
6
|
-
client:Optional[httpx.AsyncClient] = None
|
7
|
-
base_url:Optional[str] = None
|
8
|
-
|
9
|
-
@classmethod
|
10
|
-
def initialize(cls) -> None:
|
11
|
-
"""Initialize the HTTP client if not already initialized."""
|
12
|
-
if cls.client is None:
|
13
|
-
cls.client = httpx.AsyncClient()
|
14
|
-
|
15
|
-
@classmethod
|
16
|
-
async def _client_handler(cls) -> AsyncGenerator[httpx.AsyncClient, None]:
|
17
|
-
"""Reusable generator for client handling."""
|
18
|
-
if cls.client is None:
|
19
|
-
raise RuntimeError("Client has not been initialized. Call initialize first.")
|
20
|
-
|
21
|
-
yield cls.client
|
22
|
-
|
23
|
-
@classmethod
|
24
|
-
async def inject_client(cls) -> AsyncGenerator[httpx.AsyncClient, None]:
|
25
|
-
return cls._client_handler()
|
26
|
-
|
27
|
-
@classmethod
|
28
|
-
@asynccontextmanager
|
29
|
-
async def get_client(cls) -> AsyncGenerator[httpx.AsyncClient, None]:
|
30
|
-
"""
|
31
|
-
Async context manager for manual HTTP client handling.
|
32
|
-
Supports `async with HTTPClientManager.get() as client:`
|
33
|
-
"""
|
34
|
-
async for client in cls._client_handler():
|
35
|
-
yield client
|
36
|
-
|
37
|
-
@classmethod
|
38
|
-
def get_url(cls) -> str:
|
39
|
-
if cls.base_url is None:
|
40
|
-
raise RuntimeError("Base URL has not been initialized. Call initialize first.")
|
41
|
-
return cls.base_url
|
42
|
-
|
43
|
-
@classmethod
|
44
|
-
async def dispose(cls) -> None:
|
45
|
-
"""Dispose of the HTTP client and release any resources."""
|
46
|
-
if cls.client is not None:
|
47
|
-
await cls.client.aclose()
|
48
|
-
cls.client = None
|
49
|
-
if cls.base_url is not None:
|
50
|
-
cls.base_url = None
|
@@ -1,32 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from google.auth import default
|
3
|
-
from google.oauth2 import service_account
|
4
|
-
from maleo_foundation.types import BaseTypes
|
5
|
-
|
6
|
-
class GoogleClientManager:
|
7
|
-
def __init__(self, google_credentials_path:BaseTypes.OptionalString = None) -> None:
|
8
|
-
google_credentials_path = google_credentials_path or os.getenv("GOOGLE_CREDENTIALS_PATH")
|
9
|
-
try:
|
10
|
-
if google_credentials_path is not None:
|
11
|
-
self._credentials = service_account.Credentials.from_service_account_file(filename=google_credentials_path)
|
12
|
-
else:
|
13
|
-
self._credentials, _ = default()
|
14
|
-
except Exception as e:
|
15
|
-
raise ValueError(f"Failed to initialize credentials: {str(e)}")
|
16
|
-
|
17
|
-
@property
|
18
|
-
def credentials(self) -> service_account.Credentials:
|
19
|
-
return self._credentials
|
20
|
-
|
21
|
-
@property
|
22
|
-
def name(self) -> str:
|
23
|
-
raise NotImplementedError()
|
24
|
-
|
25
|
-
@property
|
26
|
-
def client(self):
|
27
|
-
raise NotImplementedError()
|
28
|
-
|
29
|
-
def dispose(self) -> None:
|
30
|
-
"""Dispose of the client and release any resources."""
|
31
|
-
if self._credentials is not None:
|
32
|
-
self._credentials = None
|
@@ -1,32 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from google.auth import default
|
3
|
-
from google.oauth2 import service_account
|
4
|
-
from maleo_foundation.types import BaseTypes
|
5
|
-
|
6
|
-
class GoogleCloudClientManager:
|
7
|
-
def __init__(self, google_credentials_path:BaseTypes.OptionalString = None) -> None:
|
8
|
-
google_credentials_path = google_credentials_path or os.getenv("GOOGLE_CREDENTIALS_PATH")
|
9
|
-
try:
|
10
|
-
if google_credentials_path is not None:
|
11
|
-
self._credentials = service_account.Credentials.from_service_account_file(filename=google_credentials_path)
|
12
|
-
else:
|
13
|
-
self._credentials, _ = default()
|
14
|
-
except Exception as e:
|
15
|
-
raise ValueError(f"Failed to initialize credentials: {str(e)}")
|
16
|
-
|
17
|
-
@property
|
18
|
-
def credentials(self) -> service_account.Credentials:
|
19
|
-
return self._credentials
|
20
|
-
|
21
|
-
@property
|
22
|
-
def name(self) -> str:
|
23
|
-
raise NotImplementedError()
|
24
|
-
|
25
|
-
@property
|
26
|
-
def client(self):
|
27
|
-
raise NotImplementedError()
|
28
|
-
|
29
|
-
def dispose(self) -> None:
|
30
|
-
"""Dispose of the client and release any resources."""
|
31
|
-
if self._credentials is not None:
|
32
|
-
self._credentials = None
|
@@ -1,63 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from google.auth import default
|
3
|
-
from google.cloud.logging import Client
|
4
|
-
from google.cloud.logging.handlers import CloudLoggingHandler
|
5
|
-
from google.oauth2 import service_account
|
6
|
-
from typing import Optional
|
7
|
-
from .base import GoogleCloudClientManager
|
8
|
-
|
9
|
-
class GoogleCloudLogging:
|
10
|
-
_client:Optional[Client] = None
|
11
|
-
|
12
|
-
@classmethod
|
13
|
-
def initialize(cls) -> Client:
|
14
|
-
"""Initialize the cloud logging if not already initialized."""
|
15
|
-
if cls._client is None:
|
16
|
-
#* Setup credentials with fallback chain
|
17
|
-
credentials = None
|
18
|
-
credentials_file = os.getenv("GOOGLE_APPLICATION_CREDENTIALS")
|
19
|
-
try:
|
20
|
-
if credentials_file:
|
21
|
-
credentials = service_account.Credentials.from_service_account_file(credentials_file)
|
22
|
-
else:
|
23
|
-
credentials, _ = default()
|
24
|
-
except Exception as e:
|
25
|
-
raise ValueError(f"Failed to initialize credentials: {str(e)}")
|
26
|
-
|
27
|
-
cls._client = Client(credentials=credentials)
|
28
|
-
cls._client.setup_logging()
|
29
|
-
|
30
|
-
@classmethod
|
31
|
-
def dispose(cls) -> None:
|
32
|
-
"""Dispose of the cloud logging and release any resources."""
|
33
|
-
if cls._client is not None:
|
34
|
-
cls._client = None
|
35
|
-
|
36
|
-
@classmethod
|
37
|
-
def _get_client(cls) -> Client:
|
38
|
-
"""Retrieve the cloud logging client, initializing it if necessary."""
|
39
|
-
cls.initialize()
|
40
|
-
return cls._client
|
41
|
-
|
42
|
-
@classmethod
|
43
|
-
def create_handler(cls, name:str):
|
44
|
-
cls.initialize()
|
45
|
-
return CloudLoggingHandler(client=cls._client, name=name)
|
46
|
-
|
47
|
-
class GoogleCloudLoggingV2(GoogleCloudClientManager):
|
48
|
-
def __init__(self, google_credentials_path = None) -> None:
|
49
|
-
super().__init__(google_credentials_path)
|
50
|
-
self._client = Client(credentials=self._credentials)
|
51
|
-
self._client.setup_logging()
|
52
|
-
|
53
|
-
@property
|
54
|
-
def client(self) -> Client:
|
55
|
-
return self._client
|
56
|
-
|
57
|
-
def dispose(self) -> None:
|
58
|
-
if self._client is not None:
|
59
|
-
self._client = None
|
60
|
-
return super().dispose()
|
61
|
-
|
62
|
-
def create_handler(self, name:str) -> CloudLoggingHandler:
|
63
|
-
return CloudLoggingHandler(client=self._client, name=name)
|
@@ -1,149 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from google.api_core import retry
|
3
|
-
from google.api_core.exceptions import NotFound
|
4
|
-
from google.auth import default
|
5
|
-
from google.cloud import secretmanager
|
6
|
-
from google.oauth2 import service_account
|
7
|
-
from typing import Optional
|
8
|
-
from .base import GoogleCloudClientManager
|
9
|
-
|
10
|
-
class GoogleSecretManager:
|
11
|
-
_project:Optional[str] = None
|
12
|
-
_client:Optional[secretmanager.SecretManagerServiceClient] = None
|
13
|
-
|
14
|
-
@classmethod
|
15
|
-
def initialize(cls, project_id:Optional[str] = None) -> None:
|
16
|
-
"""Initialize the cloud storage if not already initialized."""
|
17
|
-
cls._project = project_id or os.getenv("GCP_PROJECT_ID")
|
18
|
-
if cls._project is None:
|
19
|
-
raise ValueError("GCP_PROJECT_ID environment variable must be set if no project_id is provided")
|
20
|
-
if cls._client is None:
|
21
|
-
#* Setup credentials with fallback chain
|
22
|
-
credentials = None
|
23
|
-
credentials_file = os.getenv("GOOGLE_CREDENTIALS_PATH")
|
24
|
-
try:
|
25
|
-
if credentials_file:
|
26
|
-
credentials = service_account.Credentials.from_service_account_file(credentials_file)
|
27
|
-
else:
|
28
|
-
credentials, _ = default()
|
29
|
-
except Exception as e:
|
30
|
-
raise ValueError(f"Failed to initialize credentials: {str(e)}")
|
31
|
-
|
32
|
-
cls._client = secretmanager.SecretManagerServiceClient(credentials=credentials)
|
33
|
-
|
34
|
-
@classmethod
|
35
|
-
def dispose(cls):
|
36
|
-
"""Disposes of the Google Secret Manager client"""
|
37
|
-
if cls._client is not None:
|
38
|
-
cls._client = None
|
39
|
-
if cls._project is not None:
|
40
|
-
cls._project = None
|
41
|
-
|
42
|
-
@classmethod
|
43
|
-
@retry.Retry(
|
44
|
-
predicate=retry.if_exception_type(Exception),
|
45
|
-
timeout=5
|
46
|
-
)
|
47
|
-
def get(
|
48
|
-
cls,
|
49
|
-
name:str,
|
50
|
-
version:str = "latest",
|
51
|
-
) -> Optional[str]:
|
52
|
-
try:
|
53
|
-
secret_path = f"projects/{cls._project}/secrets/{name}/versions/{version}"
|
54
|
-
request = secretmanager.AccessSecretVersionRequest(name=secret_path)
|
55
|
-
response = cls._client.access_secret_version(request=request)
|
56
|
-
return response.payload.data.decode()
|
57
|
-
except Exception as e:
|
58
|
-
return None
|
59
|
-
|
60
|
-
@classmethod
|
61
|
-
@retry.Retry(
|
62
|
-
predicate=retry.if_exception_type(Exception),
|
63
|
-
timeout=5
|
64
|
-
)
|
65
|
-
def create(
|
66
|
-
cls,
|
67
|
-
name:str,
|
68
|
-
data:str
|
69
|
-
) -> Optional[str]:
|
70
|
-
parent = f"projects/{cls._project}"
|
71
|
-
secret_path = f"{parent}/secrets/{name}"
|
72
|
-
try:
|
73
|
-
#* Check if the secret already exists
|
74
|
-
request = secretmanager.GetSecretRequest(name=secret_path)
|
75
|
-
cls._client.get_secret(request=request)
|
76
|
-
|
77
|
-
except NotFound:
|
78
|
-
#* Secret does not exist, create it first
|
79
|
-
try:
|
80
|
-
secret = secretmanager.Secret(name=name, replication={"automatic": {}})
|
81
|
-
request = secretmanager.CreateSecretRequest(parent=parent, secret_id=name, secret=secret)
|
82
|
-
cls._client.create_secret(request=request)
|
83
|
-
except Exception as e:
|
84
|
-
return None
|
85
|
-
|
86
|
-
#* Add a new secret version
|
87
|
-
try:
|
88
|
-
payload = secretmanager.SecretPayload(data=data.encode()) # ✅ Fixed attribute name
|
89
|
-
request = secretmanager.AddSecretVersionRequest(parent=secret_path, payload=payload)
|
90
|
-
response = cls._client.add_secret_version(request=request)
|
91
|
-
return data
|
92
|
-
except Exception as e:
|
93
|
-
return None
|
94
|
-
|
95
|
-
class GoogleSecretManagerV2(GoogleCloudClientManager):
|
96
|
-
def __init__(self, google_credentials_path = None) -> None:
|
97
|
-
super().__init__(google_credentials_path)
|
98
|
-
self._project_id = self.credentials.project_id
|
99
|
-
self._client = secretmanager.SecretManagerServiceClient(credentials=self.credentials)
|
100
|
-
|
101
|
-
@property
|
102
|
-
def project_id(self):
|
103
|
-
return self._project_id
|
104
|
-
|
105
|
-
@property
|
106
|
-
def client(self) -> secretmanager.SecretManagerServiceClient:
|
107
|
-
return self._client
|
108
|
-
|
109
|
-
def dispose(self):
|
110
|
-
if self._client is not None:
|
111
|
-
self._client = None
|
112
|
-
return super().dispose()
|
113
|
-
|
114
|
-
@retry.Retry(predicate=retry.if_exception_type(Exception), timeout=5)
|
115
|
-
def get(self, name:str, version:str = "latest") -> Optional[str]:
|
116
|
-
try:
|
117
|
-
secret_path = f"projects/{self._project_id}/secrets/{name}/versions/{version}"
|
118
|
-
request = secretmanager.AccessSecretVersionRequest(name=secret_path)
|
119
|
-
response = self._client.access_secret_version(request=request)
|
120
|
-
return response.payload.data.decode()
|
121
|
-
except Exception as e:
|
122
|
-
return None
|
123
|
-
|
124
|
-
@retry.Retry(predicate=retry.if_exception_type(Exception), timeout=5)
|
125
|
-
def create(self, name:str, data:str) -> Optional[str]:
|
126
|
-
parent = f"projects/{self._project_id}"
|
127
|
-
secret_path = f"{parent}/secrets/{name}"
|
128
|
-
try:
|
129
|
-
#* Check if the secret already exists
|
130
|
-
request = secretmanager.GetSecretRequest(name=secret_path)
|
131
|
-
self._client.get_secret(request=request)
|
132
|
-
|
133
|
-
except NotFound:
|
134
|
-
#* Secret does not exist, create it first
|
135
|
-
try:
|
136
|
-
secret = secretmanager.Secret(name=name, replication={"automatic": {}})
|
137
|
-
request = secretmanager.CreateSecretRequest(parent=parent, secret_id=name, secret=secret)
|
138
|
-
self._client.create_secret(request=request)
|
139
|
-
except Exception as e:
|
140
|
-
return None
|
141
|
-
|
142
|
-
#* Add a new secret version
|
143
|
-
try:
|
144
|
-
payload = secretmanager.SecretPayload(data=data.encode()) # ✅ Fixed attribute name
|
145
|
-
request = secretmanager.AddSecretVersionRequest(parent=secret_path, payload=payload)
|
146
|
-
response = self._client.add_secret_version(request=request)
|
147
|
-
return data
|
148
|
-
except Exception as e:
|
149
|
-
return None
|
@@ -1,110 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from datetime import timedelta
|
3
|
-
from google.auth import default
|
4
|
-
from google.cloud.storage import Bucket, Client
|
5
|
-
from google.oauth2 import service_account
|
6
|
-
from typing import Optional
|
7
|
-
from maleo_foundation.types import BaseTypes
|
8
|
-
from .base import GoogleCloudClientManager
|
9
|
-
|
10
|
-
class GoogleCloudStorage:
|
11
|
-
_client:Optional[Client] = None
|
12
|
-
_bucket:Optional[Bucket] = None
|
13
|
-
|
14
|
-
@classmethod
|
15
|
-
def initialize(cls) -> None:
|
16
|
-
"""Initialize the cloud storage if not already initialized."""
|
17
|
-
if cls._client is None:
|
18
|
-
#* Setup credentials with fallback chain
|
19
|
-
credentials = None
|
20
|
-
credentials_file = os.getenv("GOOGLE_CREDENTIALS_PATH")
|
21
|
-
try:
|
22
|
-
if credentials_file:
|
23
|
-
credentials = service_account.Credentials.from_service_account_file(credentials_file)
|
24
|
-
else:
|
25
|
-
credentials, _ = default()
|
26
|
-
except Exception as e:
|
27
|
-
raise ValueError(f"Failed to initialize credentials: {str(e)}")
|
28
|
-
|
29
|
-
cls._client = Client(credentials=credentials)
|
30
|
-
|
31
|
-
#* Preload bucket
|
32
|
-
bucket_name = os.getenv("GCS_BUCKET_NAME")
|
33
|
-
if not bucket_name:
|
34
|
-
cls._client.close()
|
35
|
-
raise ValueError("GCS_BUCKET_NAME environment variable must be set")
|
36
|
-
|
37
|
-
#* Validate bucket existence
|
38
|
-
bucket = cls._client.lookup_bucket(bucket_name)
|
39
|
-
if bucket is None:
|
40
|
-
raise ValueError(f"Bucket '{bucket_name}' does not exist.")
|
41
|
-
|
42
|
-
cls._bucket = bucket
|
43
|
-
|
44
|
-
@classmethod
|
45
|
-
def dispose(cls) -> None:
|
46
|
-
"""Dispose of the cloud storage and release any resources."""
|
47
|
-
if cls._client is not None:
|
48
|
-
cls._client.close()
|
49
|
-
cls._client = None
|
50
|
-
cls._bucket = None
|
51
|
-
|
52
|
-
@classmethod
|
53
|
-
def _get_client(cls) -> Client:
|
54
|
-
"""Retrieve the cloud storage client, initializing it if necessary."""
|
55
|
-
cls.initialize()
|
56
|
-
return cls._client
|
57
|
-
|
58
|
-
@classmethod
|
59
|
-
def generate_signed_url(cls, location:str) -> str:
|
60
|
-
"""
|
61
|
-
generate signed URL of a file in the bucket based on its location.
|
62
|
-
|
63
|
-
Args:
|
64
|
-
location: str
|
65
|
-
Location of the file inside the bucket
|
66
|
-
|
67
|
-
Returns:
|
68
|
-
str: File's pre-signed download url
|
69
|
-
|
70
|
-
Raises:
|
71
|
-
ValueError: If the file does not exist
|
72
|
-
"""
|
73
|
-
cls.initialize()
|
74
|
-
blob = cls._bucket.blob(blob_name=location)
|
75
|
-
if not blob.exists():
|
76
|
-
raise ValueError(f"File '{location}' did not exists.")
|
77
|
-
|
78
|
-
url = blob.generate_signed_url(version="v4", expiration=timedelta(minutes=15), method="GET")
|
79
|
-
return url
|
80
|
-
|
81
|
-
class GoogleCloudStorageV2(GoogleCloudClientManager):
|
82
|
-
def __init__(self, google_credentials_path = None, bucket_name:BaseTypes.OptionalString = None) -> None:
|
83
|
-
super().__init__(google_credentials_path)
|
84
|
-
self._client = Client(credentials=self._credentials)
|
85
|
-
self._bucket_name = bucket_name or os.getenv("GCS_BUCKET_NAME")
|
86
|
-
if self._bucket_name is None:
|
87
|
-
self._client.close()
|
88
|
-
raise ValueError("GCS_BUCKET_NAME environment variable must be set if 'bucket_name' is set to None")
|
89
|
-
self._bucket = self._client.lookup_bucket(bucket_name=self._bucket_name)
|
90
|
-
if self._bucket is None:
|
91
|
-
raise ValueError(f"Bucket '{self._bucket_name}' does not exist.")
|
92
|
-
|
93
|
-
@property
|
94
|
-
def client(self) -> Client:
|
95
|
-
return self._client
|
96
|
-
|
97
|
-
@property
|
98
|
-
def bucket_name(self) -> str:
|
99
|
-
return self._bucket_name
|
100
|
-
|
101
|
-
@property
|
102
|
-
def bucket(self) -> Bucket:
|
103
|
-
return self._bucket
|
104
|
-
|
105
|
-
def dispose(self):
|
106
|
-
if self._bucket is not None:
|
107
|
-
self._bucket = None
|
108
|
-
if self._client is not None:
|
109
|
-
self._client = None
|
110
|
-
return super().dispose()
|