maleo-database 0.0.21__tar.gz → 0.0.22__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 (26) hide show
  1. {maleo_database-0.0.21 → maleo_database-0.0.22}/PKG-INFO +1 -1
  2. {maleo_database-0.0.21 → maleo_database-0.0.22}/maleo_database.egg-info/PKG-INFO +1 -1
  3. {maleo_database-0.0.21 → maleo_database-0.0.22}/pyproject.toml +1 -1
  4. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/handlers.py +12 -35
  5. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/managers/__init__.py +14 -10
  6. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/orm/queries.py +25 -22
  7. {maleo_database-0.0.21 → maleo_database-0.0.22}/LICENSE +0 -0
  8. {maleo_database-0.0.21 → maleo_database-0.0.22}/README.md +0 -0
  9. {maleo_database-0.0.21 → maleo_database-0.0.22}/maleo_database.egg-info/SOURCES.txt +0 -0
  10. {maleo_database-0.0.21 → maleo_database-0.0.22}/maleo_database.egg-info/dependency_links.txt +0 -0
  11. {maleo_database-0.0.21 → maleo_database-0.0.22}/maleo_database.egg-info/requires.txt +0 -0
  12. {maleo_database-0.0.21 → maleo_database-0.0.22}/maleo_database.egg-info/top_level.txt +0 -0
  13. {maleo_database-0.0.21 → maleo_database-0.0.22}/setup.cfg +0 -0
  14. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/__init__.py +0 -0
  15. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/config/__init__.py +0 -0
  16. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/config/additional.py +0 -0
  17. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/config/connection.py +0 -0
  18. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/config/identifier.py +0 -0
  19. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/config/pooling.py +0 -0
  20. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/dtos.py +0 -0
  21. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/enums.py +0 -0
  22. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/managers/client.py +0 -0
  23. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/managers/engine.py +0 -0
  24. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/managers/session.py +0 -0
  25. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/orm/__init__.py +0 -0
  26. {maleo_database-0.0.21 → maleo_database-0.0.22}/src/orm/mixins.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo-database
3
- Version: 0.0.21
3
+ Version: 0.0.22
4
4
  Summary: Database package for MaleoSuite
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: Proprietary
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo-database
3
- Version: 0.0.21
3
+ Version: 0.0.22
4
4
  Summary: Database package for MaleoSuite
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: Proprietary
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "maleo-database"
7
- version = "0.0.21"
7
+ version = "0.0.22"
8
8
  description = "Database package for MaleoSuite"
9
9
  authors = [
10
10
  { name = "Agra Bima Yuda", email = "agra@nexmedis.com" }
@@ -1,8 +1,6 @@
1
1
  from pydantic import BaseModel, ConfigDict, Field
2
- from sqlalchemy import MetaData
2
+ from sqlalchemy.orm import DeclarativeBase
3
3
  from typing import Generic, Optional, TypeVar
4
- from maleo.dtos.contexts.service import ServiceContext
5
- from maleo.logging.logger import Database
6
4
  from .config import (
7
5
  ElasticsearchConfig,
8
6
  MongoConfig,
@@ -42,17 +40,7 @@ HandlerT = TypeVar("HandlerT", bound=Handler)
42
40
 
43
41
 
44
42
  class ElasticsearchHandler(Handler[ElasticsearchConfig, ElasticsearchManager]):
45
- @classmethod
46
- def new(
47
- cls,
48
- config: ElasticsearchConfig,
49
- logger: Database,
50
- service_context: Optional[ServiceContext] = None,
51
- ) -> "ElasticsearchHandler":
52
- manager = ElasticsearchManager(
53
- config=config, logger=logger, service_context=service_context
54
- )
55
- return cls(config=config, manager=manager)
43
+ pass
56
44
 
57
45
 
58
46
  class MongoHandler(Handler[MongoConfig, MongoManager]):
@@ -63,33 +51,22 @@ class RedisHandler(Handler[RedisConfig, RedisManager]):
63
51
  pass
64
52
 
65
53
 
66
- class MySQLHandler(Handler[MySQLConfig, MySQLManager]):
54
+ T = TypeVar("T", bound=DeclarativeBase)
55
+
56
+
57
+ class MySQLHandler(Handler[MySQLConfig, MySQLManager[T]], Generic[T]):
58
+ pass
59
+
60
+
61
+ class PostgreSQLHandler(Handler[PostgreSQLConfig, PostgreSQLManager[T]], Generic[T]):
67
62
  pass
68
63
 
69
64
 
70
- class PostgreSQLHandler(Handler[PostgreSQLConfig, PostgreSQLManager]):
71
- @classmethod
72
- def new(
73
- cls,
74
- config: PostgreSQLConfig,
75
- logger: Database,
76
- metadata: MetaData,
77
- service_context: Optional[ServiceContext] = None,
78
- ) -> "PostgreSQLHandler":
79
- manager = PostgreSQLManager(
80
- config=config,
81
- logger=logger,
82
- metadata=metadata,
83
- service_context=service_context,
84
- )
85
- return cls(config=config, manager=manager)
86
-
87
-
88
- class SQLiteHandler(Handler[SQLiteConfig, SQLiteManager]):
65
+ class SQLiteHandler(Handler[SQLiteConfig, SQLiteManager[T]], Generic[T]):
89
66
  pass
90
67
 
91
68
 
92
- class SQLServerHandler(Handler[SQLServerConfig, SQLServerManager]):
69
+ class SQLServerHandler(Handler[SQLServerConfig, SQLServerManager[T]], Generic[T]):
93
70
  pass
94
71
 
95
72
 
@@ -6,8 +6,9 @@ from motor.motor_asyncio import AsyncIOMotorClient
6
6
  from pymongo import MongoClient
7
7
  from redis.asyncio import Redis as AsyncRedis
8
8
  from redis import Redis as SyncRedis
9
- from sqlalchemy import MetaData, text
10
- from typing import Generic, Optional, TypeVar
9
+ from sqlalchemy.orm import DeclarativeBase
10
+ from sqlalchemy import text
11
+ from typing import Generic, Optional, Type, TypeVar
11
12
  from uuid import uuid4
12
13
  from maleo.dtos.authentication import GenericAuthentication
13
14
  from maleo.dtos.contexts.operation import generate_operation_context
@@ -96,16 +97,18 @@ class Manager(ABC, Generic[ConfigT]):
96
97
  pass
97
98
 
98
99
 
99
- class SQLManager(Manager[SQLConfigT], Generic[SQLConfigT]):
100
+ T = TypeVar("T", bound=DeclarativeBase)
101
+
102
+
103
+ class SQLManager(Manager[SQLConfigT], Generic[SQLConfigT, T]):
100
104
  def __init__(
101
105
  self,
106
+ Base: Type[T],
102
107
  config: SQLConfigT,
103
108
  logger: Database,
104
- metadata: MetaData,
105
109
  service_context: Optional[ServiceContext] = None,
106
110
  ) -> None:
107
111
  super().__init__(config, logger, service_context)
108
- self._metadata = metadata
109
112
  self._operation_context.target.details = self._config.model_dump()
110
113
  self._engine_manager = EngineManager[SQLConfigT](config)
111
114
  self._session_manager = SessionManager(
@@ -114,7 +117,8 @@ class SQLManager(Manager[SQLConfigT], Generic[SQLConfigT]):
114
117
  logger=self._logger,
115
118
  service_context=self._service_context,
116
119
  )
117
- self._metadata.create_all(bind=self._engine_manager.get(Connection.SYNC))
120
+ self.Base = Base
121
+ self.Base.metadata.create_all(bind=self._engine_manager.get(Connection.SYNC))
118
122
 
119
123
  @property
120
124
  def engine(self) -> EngineManager[SQLConfigT]:
@@ -251,19 +255,19 @@ class SQLManager(Manager[SQLConfigT], Generic[SQLConfigT]):
251
255
  await self._engine_manager.dispose()
252
256
 
253
257
 
254
- class MySQLManager(SQLManager[MySQLConfig]):
258
+ class MySQLManager(SQLManager[MySQLConfig, T], Generic[T]):
255
259
  pass
256
260
 
257
261
 
258
- class PostgreSQLManager(SQLManager[PostgreSQLConfig]):
262
+ class PostgreSQLManager(SQLManager[PostgreSQLConfig, T], Generic[T]):
259
263
  pass
260
264
 
261
265
 
262
- class SQLiteManager(SQLManager[SQLiteConfig]):
266
+ class SQLiteManager(SQLManager[SQLiteConfig, T], Generic[T]):
263
267
  pass
264
268
 
265
269
 
266
- class SQLServerManager(SQLManager[SQLServerConfig]):
270
+ class SQLServerManager(SQLManager[SQLServerConfig, T], Generic[T]):
267
271
  pass
268
272
 
269
273
 
@@ -3,7 +3,7 @@ from sqlalchemy.orm import DeclarativeBase, Session, aliased
3
3
  from sqlalchemy.orm.attributes import InstrumentedAttribute
4
4
  from sqlalchemy.sql import Select
5
5
  from sqlalchemy.types import DATE, String, TEXT, TIMESTAMP
6
- from typing import Sequence, Type, TypeVar
6
+ from typing import Any, Sequence, Tuple, Type, TypeVar
7
7
  from maleo.enums.sort import Order
8
8
  from maleo.mixins.general import DateFilter, SortColumn
9
9
  from maleo.types.base.any import OptionalAny
@@ -14,15 +14,18 @@ from maleo.types.enums.status import OptionalListOfDataStatuses
14
14
 
15
15
 
16
16
  T = TypeVar("T", bound=DeclarativeBase)
17
+ R = TypeVar(
18
+ "R", bound=Tuple[Any, ...]
19
+ ) # result shape inferred from Select (tuple[...])
17
20
 
18
21
 
19
22
  def filter_column(
20
- stmt: Select,
23
+ stmt: Select[R],
21
24
  table: Type[T],
22
25
  column: str,
23
26
  value: OptionalAny = None,
24
27
  include_null: bool = False,
25
- ) -> Select:
28
+ ) -> Select[R]:
26
29
  column_attr = getattr(table, column, None)
27
30
  if column_attr is None or not isinstance(column_attr, InstrumentedAttribute):
28
31
  return stmt
@@ -40,12 +43,12 @@ def filter_column(
40
43
 
41
44
 
42
45
  def filter_ids(
43
- stmt: Select,
46
+ stmt: Select[R],
44
47
  table: Type[T],
45
48
  column: str,
46
49
  ids: OptionalListOfIntegers = None,
47
50
  include_null: bool = False,
48
- ) -> Select:
51
+ ) -> Select[R]:
49
52
  column_attr = getattr(table, column, None)
50
53
  if column_attr is None or not isinstance(column_attr, InstrumentedAttribute):
51
54
  return stmt
@@ -63,10 +66,10 @@ def filter_ids(
63
66
 
64
67
 
65
68
  def filter_timestamps(
66
- stmt: Select,
69
+ stmt: Select[R],
67
70
  table: Type[T],
68
71
  date_filters: Sequence[DateFilter],
69
- ) -> Select:
72
+ ) -> Select[R]:
70
73
  if date_filters:
71
74
  for date_filter in date_filters:
72
75
  try:
@@ -90,10 +93,10 @@ def filter_timestamps(
90
93
 
91
94
 
92
95
  def filter_statuses(
93
- stmt: Select,
96
+ stmt: Select[R],
94
97
  table: Type[T],
95
98
  statuses: OptionalListOfDataStatuses,
96
- ) -> Select:
99
+ ) -> Select[R]:
97
100
  if statuses is not None:
98
101
  status_filters = [table.status == status for status in statuses] # type: ignore
99
102
  stmt = stmt.filter(or_(*status_filters))
@@ -101,11 +104,11 @@ def filter_statuses(
101
104
 
102
105
 
103
106
  def filter_is_root(
104
- stmt: Select,
107
+ stmt: Select[R],
105
108
  table: Type[T],
106
109
  parent_column: str = "parent_id",
107
110
  is_root: OptionalBoolean = None,
108
- ) -> Select:
111
+ ) -> Select[R]:
109
112
  parent_attr = getattr(table, parent_column, None)
110
113
  if parent_attr is None or not isinstance(parent_attr, InstrumentedAttribute):
111
114
  return stmt
@@ -118,12 +121,12 @@ def filter_is_root(
118
121
 
119
122
  def filter_is_parent(
120
123
  session: Session,
121
- stmt: Select,
124
+ stmt: Select[R],
122
125
  table: Type[T],
123
126
  id_column: str = "id",
124
127
  parent_column: str = "parent_id",
125
128
  is_parent: OptionalBoolean = None,
126
- ) -> Select:
129
+ ) -> Select[R]:
127
130
  id_attr = getattr(table, id_column, None)
128
131
  if id_attr is None or not isinstance(id_attr, InstrumentedAttribute):
129
132
  return stmt
@@ -139,11 +142,11 @@ def filter_is_parent(
139
142
 
140
143
 
141
144
  def filter_is_child(
142
- stmt: Select,
145
+ stmt: Select[R],
143
146
  table: Type[T],
144
147
  parent_column: str = "parent_id",
145
148
  is_child: OptionalBoolean = None,
146
- ) -> Select:
149
+ ) -> Select[R]:
147
150
  parent_attr = getattr(table, parent_column, None)
148
151
  if parent_attr is None or not isinstance(parent_attr, InstrumentedAttribute):
149
152
  return stmt
@@ -156,12 +159,12 @@ def filter_is_child(
156
159
 
157
160
  def filter_is_leaf(
158
161
  session: Session,
159
- stmt: Select,
162
+ stmt: Select[R],
160
163
  table: Type[T],
161
164
  id_column: str = "id",
162
165
  parent_column: str = "parent_id",
163
166
  is_leaf: OptionalBoolean = None,
164
- ) -> Select:
167
+ ) -> Select[R]:
165
168
  id_attr = getattr(table, id_column, None)
166
169
  if id_attr is None or not isinstance(id_attr, InstrumentedAttribute):
167
170
  return stmt
@@ -177,11 +180,11 @@ def filter_is_leaf(
177
180
 
178
181
 
179
182
  def search(
180
- stmt: Select,
183
+ stmt: Select[R],
181
184
  table: Type[T],
182
185
  search: OptionalString = None,
183
186
  columns: OptionalListOfStrings = None,
184
- ) -> Select:
187
+ ) -> Select[R]:
185
188
  if search is None:
186
189
  return stmt
187
190
 
@@ -211,10 +214,10 @@ def search(
211
214
 
212
215
 
213
216
  def sort(
214
- stmt: Select,
217
+ stmt: Select[R],
215
218
  table: Type[T],
216
219
  sort_columns: Sequence[SortColumn],
217
- ) -> Select:
220
+ ) -> Select[R]:
218
221
  for sort_column in sort_columns:
219
222
  try:
220
223
  sort_col = getattr(table, sort_column.name)
@@ -227,7 +230,7 @@ def sort(
227
230
  return stmt
228
231
 
229
232
 
230
- def paginate(stmt: Select, page: int, limit: int) -> Select:
233
+ def paginate(stmt: Select[R], page: int, limit: int) -> Select[R]:
231
234
  offset: int = int((page - 1) * limit)
232
235
  stmt = stmt.limit(limit).offset(offset)
233
236
  return stmt
File without changes