maleo-foundation 0.0.46__py3-none-any.whl → 0.0.48__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.
- maleo_foundation/utils/query.py +1 -1
- {maleo_foundation-0.0.46.dist-info → maleo_foundation-0.0.48.dist-info}/METADATA +1 -1
- {maleo_foundation-0.0.46.dist-info → maleo_foundation-0.0.48.dist-info}/RECORD +5 -7
- maleo_foundation/controller.py +0 -50
- maleo_foundation/query.py +0 -95
- {maleo_foundation-0.0.46.dist-info → maleo_foundation-0.0.48.dist-info}/WHEEL +0 -0
- {maleo_foundation-0.0.46.dist-info → maleo_foundation-0.0.48.dist-info}/top_level.txt +0 -0
maleo_foundation/utils/query.py
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
maleo_foundation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
maleo_foundation/constants.py,sha256=aBmEfWlBqZxi0k-n6h2NM1YRLOjMnheEiLyQcjP-zCQ,1164
|
|
3
|
-
maleo_foundation/controller.py,sha256=9ceIEajWLouLBph2NQe7L7tQNnQyyW_ETojilSeFv6M,2991
|
|
4
3
|
maleo_foundation/enums.py,sha256=uXA5fLFeDXwlspUjU4DXSB68dfanxEwIJhsAMZXhsYo,2359
|
|
5
4
|
maleo_foundation/extended_types.py,sha256=pIKt-_9tby4rmune3fmWcCW_mohaNRh_1lywBmdc-L4,301
|
|
6
|
-
maleo_foundation/query.py,sha256=wlUkGS7ZOFnz1_reGvA54_aHD064LVl98DRKKDPa84M,4398
|
|
7
5
|
maleo_foundation/types.py,sha256=D_EtYK-sNeELSbc-ngX65iuQCRhZQB4TtV73P6Gl76o,1206
|
|
8
6
|
maleo_foundation/clients/__init__.py,sha256=W8vydJYeDEi6gdmOZSBFSSDsfZJtb8C05CHErZgsZ30,188
|
|
9
7
|
maleo_foundation/clients/logging.py,sha256=JaAYfLkci97bTb6Wt5YO1uxQK5afIMuR8kin0q5rlIM,1145
|
|
@@ -50,10 +48,10 @@ maleo_foundation/utils/__init__.py,sha256=FavmL5XYGCm955EAKiWWcXYeU15p5rSzfcglpV
|
|
|
50
48
|
maleo_foundation/utils/controller.py,sha256=hapDGng4q5XTfaG18M3bbFsFGqEOlkNKRzGf8BMKrhs,2996
|
|
51
49
|
maleo_foundation/utils/exceptions.py,sha256=mcvBwHm6uWpVQkPtO1T2j-GaTYEiyPOeGxiDL9-sjNA,3639
|
|
52
50
|
maleo_foundation/utils/logger.py,sha256=sK95UC5jLKKuAV8lu8pFnoQfLRB0nPtCbmAC5CJLgO8,3338
|
|
53
|
-
maleo_foundation/utils/query.py,sha256
|
|
51
|
+
maleo_foundation/utils/query.py,sha256=qKNcjf5J7_Q7NjA79BO6_TpZVdYcF8YIO68F9M501ew,4398
|
|
54
52
|
maleo_foundation/utils/formatter/__init__.py,sha256=iKf5YCbEdg1qKnFHyKqqcQbqAqEeRUf8mhI3v3dQoj8,78
|
|
55
53
|
maleo_foundation/utils/formatter/case.py,sha256=TmvvlfzGdC_omMTB5vAa40TZBxQ3hnr-SYeo0M52Rlg,1352
|
|
56
|
-
maleo_foundation-0.0.
|
|
57
|
-
maleo_foundation-0.0.
|
|
58
|
-
maleo_foundation-0.0.
|
|
59
|
-
maleo_foundation-0.0.
|
|
54
|
+
maleo_foundation-0.0.48.dist-info/METADATA,sha256=jCMgxxpqpC_h2P6WpVsi6v6DDJgbzaCUXPteFKuWU6Y,3160
|
|
55
|
+
maleo_foundation-0.0.48.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
|
|
56
|
+
maleo_foundation-0.0.48.dist-info/top_level.txt,sha256=_iBos3F_bhEOdjOnzeiEYSrCucasc810xXtLBXI8cQc,17
|
|
57
|
+
maleo_foundation-0.0.48.dist-info/RECORD,,
|
maleo_foundation/controller.py
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
from fastapi import status
|
|
2
|
-
from typing import Type, Any
|
|
3
|
-
from maleo_foundation.enums import BaseEnums
|
|
4
|
-
from maleo_foundation.models.responses import BaseResponses
|
|
5
|
-
from maleo_foundation.models.transfers.results.service.controllers.rest import BaseServiceRESTControllerResults
|
|
6
|
-
from maleo_foundation.models.transfers.parameters.service import BaseServiceParametersTransfers
|
|
7
|
-
from maleo_foundation.expanded_types.service import ExpandedServiceTypes
|
|
8
|
-
|
|
9
|
-
class BaseController:
|
|
10
|
-
@staticmethod
|
|
11
|
-
def check_unique_existence(
|
|
12
|
-
check:BaseServiceParametersTransfers.UniqueFieldCheck,
|
|
13
|
-
get_single_parameters_class:Type[ExpandedServiceTypes.GetSingleParameter],
|
|
14
|
-
get_single_service_function:ExpandedServiceTypes.SyncGetSingleFunction,
|
|
15
|
-
create_failed_response_class:Type[BaseResponses.Fail],
|
|
16
|
-
update_failed_response_class:Type[BaseResponses.Fail],
|
|
17
|
-
**additional_get_parameters:Any
|
|
18
|
-
) -> BaseServiceRESTControllerResults:
|
|
19
|
-
"""Generic helper function to check if a unique value exists in the database."""
|
|
20
|
-
|
|
21
|
-
#* Return early if nullable and no new value
|
|
22
|
-
if check.nullable and check.new_value is None:
|
|
23
|
-
return BaseServiceRESTControllerResults(success=True, content=None)
|
|
24
|
-
|
|
25
|
-
#* Return early if values are unchanged on update
|
|
26
|
-
if check.operation == BaseEnums.OperationType.UPDATE and check.old_value == check.new_value:
|
|
27
|
-
return BaseServiceRESTControllerResults(success=True, content=None)
|
|
28
|
-
|
|
29
|
-
#* Prepare parameters to query for existing data
|
|
30
|
-
get_single_parameters = get_single_parameters_class(identifier=check.field, value=check.new_value)
|
|
31
|
-
|
|
32
|
-
#* Query the existing data using provided function
|
|
33
|
-
service_result:ExpandedServiceTypes.GetSingleResult = get_single_service_function(parameters=get_single_parameters, **additional_get_parameters)
|
|
34
|
-
if not service_result.success:
|
|
35
|
-
content = BaseResponses.ServerError.model_validate(service_result.model_dump(exclude_unset=True)).model_dump()
|
|
36
|
-
return BaseServiceRESTControllerResults(success=False, content=content, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
37
|
-
|
|
38
|
-
#* Handle case if duplicate is found
|
|
39
|
-
if service_result.data:
|
|
40
|
-
description = f"External error: {check.field} of '{check.new_value}' already exists in the database"
|
|
41
|
-
other = check.suggestion or f"Select another {check.field} value"
|
|
42
|
-
if check.operation == BaseEnums.OperationType.CREATE:
|
|
43
|
-
content = create_failed_response_class(description=description, other=other).model_dump()
|
|
44
|
-
elif check.operation == BaseEnums.OperationType.UPDATE:
|
|
45
|
-
content = update_failed_response_class(description=description, other=other).model_dump()
|
|
46
|
-
|
|
47
|
-
return BaseServiceRESTControllerResults(success=False, content=content, status_code=status.HTTP_400_BAD_REQUEST)
|
|
48
|
-
|
|
49
|
-
#* No duplicates found
|
|
50
|
-
return BaseServiceRESTControllerResults(success=True, content=None)
|
maleo_foundation/query.py
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
from sqlalchemy import Column, Table, in_
|
|
2
|
-
from sqlalchemy.orm import Query
|
|
3
|
-
from sqlalchemy.orm.attributes import InstrumentedAttribute
|
|
4
|
-
from sqlalchemy.sql.expression import or_, asc, cast, desc
|
|
5
|
-
from sqlalchemy.types import DATE, String, TEXT, TIMESTAMP
|
|
6
|
-
from typing import Type
|
|
7
|
-
from maleo_foundation.db import DatabaseManager
|
|
8
|
-
from maleo_foundation.types import BaseTypes
|
|
9
|
-
from maleo_foundation.extended_types import ExtendedTypes
|
|
10
|
-
|
|
11
|
-
class BaseQuery:
|
|
12
|
-
@staticmethod
|
|
13
|
-
def filter_column(query:Query, table:Type[DatabaseManager.Base], column:str, value:BaseTypes.OptionalAny) -> Query:
|
|
14
|
-
if not value:
|
|
15
|
-
return query
|
|
16
|
-
column_attr = getattr(table, column, None)
|
|
17
|
-
if not column_attr:
|
|
18
|
-
return query
|
|
19
|
-
if isinstance(value, list):
|
|
20
|
-
value_filters = [column_attr == val for val in value]
|
|
21
|
-
query = query.filter(or_(*value_filters))
|
|
22
|
-
return query
|
|
23
|
-
query = query.filter(column_attr == value)
|
|
24
|
-
return query
|
|
25
|
-
|
|
26
|
-
@staticmethod
|
|
27
|
-
def filter_ids(query:Query, table:Type[DatabaseManager.Base], column:str, ids:BaseTypes.OptionalListOfIntegers) -> Query:
|
|
28
|
-
if ids is not None:
|
|
29
|
-
column_attr = getattr(table, column, None)
|
|
30
|
-
if column_attr:
|
|
31
|
-
id_filters = [column_attr == id for id in ids]
|
|
32
|
-
query = query.filter(or_(*id_filters))
|
|
33
|
-
return query
|
|
34
|
-
|
|
35
|
-
@staticmethod
|
|
36
|
-
def filter_timestamps(query:Query, table:Type[DatabaseManager.Base], date_filters:ExtendedTypes.ListOfDateFilters) -> Query:
|
|
37
|
-
if date_filters and len(date_filters) > 0:
|
|
38
|
-
for date_filter in date_filters:
|
|
39
|
-
try:
|
|
40
|
-
table:Table = table.__table__
|
|
41
|
-
column:Column = table.columns[date_filter.name]
|
|
42
|
-
column_attr:InstrumentedAttribute = getattr(table, date_filter.name)
|
|
43
|
-
if isinstance(column.type, (TIMESTAMP, DATE)):
|
|
44
|
-
if date_filter.from_date and date_filter.to_date:
|
|
45
|
-
query = query.filter(column_attr.between(date_filter.from_date, date_filter.to_date))
|
|
46
|
-
elif date_filter.from_date:
|
|
47
|
-
query = query.filter(column_attr >= date_filter.from_date)
|
|
48
|
-
elif date_filter.to_date:
|
|
49
|
-
query = query.filter(column_attr <= date_filter.to_date)
|
|
50
|
-
except KeyError:
|
|
51
|
-
continue
|
|
52
|
-
return query
|
|
53
|
-
|
|
54
|
-
@staticmethod
|
|
55
|
-
def filter_statuses(query:Query, table:Type[DatabaseManager.Base], statuses:BaseTypes.OptionalListOfStatuses) -> Query:
|
|
56
|
-
if statuses is not None:
|
|
57
|
-
status_filters = [table.status == status for status in statuses]
|
|
58
|
-
query = query.filter(or_(*status_filters))
|
|
59
|
-
return query
|
|
60
|
-
|
|
61
|
-
@staticmethod
|
|
62
|
-
def filter_search(query:Query, table:Type[DatabaseManager.Base], search:BaseTypes.OptionalString) -> Query:
|
|
63
|
-
if search:
|
|
64
|
-
search_term = f"%{search}%" #* Use wildcard for partial matching
|
|
65
|
-
search_filters = []
|
|
66
|
-
sqla_table:Table = table.__table__
|
|
67
|
-
for name, attr in vars(table).items():
|
|
68
|
-
try:
|
|
69
|
-
column: Column = sqla_table.columns[name]
|
|
70
|
-
if not isinstance(attr, InstrumentedAttribute):
|
|
71
|
-
continue
|
|
72
|
-
if isinstance(column.type, (String, TEXT)):
|
|
73
|
-
search_filters.append(cast(attr, TEXT).ilike(search_term))
|
|
74
|
-
except KeyError:
|
|
75
|
-
continue
|
|
76
|
-
if search_filters:
|
|
77
|
-
query = query.filter(or_(*search_filters))
|
|
78
|
-
return query
|
|
79
|
-
|
|
80
|
-
@staticmethod
|
|
81
|
-
def sort(query:Query, table:Type[DatabaseManager.Base], sort_columns:ExtendedTypes.ListOfSortColumns) -> Query:
|
|
82
|
-
for sort_column in sort_columns:
|
|
83
|
-
try:
|
|
84
|
-
sort_col = getattr(table, sort_column.name)
|
|
85
|
-
sort_col = asc(sort_col) if sort_column.order.value.lower() == "asc" else desc(sort_col)
|
|
86
|
-
query = query.order_by(sort_col)
|
|
87
|
-
except AttributeError:
|
|
88
|
-
continue
|
|
89
|
-
return query
|
|
90
|
-
|
|
91
|
-
@staticmethod
|
|
92
|
-
def paginate(query:Query, page:int, limit:int) -> Query:
|
|
93
|
-
offset:int = (page - 1) * limit #* Calculate offset based on page
|
|
94
|
-
query = query.limit(limit=limit).offset(offset=offset)
|
|
95
|
-
return query
|
|
File without changes
|
|
File without changes
|