maleo-database 0.0.4__py3-none-any.whl → 0.0.6__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,14 @@
1
+ from elasticsearch import AsyncElasticsearch, Elasticsearch
2
+ from motor.motor_asyncio import AsyncIOMotorClient
1
3
  from pydantic import BaseModel, Field
2
- from typing import Generic
4
+ from pymongo import MongoClient
5
+ from redis.asyncio import Redis as AsyncRedis
6
+ from redis import Redis as SyncRedis
7
+ from sqlalchemy.engine import create_engine as create_sync_engine, Engine
8
+ from sqlalchemy.ext.asyncio import create_async_engine, AsyncEngine
9
+ from typing import Generic, Literal, TypeVar, Union, overload
10
+ from maleo.types.base.dict import StringToAnyDict
11
+ from ..enums import Connection
3
12
  from .additional import AdditionalConfigT, RedisAdditionalConfig
4
13
  from .connection import (
5
14
  ConnectionConfigT,
@@ -35,25 +44,61 @@ class BaseDatabaseConfig(
35
44
  additional: AdditionalConfigT = Field(..., description="Additional config")
36
45
 
37
46
 
38
- class PostgreSQLDatabaseConfig(
47
+ class MySQLDatabaseConfig(
39
48
  BaseDatabaseConfig[
40
- PostgreSQLConnectionConfig,
41
- PostgreSQLPoolingConfig,
49
+ MySQLConnectionConfig,
50
+ MySQLPoolingConfig,
42
51
  None,
43
52
  ]
44
53
  ):
45
54
  additional: None = None
46
55
 
56
+ @property
57
+ def engine_kwargs(self) -> StringToAnyDict:
58
+ return {
59
+ **self.connection.engine_kwargs,
60
+ **self.pooling.engine_kwargs,
61
+ }
47
62
 
48
- class MySQLDatabaseConfig(
63
+ @overload
64
+ def create_engine(self, connection: Literal[Connection.ASYNC]) -> AsyncEngine: ...
65
+ @overload
66
+ def create_engine(self, connection: Literal[Connection.SYNC]) -> Engine: ...
67
+ def create_engine(self, connection: Connection) -> Union[AsyncEngine, Engine]:
68
+ url = self.connection.make_url(connection)
69
+ if connection is Connection.ASYNC:
70
+ return create_async_engine(url, **self.engine_kwargs)
71
+ elif connection is Connection.SYNC:
72
+ return create_sync_engine(url, **self.engine_kwargs)
73
+
74
+
75
+ class PostgreSQLDatabaseConfig(
49
76
  BaseDatabaseConfig[
50
- MySQLConnectionConfig,
51
- MySQLPoolingConfig,
77
+ PostgreSQLConnectionConfig,
78
+ PostgreSQLPoolingConfig,
52
79
  None,
53
80
  ]
54
81
  ):
55
82
  additional: None = None
56
83
 
84
+ @property
85
+ def engine_kwargs(self) -> StringToAnyDict:
86
+ return {
87
+ **self.connection.engine_kwargs,
88
+ **self.pooling.engine_kwargs,
89
+ }
90
+
91
+ @overload
92
+ def create_engine(self, connection: Literal[Connection.ASYNC]) -> AsyncEngine: ...
93
+ @overload
94
+ def create_engine(self, connection: Literal[Connection.SYNC]) -> Engine: ...
95
+ def create_engine(self, connection: Connection) -> Union[AsyncEngine, Engine]:
96
+ url = self.connection.make_url(connection)
97
+ if connection is Connection.ASYNC:
98
+ return create_async_engine(url, **self.engine_kwargs)
99
+ elif connection is Connection.SYNC:
100
+ return create_sync_engine(url, **self.engine_kwargs)
101
+
57
102
 
58
103
  class SQLiteDatabaseConfig(
59
104
  BaseDatabaseConfig[
@@ -64,6 +109,24 @@ class SQLiteDatabaseConfig(
64
109
  ):
65
110
  additional: None = None
66
111
 
112
+ @property
113
+ def engine_kwargs(self) -> StringToAnyDict:
114
+ return {
115
+ **self.connection.engine_kwargs,
116
+ **self.pooling.engine_kwargs,
117
+ }
118
+
119
+ @overload
120
+ def create_engine(self, connection: Literal[Connection.ASYNC]) -> AsyncEngine: ...
121
+ @overload
122
+ def create_engine(self, connection: Literal[Connection.SYNC]) -> Engine: ...
123
+ def create_engine(self, connection: Connection) -> Union[AsyncEngine, Engine]:
124
+ url = self.connection.make_url(connection)
125
+ if connection is Connection.ASYNC:
126
+ return create_async_engine(url, **self.engine_kwargs)
127
+ elif connection is Connection.SYNC:
128
+ return create_sync_engine(url, **self.engine_kwargs)
129
+
67
130
 
68
131
  class SQLServerDatabaseConfig(
69
132
  BaseDatabaseConfig[
@@ -74,6 +137,72 @@ class SQLServerDatabaseConfig(
74
137
  ):
75
138
  additional: None = None
76
139
 
140
+ @property
141
+ def engine_kwargs(self) -> StringToAnyDict:
142
+ return {
143
+ **self.connection.engine_kwargs,
144
+ **self.pooling.engine_kwargs,
145
+ }
146
+
147
+ @overload
148
+ def create_engine(self, connection: Literal[Connection.ASYNC]) -> AsyncEngine: ...
149
+ @overload
150
+ def create_engine(self, connection: Literal[Connection.SYNC]) -> Engine: ...
151
+ def create_engine(self, connection: Connection) -> Union[AsyncEngine, Engine]:
152
+ url = self.connection.make_url(connection)
153
+ if connection is Connection.ASYNC:
154
+ return create_async_engine(url, **self.engine_kwargs)
155
+ elif connection is Connection.SYNC:
156
+ return create_sync_engine(url, **self.engine_kwargs)
157
+
158
+
159
+ SQLConfigT = TypeVar(
160
+ "SQLConfigT",
161
+ PostgreSQLDatabaseConfig,
162
+ MySQLDatabaseConfig,
163
+ SQLiteDatabaseConfig,
164
+ SQLServerDatabaseConfig,
165
+ )
166
+
167
+
168
+ class ElasticsearchDatabaseConfig(
169
+ BaseDatabaseConfig[
170
+ ElasticsearchConnectionConfig,
171
+ ElasticsearchPoolingConfig,
172
+ None,
173
+ ]
174
+ ):
175
+ additional: None = None
176
+
177
+ @property
178
+ def client_kwargs(self) -> StringToAnyDict:
179
+ client_kwargs = {}
180
+
181
+ if self.connection.username and self.connection.password:
182
+ client_kwargs["http_auth"] = (
183
+ self.connection.username,
184
+ self.connection.password,
185
+ )
186
+
187
+ client_kwargs.update(self.pooling.client_kwargs)
188
+
189
+ return client_kwargs
190
+
191
+ @overload
192
+ def create_client(
193
+ self, connection: Literal[Connection.ASYNC]
194
+ ) -> AsyncElasticsearch: ...
195
+ @overload
196
+ def create_client(self, connection: Literal[Connection.SYNC]) -> Elasticsearch: ...
197
+ def create_client(
198
+ self, connection: Connection
199
+ ) -> Union[AsyncElasticsearch, Elasticsearch]:
200
+ hosts = [{"host": self.connection.host, "port": self.connection.port}]
201
+ if connection is Connection.ASYNC:
202
+ return AsyncElasticsearch(hosts, **self.client_kwargs)
203
+ else:
204
+ return Elasticsearch(hosts, **self.client_kwargs)
205
+
77
206
 
78
207
  class MongoDBDatabaseConfig(
79
208
  BaseDatabaseConfig[
@@ -84,6 +213,25 @@ class MongoDBDatabaseConfig(
84
213
  ):
85
214
  additional: None = None
86
215
 
216
+ @property
217
+ def client_kwargs(self) -> StringToAnyDict:
218
+ return self.pooling.client_kwargs
219
+
220
+ @overload
221
+ def create_client(
222
+ self, connection: Literal[Connection.ASYNC]
223
+ ) -> AsyncIOMotorClient: ...
224
+ @overload
225
+ def create_client(self, connection: Literal[Connection.SYNC]) -> MongoClient: ...
226
+ def create_client(
227
+ self, connection: Connection
228
+ ) -> Union[AsyncIOMotorClient, MongoClient]:
229
+ url = self.connection.make_url(connection)
230
+ if connection is Connection.ASYNC:
231
+ return AsyncIOMotorClient(url, **self.client_kwargs)
232
+ else:
233
+ return MongoClient(url, **self.client_kwargs)
234
+
87
235
 
88
236
  class RedisDatabaseConfig(
89
237
  BaseDatabaseConfig[
@@ -94,12 +242,37 @@ class RedisDatabaseConfig(
94
242
  ):
95
243
  additional: RedisAdditionalConfig = Field(..., description="Additional config")
96
244
 
245
+ @property
246
+ def client_kwargs(self) -> StringToAnyDict:
247
+ return self.pooling.client_kwargs
97
248
 
98
- class ElasticsearchDatabaseConfig(
99
- BaseDatabaseConfig[
100
- ElasticsearchConnectionConfig,
101
- ElasticsearchPoolingConfig,
102
- None,
103
- ]
104
- ):
105
- additional: None = None
249
+ @overload
250
+ def create_client(self, connection: Literal[Connection.ASYNC]) -> AsyncRedis: ...
251
+ @overload
252
+ def create_client(self, connection: Literal[Connection.SYNC]) -> SyncRedis: ...
253
+ def create_client(self, connection: Connection) -> Union[AsyncRedis, SyncRedis]:
254
+ url = self.connection.make_url(connection)
255
+ if connection is Connection.ASYNC:
256
+ return AsyncRedis.from_url(url, **self.client_kwargs)
257
+ else:
258
+ return SyncRedis.from_url(url, **self.client_kwargs)
259
+
260
+
261
+ NoSQLConfigT = TypeVar(
262
+ "NoSQLConfigT",
263
+ ElasticsearchDatabaseConfig,
264
+ MongoDBDatabaseConfig,
265
+ RedisDatabaseConfig,
266
+ )
267
+
268
+
269
+ ConfigT = TypeVar(
270
+ "ConfigT",
271
+ PostgreSQLDatabaseConfig,
272
+ MySQLDatabaseConfig,
273
+ SQLiteDatabaseConfig,
274
+ SQLServerDatabaseConfig,
275
+ MongoDBDatabaseConfig,
276
+ RedisDatabaseConfig,
277
+ ElasticsearchDatabaseConfig,
278
+ )
@@ -241,6 +241,41 @@ class BaseConnectionConfig(
241
241
  ConnectionConfigT = TypeVar("ConnectionConfigT", bound=BaseConnectionConfig)
242
242
 
243
243
 
244
+ class MySQLConnectionConfig(
245
+ BaseConnectionConfig[Literal[Driver.MYSQL], str, str, str, int, str]
246
+ ):
247
+ driver: Literal[Driver.MYSQL] = Driver.MYSQL
248
+ port: int = Field(3306, description="MySQL port")
249
+ username: str = Field("root", description="MySQL username")
250
+
251
+ # MySQL-specific options
252
+ echo: bool = Field(False, description="Enable SQL statement logging")
253
+ charset: MySQLCharset = Field(MySQLCharset.UTF8MB4, description="Character set")
254
+
255
+ def _make_mysql_url(self, connection: Connection = Connection.ASYNC) -> str:
256
+ """MySQL database URL format with proper async/sync drivers."""
257
+ # Choose appropriate driver based on connection type
258
+ if connection is Connection.ASYNC:
259
+ driver_name = "mysql+aiomysql"
260
+ elif connection is Connection.SYNC:
261
+ driver_name = "mysql+pymysql" # or mysqlclient
262
+ else:
263
+ driver_name = "mysql" # Default
264
+
265
+ encoded_user = self._safe_encode_credential(self.username)
266
+ encoded_pass = self._safe_encode_credential(self.password)
267
+
268
+ base_url = f"{driver_name}://{encoded_user}:{encoded_pass}@{self.host}:{self.port}/{self.database}"
269
+
270
+ # Add MySQL-specific options
271
+ mysql_options = {"charset": self.charset}
272
+ return base_url + self._make_options_string(mysql_options)
273
+
274
+ @property
275
+ def engine_kwargs(self) -> StringToAnyDict:
276
+ return self.model_dump(include={"echo"}, exclude_none=True)
277
+
278
+
244
279
  class PostgreSQLConnectionConfig(
245
280
  BaseConnectionConfig[Literal[Driver.POSTGRESQL], str, str, str, int, str]
246
281
  ):
@@ -279,36 +314,9 @@ class PostgreSQLConnectionConfig(
279
314
 
280
315
  return base_url + self._make_options_string(pg_options)
281
316
 
282
-
283
- class MySQLConnectionConfig(
284
- BaseConnectionConfig[Literal[Driver.MYSQL], str, str, str, int, str]
285
- ):
286
- driver: Literal[Driver.MYSQL] = Driver.MYSQL
287
- port: int = Field(3306, description="MySQL port")
288
- username: str = Field("root", description="MySQL username")
289
-
290
- # MySQL-specific options
291
- echo: bool = Field(False, description="Enable SQL statement logging")
292
- charset: MySQLCharset = Field(MySQLCharset.UTF8MB4, description="Character set")
293
-
294
- def _make_mysql_url(self, connection: Connection = Connection.ASYNC) -> str:
295
- """MySQL database URL format with proper async/sync drivers."""
296
- # Choose appropriate driver based on connection type
297
- if connection is Connection.ASYNC:
298
- driver_name = "mysql+aiomysql"
299
- elif connection is Connection.SYNC:
300
- driver_name = "mysql+pymysql" # or mysqlclient
301
- else:
302
- driver_name = "mysql" # Default
303
-
304
- encoded_user = self._safe_encode_credential(self.username)
305
- encoded_pass = self._safe_encode_credential(self.password)
306
-
307
- base_url = f"{driver_name}://{encoded_user}:{encoded_pass}@{self.host}:{self.port}/{self.database}"
308
-
309
- # Add MySQL-specific options
310
- mysql_options = {"charset": self.charset}
311
- return base_url + self._make_options_string(mysql_options)
317
+ @property
318
+ def engine_kwargs(self) -> StringToAnyDict:
319
+ return self.model_dump(include={"echo"}, exclude_none=True)
312
320
 
313
321
 
314
322
  class SQLiteConnectionConfig(
@@ -339,6 +347,10 @@ class SQLiteConnectionConfig(
339
347
  base_url = f"{driver_name}:///{self.database}"
340
348
  return base_url + self._make_options_string()
341
349
 
350
+ @property
351
+ def engine_kwargs(self) -> StringToAnyDict:
352
+ return self.model_dump(include={"echo"}, exclude_none=True)
353
+
342
354
 
343
355
  class SQLServerConnectionConfig(
344
356
  BaseConnectionConfig[Literal[Driver.MSSQL], str, str, str, int, str]
@@ -392,6 +404,10 @@ class SQLServerConnectionConfig(
392
404
  }
393
405
  return base_url + self._make_options_string(mssql_options)
394
406
 
407
+ @property
408
+ def engine_kwargs(self) -> StringToAnyDict:
409
+ return self.model_dump(include={"echo"}, exclude_none=True)
410
+
395
411
 
396
412
  class MongoDBConnectionConfig(
397
413
  BaseConnectionConfig[