maleo-foundation 0.3.66__py3-none-any.whl → 0.3.68__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.
@@ -1,5 +1,6 @@
1
1
  from fastapi import FastAPI, APIRouter
2
2
  from fastapi.exceptions import RequestValidationError
3
+ from google.cloud import pubsub_v1
3
4
  from google.oauth2.service_account import Credentials
4
5
  from redis.asyncio.client import Redis
5
6
  from redis.exceptions import RedisError
@@ -72,6 +73,7 @@ class ServiceManager:
72
73
  self._load_keys()
73
74
  self._initialize_loggers()
74
75
  self._initialize_database()
76
+ self._initialize_publisher()
75
77
  self._initialize_foundation()
76
78
 
77
79
  @property
@@ -224,6 +226,13 @@ class ServiceManager:
224
226
  def database(self) -> DatabaseManager:
225
227
  return self._database
226
228
 
229
+ def _initialize_publisher(self) -> None:
230
+ self._publisher = pubsub_v1.PublisherClient()
231
+
232
+ @property
233
+ def publisher(self) -> pubsub_v1.PublisherClient:
234
+ return self._publisher
235
+
227
236
  def _initialize_foundation(self) -> None:
228
237
  self._foundation = MaleoFoundationClientManager(
229
238
  log_config=self._log_config, service_key=self._settings.SERVICE_KEY
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
  from datetime import datetime, timezone
3
- from pydantic import BaseModel, Field
3
+ from pydantic import BaseModel, Field, model_validator
4
+ from typing import Any, Optional, Self
4
5
  from uuid import UUID
5
6
  from maleo_foundation.enums import BaseEnums
6
7
  from maleo_foundation.types import BaseTypes
@@ -22,6 +23,135 @@ class BaseGeneralSchemas:
22
23
  10, ge=1, le=100, description="Page size, must be 1 <= limit <= 100."
23
24
  )
24
25
 
26
+ # * ----- ----- ----- Operation ----- ----- ----- *#
27
+ class OperationArguments(BaseModel):
28
+ positional: BaseTypes.ListOfAny = Field([], description="Positional arguments")
29
+ keyword: BaseTypes.StringToAnyDict = Field({}, description="Keyword arguments")
30
+
31
+ class OperationContext(BaseModel):
32
+ origin: BaseEnums.OperationOrigin = Field(..., description="Operation's origin")
33
+ client_key: BaseTypes.OptionalString = Field(None, description="Client's key")
34
+ layer: BaseEnums.OperationLayer = Field(..., description="Operation's layer")
35
+ target: Optional[BaseEnums.OperationTarget] = Field(
36
+ None, description="Operation's target (optional)"
37
+ )
38
+ environment: Optional[BaseEnums.EnvironmentType] = Field(
39
+ None, description="Operation's target's environment (optional)"
40
+ )
41
+ target_name: BaseTypes.OptionalString = Field(
42
+ None, description="Operation's target's name (optional)"
43
+ )
44
+ target_resource: BaseTypes.OptionalString = Field(
45
+ None, description="Operation's target's resource (optional)"
46
+ )
47
+
48
+ class OperationMetadata(BaseModel):
49
+ type: BaseEnums.OperationType = Field(..., description="Operation's type")
50
+ create_type: Optional[BaseEnums.CreateType] = Field(
51
+ None, description="Create type (optional)"
52
+ )
53
+ update_type: Optional[BaseEnums.UpdateType] = Field(
54
+ None, description="Update type (optional)"
55
+ )
56
+ status_update_type: Optional[BaseEnums.StatusUpdateType] = Field(
57
+ None, description="Status update type (optional)"
58
+ )
59
+ summary: BaseTypes.OptionalString = Field(
60
+ None, description="Summary (optional)"
61
+ )
62
+
63
+ @model_validator(mode="after")
64
+ def validate_operation_types(self) -> Self:
65
+ # Validate create operation type
66
+ if self.type is BaseEnums.OperationType.CREATE:
67
+ if self.create_type is None:
68
+ raise ValueError(
69
+ "'create_type' must have value if 'type' is 'create'"
70
+ )
71
+ if self.create_type not in BaseEnums.CreateType:
72
+ raise ValueError(
73
+ f"'create_type' must be one of {[e.value for e in BaseEnums.CreateType]}"
74
+ )
75
+
76
+ # Validate update operation type
77
+ if self.type is BaseEnums.OperationType.UPDATE:
78
+ if self.update_type is None:
79
+ raise ValueError(
80
+ "'update_type' must have value if 'type' is 'update'"
81
+ )
82
+ if self.update_type not in BaseEnums.UpdateType:
83
+ raise ValueError(
84
+ f"'update_type' must be one of {[e.value for e in BaseEnums.UpdateType]}"
85
+ )
86
+ if self.update_type is BaseEnums.UpdateType.STATUS:
87
+ if self.status_update_type is None:
88
+ raise ValueError(
89
+ "'status_update_type' must have value if 'update_type' is 'status'"
90
+ )
91
+ if self.status_update_type not in BaseEnums.StatusUpdateType:
92
+ raise ValueError(
93
+ f"'status_update_type' must be one of {[e.value for e in BaseEnums.StatusUpdateType]}"
94
+ )
95
+
96
+ return self
97
+
98
+ class OperationServiceContext(BaseModel):
99
+ key: BaseEnums.Service = Field(..., description="Service's key")
100
+ environment: BaseEnums.EnvironmentType = Field(
101
+ ..., description="Service's environment"
102
+ )
103
+
104
+ class OperationTimestamps(BaseModel):
105
+ started_at: BaseTypes.OptionalDatetime = Field(
106
+ None, description="Started at timestamp (Optional)"
107
+ )
108
+ finished_at: BaseTypes.OptionalDatetime = Field(
109
+ None, description="Finished at timestamp (Optional)"
110
+ )
111
+ duration: float = Field(0, description="Operation duration")
112
+
113
+ @model_validator(mode="after")
114
+ def calculate_duration(self) -> Self:
115
+ if self.started_at is not None and self.finished_at is not None:
116
+ self.duration = (self.finished_at - self.started_at).total_seconds()
117
+
118
+ return self
119
+
120
+ class OperationResult(BaseModel):
121
+ success: bool = Field(..., description="Success status")
122
+ code: BaseTypes.OptionalString = Field(None, description="Optional result code")
123
+ message: BaseTypes.OptionalString = Field(None, description="Optional message")
124
+ description: BaseTypes.OptionalString = Field(
125
+ None, description="Optional description"
126
+ )
127
+ data: Any = Field(..., description="Data")
128
+ metadata: BaseTypes.OptionalAny = Field(None, description="Optional metadata")
129
+ other: BaseTypes.OptionalAny = Field(
130
+ None, description="Optional other information"
131
+ )
132
+
133
+ class DatabaseOperationContext(BaseModel):
134
+ database: str = Field(..., description="Database name")
135
+ environment: BaseEnums.EnvironmentType = Field(
136
+ ..., description="Database environment"
137
+ )
138
+ table: str = Field(..., description="Table name")
139
+
140
+ class DatabaseOperationResult(BaseModel):
141
+ data_id: int = Field(..., ge=1, description="Data's ID")
142
+ old_data: BaseTypes.OptionalStringToAnyDict = Field(
143
+ None, description="Old data"
144
+ )
145
+ new_data: BaseTypes.OptionalStringToAnyDict = Field(
146
+ None, description="New data"
147
+ )
148
+
149
+ @model_validator(mode="after")
150
+ def validate_data(self) -> Self:
151
+ if self.old_data is None and self.new_data is None:
152
+ raise ValueError("Either 'old_data' or 'new_data' must have value")
153
+ return self
154
+
25
155
  # * ----- ----- ----- Data ----- ----- ----- *#
26
156
  class Identifiers(BaseModel):
27
157
  id: int = Field(..., ge=1, description="Data's ID, must be >= 1.")
@@ -49,6 +179,9 @@ class BaseGeneralSchemas:
49
179
  class Status(BaseModel):
50
180
  status: BaseEnums.StatusType = Field(..., description="Data's status")
51
181
 
182
+ class DataMixin(Status, Timestamps, Identifiers):
183
+ pass
184
+
52
185
  class IsDefault(BaseModel):
53
186
  is_default: BaseTypes.OptionalBoolean = Field(
54
187
  None, description="Whether data is default"
@@ -0,0 +1,51 @@
1
+ from pydantic import BaseModel, Field
2
+ from typing import Optional
3
+ from .request import RequestContext
4
+ from maleo_foundation.authentication import Authentication
5
+ from maleo_foundation.authorization import Authorization
6
+ from maleo_foundation.models.schemas.general import BaseGeneralSchemas
7
+
8
+
9
+ class Operation(BaseModel):
10
+ request_context: RequestContext = Field(..., description="Request context")
11
+ authentication: Authentication = Field(..., description="Authentication")
12
+ authorization: Optional[Authorization] = Field(None, description="Authorization")
13
+ service: BaseGeneralSchemas.OperationServiceContext = Field(
14
+ ..., description="Service's context"
15
+ )
16
+ timestamps: BaseGeneralSchemas.OperationTimestamps = Field(
17
+ ..., description="Operation's timestamps"
18
+ )
19
+ context: BaseGeneralSchemas.OperationContext = Field(
20
+ ..., description="Operation's context"
21
+ )
22
+ metadata: BaseGeneralSchemas.OperationMetadata = Field(
23
+ ..., description="Operation's metadata"
24
+ )
25
+ arguments: BaseGeneralSchemas.OperationArguments = Field(
26
+ ..., description="Operation's arguments"
27
+ )
28
+ result: BaseGeneralSchemas.OperationResult = Field(
29
+ ..., description="Database operation's result"
30
+ )
31
+
32
+
33
+ class DatabaseOperation(BaseModel):
34
+ request_context: RequestContext = Field(..., description="Request context")
35
+ authentication: Authentication = Field(..., description="Authentication")
36
+ authorization: Optional[Authorization] = Field(None, description="Authorization")
37
+ service: BaseGeneralSchemas.OperationServiceContext = Field(
38
+ ..., description="Service's context"
39
+ )
40
+ timestamps: BaseGeneralSchemas.OperationTimestamps = Field(
41
+ ..., description="Operation's timestamps"
42
+ )
43
+ context: BaseGeneralSchemas.DatabaseOperationContext = Field(
44
+ ..., description="Database operation's context"
45
+ )
46
+ metadata: BaseGeneralSchemas.OperationMetadata = Field(
47
+ ..., description="Operation's metadata"
48
+ )
49
+ result: BaseGeneralSchemas.DatabaseOperationResult = Field(
50
+ ..., description="Database operation's result"
51
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo_foundation
3
- Version: 0.3.66
3
+ Version: 0.3.68
4
4
  Summary: Foundation package for Maleo
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: MIT
@@ -36,7 +36,7 @@ maleo_foundation/managers/configuration.py,sha256=Zc397mT3Qn1Q_gDeuDVKl5YA3bSM-o
36
36
  maleo_foundation/managers/credential.py,sha256=um1M45deBEzTVfsUcpAtKEp3Rb_dH1qQrr8abkG_GeU,3057
37
37
  maleo_foundation/managers/db.py,sha256=y0rQIg-vohhFUtck3v1LCdXov7XYjy9PFiCsVtcg8VI,6496
38
38
  maleo_foundation/managers/middleware.py,sha256=Uglwt4X3MauKtBvbPTyHl0-32od3IN6AYYUtiUCoV9I,2464
39
- maleo_foundation/managers/service.py,sha256=YRG1cLc7yGytDXzOe-btKJ5K0YRHJfkgfGF3D5h3ty4,11795
39
+ maleo_foundation/managers/service.py,sha256=ebmKAXC02R4q_ZXXKCGgQm_SLMzLEKOleZZlD-z5N0s,12067
40
40
  maleo_foundation/managers/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  maleo_foundation/managers/client/base.py,sha256=iM5xZjLm5VQqqpiYcba-rifW0LgkVd-gRTE6XwdOFqY,4369
42
42
  maleo_foundation/managers/client/maleo.py,sha256=aNh3I9EsxeD2rqx5WaXbZ5fjyyXVzvppHJiC98jJYfM,3163
@@ -54,7 +54,7 @@ maleo_foundation/models/responses.py,sha256=WNAz67ewOyWV0oHyiB_BF_-sfaoDF-FVzcwg
54
54
  maleo_foundation/models/table.py,sha256=k0-OtahF2KRmvFUL8TborT6PoIhGsyoVrPJBKGg1QbU,1855
55
55
  maleo_foundation/models/schemas/__init__.py,sha256=tmjBCyG4uMRjiTbnbhIjZaR8q7zk0_J_CqnRzsSfoBQ,279
56
56
  maleo_foundation/models/schemas/encryption.py,sha256=S86FGlcBhyGxxZ5ObNSHTjSDwBUlUtLOMoCAKd5wE34,687
57
- maleo_foundation/models/schemas/general.py,sha256=jxzBsVGsdKKEiM14MfV47dDiAZalUK4RnTlq8S36Qus,4060
57
+ maleo_foundation/models/schemas/general.py,sha256=Vscc4BsAFUzozYXf_nCwswr3HX0t9QJ3NOb06SjWFdo,10064
58
58
  maleo_foundation/models/schemas/hash.py,sha256=jthDmu_VTBydffPruAIAiR8l0Xs6IrlgTptaP42zr1M,447
59
59
  maleo_foundation/models/schemas/key.py,sha256=LSEDQpaCxavwp5je2O-ZNyOPtrFW_lXDywF9LK-An1w,622
60
60
  maleo_foundation/models/schemas/parameter.py,sha256=OE1hg100lEa2IlGlT2Zz6PJ-OcC-6ZfDzsTOeJvvEig,3907
@@ -67,6 +67,7 @@ maleo_foundation/models/transfers/general/credentials.py,sha256=t6OhQb3DyGSfBpbq
67
67
  maleo_foundation/models/transfers/general/data.py,sha256=_J-Y5X2Nx8D1lpaR9ctpm54kUbxR7Vy00hO103uXtxE,1408
68
68
  maleo_foundation/models/transfers/general/database.py,sha256=VQYnZa8dYrqucSQdzkaPSrzLd4SJnpU8LPytUrWErO0,1245
69
69
  maleo_foundation/models/transfers/general/key.py,sha256=QV_kcxAlnrupBcGQK8tqz9FVYbivxwhgIsrmW7XDdME,845
70
+ maleo_foundation/models/transfers/general/operation.py,sha256=M3DraArkFhgjNvA1StWfyS7W0Jhy3hIcdUWUYXlt7Do,2143
70
71
  maleo_foundation/models/transfers/general/request.py,sha256=W2aKxo0lQ-kV-4XpQEzxxa-odwLlGfOulh_wQKgcz9o,1920
71
72
  maleo_foundation/models/transfers/general/settings.py,sha256=1QkPq6GP33S5R718be3XBz0BCtApAuxlL-x21EZ2Xmo,1609
72
73
  maleo_foundation/models/transfers/general/signature.py,sha256=TCTIy928EeBBeFLlyQ3_NozpR9FUcWXPQKIYIwyj66k,308
@@ -137,7 +138,7 @@ maleo_foundation/utils/loaders/credential/__init__.py,sha256=g-cAxkTE2EtHaG8Tv52
137
138
  maleo_foundation/utils/loaders/credential/google.py,sha256=GCJl-bsKSSxoE_ERAkIzRrRNIbIEeqYOhHwzFuBr0mk,6576
138
139
  maleo_foundation/utils/loaders/key/__init__.py,sha256=RfqIbUxkdlx1xrbzJZPD_JHiRFNFLRuQs8JoUPCGCv4,108
139
140
  maleo_foundation/utils/loaders/key/rsa.py,sha256=UXcP0rr4QVacTsHLNQuU05wcow5CHWz-JW-zsVxlbPs,4121
140
- maleo_foundation-0.3.66.dist-info/METADATA,sha256=4NJIYuPP7pJbPrmI04VLqpmE0SGH9WloO9RjQlbNYkc,4150
141
- maleo_foundation-0.3.66.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
142
- maleo_foundation-0.3.66.dist-info/top_level.txt,sha256=_iBos3F_bhEOdjOnzeiEYSrCucasc810xXtLBXI8cQc,17
143
- maleo_foundation-0.3.66.dist-info/RECORD,,
141
+ maleo_foundation-0.3.68.dist-info/METADATA,sha256=xrOYCviMG8PrD0Nstd4wSY_RMJlwaB-Nn0yBAwVTC34,4150
142
+ maleo_foundation-0.3.68.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
143
+ maleo_foundation-0.3.68.dist-info/top_level.txt,sha256=_iBos3F_bhEOdjOnzeiEYSrCucasc810xXtLBXI8cQc,17
144
+ maleo_foundation-0.3.68.dist-info/RECORD,,