maleo-database 0.0.19__py3-none-any.whl → 0.0.21__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.
@@ -92,7 +92,7 @@ class SessionManager(Generic[SQLConfigT]):
92
92
  operation_action = SystemOperationAction(
93
93
  type=SystemOperationType.DATABASE_CONNECTION, details=None
94
94
  )
95
- session = self._async_sessionmaker()
95
+ session: AsyncSession = self._async_sessionmaker()
96
96
  SuccessfulSystemOperation[
97
97
  Optional[GenericAuthentication], NoDataResponse[None]
98
98
  ](
@@ -111,8 +111,9 @@ class SessionManager(Generic[SQLConfigT]):
111
111
 
112
112
  executed_at = datetime.now(tz=timezone.utc)
113
113
  try:
114
- yield session # Provide session
115
- await session.commit() # Auto-commit on success
114
+ # explicit transaction context — will commit on success, rollback on exception
115
+ async with session.begin():
116
+ yield session
116
117
  SuccessfulSystemOperation[
117
118
  Optional[GenericAuthentication], NoDataResponse[None]
118
119
  ](
@@ -129,7 +130,11 @@ class SessionManager(Generic[SQLConfigT]):
129
130
  self._logger, level=Level.INFO
130
131
  )
131
132
  except SQLAlchemyError as se:
132
- await session.rollback() # Rollback on error
133
+ # session.begin() will rollback, but keep explicit rollback to be safe
134
+ try:
135
+ await session.rollback()
136
+ except Exception:
137
+ pass
133
138
  error = DatabaseError[Optional[GenericAuthentication]](
134
139
  OperationType.SYSTEM,
135
140
  service_context=self._service_context,
@@ -152,7 +157,10 @@ class SessionManager(Generic[SQLConfigT]):
152
157
  operation.log(self._logger, level=Level.ERROR)
153
158
  raise error from se
154
159
  except ValidationError as ve:
155
- await session.rollback() # Rollback on error
160
+ try:
161
+ await session.rollback()
162
+ except Exception:
163
+ pass
156
164
  error = UnprocessableEntity[Optional[GenericAuthentication]](
157
165
  OperationType.SYSTEM,
158
166
  service_context=self._service_context,
@@ -169,9 +177,16 @@ class SessionManager(Generic[SQLConfigT]):
169
177
  operation.log(self._logger, level=Level.ERROR)
170
178
  raise error from ve
171
179
  except MaleoException:
180
+ try:
181
+ await session.rollback()
182
+ except Exception:
183
+ pass
172
184
  raise
173
185
  except Exception as e:
174
- await session.rollback() # Rollback on error
186
+ try:
187
+ await session.rollback()
188
+ except Exception:
189
+ pass
175
190
  error = InternalServerError[Optional[GenericAuthentication]](
176
191
  OperationType.SYSTEM,
177
192
  service_context=self._service_context,
@@ -194,7 +209,11 @@ class SessionManager(Generic[SQLConfigT]):
194
209
  operation.log(self._logger, level=Level.ERROR)
195
210
  raise error from e
196
211
  finally:
197
- await session.close() # Ensure session closes
212
+ # close session
213
+ try:
214
+ await session.close()
215
+ except Exception:
216
+ pass
198
217
  SuccessfulSystemOperation[
199
218
  Optional[GenericAuthentication], NoDataResponse[None]
200
219
  ](
@@ -222,7 +241,7 @@ class SessionManager(Generic[SQLConfigT]):
222
241
  operation_action = SystemOperationAction(
223
242
  type=SystemOperationType.DATABASE_CONNECTION, details=None
224
243
  )
225
- session = self._sync_sessionmaker()
244
+ session: Session = self._sync_sessionmaker()
226
245
  SuccessfulSystemOperation[
227
246
  Optional[GenericAuthentication], NoDataResponse[None]
228
247
  ](
@@ -241,8 +260,9 @@ class SessionManager(Generic[SQLConfigT]):
241
260
 
242
261
  executed_at = datetime.now(tz=timezone.utc)
243
262
  try:
244
- yield session # Provide session
245
- session.commit() # Auto-commit on success
263
+ # explicit transaction context — will commit on success, rollback on exception
264
+ with session.begin():
265
+ yield session
246
266
  SuccessfulSystemOperation[
247
267
  Optional[GenericAuthentication], NoDataResponse[None]
248
268
  ](
@@ -0,0 +1,91 @@
1
+ from datetime import datetime
2
+ from sqlalchemy import func
3
+ from sqlalchemy.dialects.postgresql import UUID as PostgresUUID
4
+ from sqlalchemy.orm import Mapped, declared_attr, mapped_column
5
+ from sqlalchemy.types import Integer, Enum, TIMESTAMP
6
+ from maleo.enums.status import DataStatus as DataStatusEnum
7
+ from uuid import UUID as PythonUUID, uuid4
8
+ from maleo.types.base.datetime import OptionalDatetime
9
+ from maleo.utils.formatters.case import to_snake
10
+
11
+
12
+ class TableName:
13
+ @declared_attr.directive
14
+ def __tablename__(cls) -> str:
15
+ return to_snake(cls.__name__) # type: ignore
16
+
17
+
18
+ class DataIdentifier:
19
+ id: Mapped[int] = mapped_column("id", Integer, primary_key=True)
20
+ uuid: Mapped[PythonUUID] = mapped_column(
21
+ "uuid", PostgresUUID(as_uuid=True), default=uuid4, unique=True, nullable=False
22
+ )
23
+
24
+
25
+ class DataStatus:
26
+ status: Mapped[DataStatusEnum] = mapped_column(
27
+ "status",
28
+ Enum(DataStatusEnum, name="statustype", create_constraints=True),
29
+ default=DataStatusEnum.ACTIVE,
30
+ nullable=False,
31
+ )
32
+
33
+
34
+ class CreationTimestamp:
35
+ created_at: Mapped[datetime] = mapped_column(
36
+ "created_at",
37
+ TIMESTAMP(timezone=True),
38
+ server_default=func.now(),
39
+ nullable=False,
40
+ )
41
+
42
+
43
+ class UpdateTimestamp:
44
+ updated_at: Mapped[datetime] = mapped_column(
45
+ "updated_at",
46
+ TIMESTAMP(timezone=True),
47
+ server_default=func.now(),
48
+ onupdate=func.now(),
49
+ nullable=False,
50
+ )
51
+
52
+
53
+ class LifecyleTimestamp(UpdateTimestamp, CreationTimestamp):
54
+ pass
55
+
56
+
57
+ class DeletionTimestamp:
58
+ deleted_at: Mapped[OptionalDatetime] = mapped_column(
59
+ "deleted_at", TIMESTAMP(timezone=True)
60
+ )
61
+
62
+
63
+ class RestorationTimestamp:
64
+ restored_at: Mapped[OptionalDatetime] = mapped_column(
65
+ "restored_at", TIMESTAMP(timezone=True)
66
+ )
67
+
68
+
69
+ class DeactivationTimestamp:
70
+ deactivated_at: Mapped[OptionalDatetime] = mapped_column(
71
+ "deactivated_at", TIMESTAMP(timezone=True)
72
+ )
73
+
74
+
75
+ class ActivationTimestamp:
76
+ activated_at: Mapped[datetime] = mapped_column(
77
+ "activated_at",
78
+ TIMESTAMP(timezone=True),
79
+ server_default=func.now(),
80
+ nullable=False,
81
+ )
82
+
83
+
84
+ class StatusTimestamp(
85
+ ActivationTimestamp, DeactivationTimestamp, RestorationTimestamp, DeletionTimestamp
86
+ ):
87
+ pass
88
+
89
+
90
+ class DataTimestamp(StatusTimestamp, LifecyleTimestamp):
91
+ pass
@@ -1,10 +1,9 @@
1
- from sqlalchemy import Column, Table
2
- from sqlalchemy.ext.declarative import DeclarativeMeta
3
- from sqlalchemy.orm import Query, Session, aliased
1
+ from sqlalchemy import asc, cast, desc, or_, select
2
+ from sqlalchemy.orm import DeclarativeBase, Session, aliased
4
3
  from sqlalchemy.orm.attributes import InstrumentedAttribute
5
- from sqlalchemy.sql.expression import or_, asc, cast, desc
4
+ from sqlalchemy.sql import Select
6
5
  from sqlalchemy.types import DATE, String, TEXT, TIMESTAMP
7
- from typing import Sequence, Type
6
+ from typing import Sequence, Type, TypeVar
8
7
  from maleo.enums.sort import Order
9
8
  from maleo.mixins.general import DateFilter, SortColumn
10
9
  from maleo.types.base.any import OptionalAny
@@ -14,16 +13,19 @@ from maleo.types.base.string import OptionalListOfStrings, OptionalString
14
13
  from maleo.types.enums.status import OptionalListOfDataStatuses
15
14
 
16
15
 
16
+ T = TypeVar("T", bound=DeclarativeBase)
17
+
18
+
17
19
  def filter_column(
18
- query: Query,
19
- table: Type[DeclarativeMeta],
20
+ stmt: Select,
21
+ table: Type[T],
20
22
  column: str,
21
23
  value: OptionalAny = None,
22
24
  include_null: bool = False,
23
- ) -> Query:
25
+ ) -> Select:
24
26
  column_attr = getattr(table, column, None)
25
27
  if column_attr is None or not isinstance(column_attr, InstrumentedAttribute):
26
- return query
28
+ return stmt
27
29
 
28
30
  value_filters = []
29
31
  if value is not None:
@@ -32,21 +34,21 @@ def filter_column(
32
34
  if value_filters:
33
35
  if include_null:
34
36
  value_filters.append(column_attr.is_(None))
35
- query = query.filter(or_(*value_filters))
37
+ stmt = stmt.filter(or_(*value_filters))
36
38
 
37
- return query
39
+ return stmt
38
40
 
39
41
 
40
42
  def filter_ids(
41
- query: Query,
42
- table: Type[DeclarativeMeta],
43
+ stmt: Select,
44
+ table: Type[T],
43
45
  column: str,
44
46
  ids: OptionalListOfIntegers = None,
45
47
  include_null: bool = False,
46
- ) -> Query:
48
+ ) -> Select:
47
49
  column_attr = getattr(table, column, None)
48
50
  if column_attr is None or not isinstance(column_attr, InstrumentedAttribute):
49
- return query
51
+ return stmt
50
52
 
51
53
  id_filters = []
52
54
  if ids is not None:
@@ -55,180 +57,177 @@ def filter_ids(
55
57
  if id_filters:
56
58
  if include_null:
57
59
  id_filters.append(column_attr.is_(None))
58
- query = query.filter(or_(*id_filters))
60
+ stmt = stmt.filter(or_(*id_filters))
59
61
 
60
- return query
62
+ return stmt
61
63
 
62
64
 
63
65
  def filter_timestamps(
64
- query: Query,
65
- table: Type[DeclarativeMeta], # type: ignore
66
+ stmt: Select,
67
+ table: Type[T],
66
68
  date_filters: Sequence[DateFilter],
67
- ) -> Query:
68
- if date_filters and len(date_filters) > 0:
69
+ ) -> Select:
70
+ if date_filters:
69
71
  for date_filter in date_filters:
70
72
  try:
71
- table: Table = table.__table__ # type: ignore
72
- column: Column = table.columns[date_filter.name]
73
+ sqla_table = table.__table__
74
+ column = sqla_table.columns[date_filter.name]
73
75
  column_attr: InstrumentedAttribute = getattr(table, date_filter.name)
74
76
  if isinstance(column.type, (TIMESTAMP, DATE)):
75
77
  if date_filter.from_date and date_filter.to_date:
76
- query = query.filter(
78
+ stmt = stmt.filter(
77
79
  column_attr.between(
78
80
  date_filter.from_date, date_filter.to_date
79
81
  )
80
82
  )
81
83
  elif date_filter.from_date:
82
- query = query.filter(column_attr >= date_filter.from_date)
84
+ stmt = stmt.filter(column_attr >= date_filter.from_date)
83
85
  elif date_filter.to_date:
84
- query = query.filter(column_attr <= date_filter.to_date)
86
+ stmt = stmt.filter(column_attr <= date_filter.to_date)
85
87
  except KeyError:
86
88
  continue
87
- return query
89
+ return stmt
88
90
 
89
91
 
90
92
  def filter_statuses(
91
- query: Query,
92
- table: Type[DeclarativeMeta],
93
+ stmt: Select,
94
+ table: Type[T],
93
95
  statuses: OptionalListOfDataStatuses,
94
- ) -> Query:
96
+ ) -> Select:
95
97
  if statuses is not None:
96
98
  status_filters = [table.status == status for status in statuses] # type: ignore
97
- query = query.filter(or_(*status_filters))
98
- return query
99
+ stmt = stmt.filter(or_(*status_filters))
100
+ return stmt
99
101
 
100
102
 
101
103
  def filter_is_root(
102
- query: Query,
103
- table: Type[DeclarativeMeta],
104
+ stmt: Select,
105
+ table: Type[T],
104
106
  parent_column: str = "parent_id",
105
107
  is_root: OptionalBoolean = None,
106
- ) -> Query:
108
+ ) -> Select:
107
109
  parent_attr = getattr(table, parent_column, None)
108
110
  if parent_attr is None or not isinstance(parent_attr, InstrumentedAttribute):
109
- return query
111
+ return stmt
110
112
  if is_root is not None:
111
- query = query.filter(
113
+ stmt = stmt.filter(
112
114
  parent_attr.is_(None) if is_root else parent_attr.is_not(None)
113
115
  )
114
- return query
116
+ return stmt
115
117
 
116
118
 
117
119
  def filter_is_parent(
118
120
  session: Session,
119
- query: Query,
120
- table: Type[DeclarativeMeta],
121
+ stmt: Select,
122
+ table: Type[T],
121
123
  id_column: str = "id",
122
124
  parent_column: str = "parent_id",
123
125
  is_parent: OptionalBoolean = None,
124
- ) -> Query:
126
+ ) -> Select:
125
127
  id_attr = getattr(table, id_column, None)
126
128
  if id_attr is None or not isinstance(id_attr, InstrumentedAttribute):
127
- return query
129
+ return stmt
128
130
  parent_attr = getattr(table, parent_column, None)
129
131
  if parent_attr is None or not isinstance(parent_attr, InstrumentedAttribute):
130
- return query
132
+ return stmt
131
133
  if is_parent is not None:
132
134
  child_table = aliased(table)
133
135
  child_parent_attr = getattr(child_table, parent_column)
134
- subq = session.query(child_table).filter(child_parent_attr == id_attr).exists()
135
- query = query.filter(subq if is_parent else ~subq)
136
- return query
136
+ subq = select(child_table).filter(child_parent_attr == id_attr).exists()
137
+ stmt = stmt.filter(subq if is_parent else ~subq)
138
+ return stmt
137
139
 
138
140
 
139
141
  def filter_is_child(
140
- query: Query,
141
- table: Type[DeclarativeMeta],
142
+ stmt: Select,
143
+ table: Type[T],
142
144
  parent_column: str = "parent_id",
143
145
  is_child: OptionalBoolean = None,
144
- ) -> Query:
146
+ ) -> Select:
145
147
  parent_attr = getattr(table, parent_column, None)
146
148
  if parent_attr is None or not isinstance(parent_attr, InstrumentedAttribute):
147
- return query
149
+ return stmt
148
150
  if is_child is not None:
149
- query = query.filter(
151
+ stmt = stmt.filter(
150
152
  parent_attr.is_not(None) if is_child else parent_attr.is_(None)
151
153
  )
152
- return query
154
+ return stmt
153
155
 
154
156
 
155
157
  def filter_is_leaf(
156
158
  session: Session,
157
- query: Query,
158
- table: Type[DeclarativeMeta],
159
+ stmt: Select,
160
+ table: Type[T],
159
161
  id_column: str = "id",
160
162
  parent_column: str = "parent_id",
161
163
  is_leaf: OptionalBoolean = None,
162
- ) -> Query:
164
+ ) -> Select:
163
165
  id_attr = getattr(table, id_column, None)
164
166
  if id_attr is None or not isinstance(id_attr, InstrumentedAttribute):
165
- return query
167
+ return stmt
166
168
  parent_attr = getattr(table, parent_column, None)
167
169
  if parent_attr is None or not isinstance(parent_attr, InstrumentedAttribute):
168
- return query
170
+ return stmt
169
171
  if is_leaf is not None:
170
172
  child_table = aliased(table)
171
173
  child_parent_attr = getattr(child_table, parent_column)
172
- subq = session.query(child_table).filter(child_parent_attr == id_attr).exists()
173
- query = query.filter(~subq if is_leaf else subq)
174
- return query
174
+ subq = select(child_table).filter(child_parent_attr == id_attr).exists()
175
+ stmt = stmt.filter(~subq if is_leaf else subq)
176
+ return stmt
175
177
 
176
178
 
177
179
  def search(
178
- query: Query,
179
- table: Type[DeclarativeMeta],
180
+ stmt: Select,
181
+ table: Type[T],
180
182
  search: OptionalString = None,
181
183
  columns: OptionalListOfStrings = None,
182
- ) -> Query:
184
+ ) -> Select:
183
185
  if search is None:
184
- return query
186
+ return stmt
185
187
 
186
188
  search_term = f"%{search}%"
187
- sqla_table: Table = table.__table__ # type: ignore
189
+ sqla_table = table.__table__
188
190
  search_filters = []
189
191
 
190
192
  for name, attr in vars(table).items():
191
- # Only consider InstrumentedAttribute (mapped columns)
192
193
  if not isinstance(attr, InstrumentedAttribute):
193
194
  continue
194
195
 
195
196
  try:
196
- column: Column = sqla_table.columns[name]
197
+ column = sqla_table.columns[name]
197
198
  except KeyError:
198
199
  continue
199
200
 
200
- # Skip columns not in the user-provided list
201
201
  if columns is not None and name not in columns:
202
202
  continue
203
203
 
204
- # Only allow string/TEXT columns
205
204
  if isinstance(column.type, (String, TEXT)):
206
205
  search_filters.append(cast(attr, TEXT).ilike(search_term))
207
206
 
208
207
  if search_filters:
209
- query = query.filter(or_(*search_filters))
208
+ stmt = stmt.filter(or_(*search_filters))
210
209
 
211
- return query
210
+ return stmt
212
211
 
213
212
 
214
213
  def sort(
215
- query: Query,
216
- table: Type[DeclarativeMeta],
214
+ stmt: Select,
215
+ table: Type[T],
217
216
  sort_columns: Sequence[SortColumn],
218
- ) -> Query:
217
+ ) -> Select:
219
218
  for sort_column in sort_columns:
220
219
  try:
221
220
  sort_col = getattr(table, sort_column.name)
222
221
  sort_col = (
223
222
  asc(sort_col) if sort_column.order is Order.ASC else desc(sort_col)
224
223
  )
225
- query = query.order_by(sort_col)
224
+ stmt = stmt.order_by(sort_col)
226
225
  except AttributeError:
227
226
  continue
228
- return query
227
+ return stmt
229
228
 
230
229
 
231
- def paginate(query: Query, page: int, limit: int) -> Query:
232
- offset: int = int((page - 1) * limit) # Calculate offset based on page
233
- query = query.limit(limit=limit).offset(offset=offset)
234
- return query
230
+ def paginate(stmt: Select, page: int, limit: int) -> Select:
231
+ offset: int = int((page - 1) * limit)
232
+ stmt = stmt.limit(limit).offset(offset)
233
+ return stmt
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo-database
3
- Version: 0.0.19
3
+ Version: 0.0.21
4
4
  Summary: Database package for MaleoSuite
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: Proprietary
@@ -46,10 +46,10 @@ Requires-Dist: importlib_metadata>=8.7.0
46
46
  Requires-Dist: maleo-constants>=0.0.6
47
47
  Requires-Dist: maleo-dtos>=0.0.18
48
48
  Requires-Dist: maleo-enums>=0.0.6
49
- Requires-Dist: maleo-exceptions>=0.0.25
49
+ Requires-Dist: maleo-exceptions>=0.0.26
50
50
  Requires-Dist: maleo-logging>=0.0.8
51
51
  Requires-Dist: maleo-mixins>=0.0.13
52
- Requires-Dist: maleo-schemas>=0.0.23
52
+ Requires-Dist: maleo-schemas>=0.0.24
53
53
  Requires-Dist: maleo-types-base>=0.0.2
54
54
  Requires-Dist: maleo-types-controllers>=0.0.1
55
55
  Requires-Dist: maleo-types-enums>=0.0.4
@@ -10,18 +10,12 @@ maleo/database/config/pooling.py,sha256=4Q0rkM4FAt6xAbBG1PItHmMSzS7aCZNBgFPeaEjK
10
10
  maleo/database/managers/__init__.py,sha256=45un_rhnAeSFQLxmEsEXNsYLfg6kpWWljsXpqDFWZQk,13073
11
11
  maleo/database/managers/client.py,sha256=hdfPn8Ae8G78yZYDxI1FylcM-rPMIL8Ty4XmsASDrt0,3065
12
12
  maleo/database/managers/engine.py,sha256=aF7JCjSYujodbn2QQrT_OeLX-WjUdIv5cBgWtvLgHI0,1725
13
- maleo/database/managers/session.py,sha256=QCyw1Um0xTmEGCHxX3kQ6z7Q_L2TT8Eq3_8NcpKIsxE,19000
13
+ maleo/database/managers/session.py,sha256=aKyuiHiA171Vptr92AA5U-mRwzwbKXb9RAZ9Wq5Wo4s,19557
14
14
  maleo/database/orm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- maleo/database/orm/base.py,sha256=qdRK_TQqDoZ1hANvm1mJDiblqFr77J1IhBnlENr7RK8,229
16
- maleo/database/orm/queries.py,sha256=NX9PYT6GZgwIhtRc7WSTS9EUzqTZCb-ib99ccYjmUkM,7643
17
- maleo/database/orm/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- maleo/database/orm/models/table.py,sha256=UhEH7WN1lrNY3uTb4a5VWO4l9UaYhnRQK_0Z7R0lMNA,457
19
- maleo/database/orm/models/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- maleo/database/orm/models/mixins/identifier.py,sha256=jICVsLUFw_f7TV_aX4KTTs_ycH35MRtRj5boTqctmZo,425
21
- maleo/database/orm/models/mixins/status.py,sha256=Jzithn-Hl2ct1AqboGZSXrA35aaQEDvqtaB8oL7KIyo,376
22
- maleo/database/orm/models/mixins/timestamp.py,sha256=TWqBTBvgSxcPsK0m7ggVrkHqzlqCM-2Zox7TAwCxd0I,1500
23
- maleo_database-0.0.19.dist-info/licenses/LICENSE,sha256=aftGsecnk7TWVX-7KW94FqK4Syy6YSZ8PZEF7EcIp3M,2621
24
- maleo_database-0.0.19.dist-info/METADATA,sha256=IK-_9iOgz-THwQ2XJcxF8yJU-U4XZ_NMlsJ5jSOCPgQ,3837
25
- maleo_database-0.0.19.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
- maleo_database-0.0.19.dist-info/top_level.txt,sha256=3Tpd1siVsfYoeI9FEOJNYnffx_shzZ3wsPpTvz5bljc,6
27
- maleo_database-0.0.19.dist-info/RECORD,,
15
+ maleo/database/orm/mixins.py,sha256=rW-FVOrRm_R8yJyrcwGoVIPPV1oAOhSVFmANHR7bowU,2372
16
+ maleo/database/orm/queries.py,sha256=o_6KHMfQeSp_3sJWusXll-NQBxPm8XUJepnWBahoyv4,7152
17
+ maleo_database-0.0.21.dist-info/licenses/LICENSE,sha256=aftGsecnk7TWVX-7KW94FqK4Syy6YSZ8PZEF7EcIp3M,2621
18
+ maleo_database-0.0.21.dist-info/METADATA,sha256=YPQk2kQ8dTfnfnnwwvgm7M23GLDgWEnJDpENItdGTt0,3837
19
+ maleo_database-0.0.21.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
+ maleo_database-0.0.21.dist-info/top_level.txt,sha256=3Tpd1siVsfYoeI9FEOJNYnffx_shzZ3wsPpTvz5bljc,6
21
+ maleo_database-0.0.21.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- from sqlalchemy.orm import DeclarativeMeta, declarative_base
2
- from typing import Any, Type
3
- from .models.table import BaseTable
4
-
5
-
6
- def create_base(cls: Type[Any] = BaseTable) -> DeclarativeMeta:
7
- return declarative_base(cls=cls)
File without changes
File without changes
@@ -1,11 +0,0 @@
1
- from sqlalchemy.dialects.postgresql import UUID as PostgresUUID
2
- from sqlalchemy.orm import Mapped, mapped_column
3
- from sqlalchemy.types import Integer
4
- from uuid import UUID as PythonUUID, uuid4
5
-
6
-
7
- class DataIdentifier:
8
- id: Mapped[int] = mapped_column("id", Integer, primary_key=True)
9
- uuid: Mapped[PythonUUID] = mapped_column(
10
- "uuid", PostgresUUID(as_uuid=True), default=uuid4, unique=True, nullable=False
11
- )
@@ -1,12 +0,0 @@
1
- from sqlalchemy.orm import Mapped, mapped_column
2
- from sqlalchemy.types import Enum
3
- from maleo.enums.status import DataStatus as DataStatusEnum
4
-
5
-
6
- class DataStatus:
7
- status: Mapped[DataStatusEnum] = mapped_column(
8
- "status",
9
- Enum(DataStatusEnum, name="statustype", create_constraints=True),
10
- default=DataStatusEnum.ACTIVE,
11
- nullable=False,
12
- )
@@ -1,65 +0,0 @@
1
- from datetime import datetime
2
- from sqlalchemy import func
3
- from sqlalchemy.orm import Mapped, mapped_column
4
- from sqlalchemy.types import TIMESTAMP
5
- from maleo.types.base.datetime import OptionalDatetime
6
-
7
-
8
- class CreateTimestamp:
9
- created_at: Mapped[datetime] = mapped_column(
10
- "created_at",
11
- TIMESTAMP(timezone=True),
12
- server_default=func.now(),
13
- nullable=False,
14
- )
15
-
16
-
17
- class UpdateTimestamp:
18
- updated_at: Mapped[datetime] = mapped_column(
19
- "updated_at",
20
- TIMESTAMP(timezone=True),
21
- server_default=func.now(),
22
- onupdate=func.now(),
23
- nullable=False,
24
- )
25
-
26
-
27
- class LifecyleTimestamp(UpdateTimestamp, CreateTimestamp):
28
- pass
29
-
30
-
31
- class DeleteTimestamp:
32
- deleted_at: Mapped[OptionalDatetime] = mapped_column(
33
- "deleted_at", TIMESTAMP(timezone=True)
34
- )
35
-
36
-
37
- class RestoreTimestamp:
38
- restored_at: Mapped[OptionalDatetime] = mapped_column(
39
- "restored_at", TIMESTAMP(timezone=True)
40
- )
41
-
42
-
43
- class DeactivateTimestamp:
44
- deactivated_at: Mapped[OptionalDatetime] = mapped_column(
45
- "deactivated_at", TIMESTAMP(timezone=True)
46
- )
47
-
48
-
49
- class ActivateTimestamp:
50
- activated_at: Mapped[datetime] = mapped_column(
51
- "activated_at",
52
- TIMESTAMP(timezone=True),
53
- server_default=func.now(),
54
- nullable=False,
55
- )
56
-
57
-
58
- class StatusTimestamp(
59
- ActivateTimestamp, DeactivateTimestamp, RestoreTimestamp, DeleteTimestamp
60
- ):
61
- pass
62
-
63
-
64
- class DataTimestamp(StatusTimestamp, LifecyleTimestamp):
65
- pass
@@ -1,17 +0,0 @@
1
- from sqlalchemy.orm import declared_attr
2
- from maleo.utils.formatters.case import to_snake
3
- from .mixins.identifier import DataIdentifier
4
- from .mixins.status import DataStatus
5
- from .mixins.timestamp import DataTimestamp
6
-
7
-
8
- class BaseTable:
9
- __abstract__ = True
10
-
11
- @declared_attr # type: ignore
12
- def __tablename__(cls) -> str:
13
- return to_snake(cls.__name__) # type: ignore
14
-
15
-
16
- class DataTable(DataStatus, DataTimestamp, DataIdentifier):
17
- pass