maleo-foundation 0.0.47__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo_foundation
3
- Version: 0.0.47
3
+ Version: 0.0.48
4
4
  Summary: Foundation package for Maleo
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: MIT
@@ -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=O8U-RknKlihONxnjlKLQ02Q2aarH2GzEf2T4VABCMe4,4393
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
@@ -53,7 +51,7 @@ maleo_foundation/utils/logger.py,sha256=sK95UC5jLKKuAV8lu8pFnoQfLRB0nPtCbmAC5CJL
53
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.47.dist-info/METADATA,sha256=u2R6BiNSqzVrxOPsFQgRx9WsB15xvdmatl0NRvd6Eqw,3160
57
- maleo_foundation-0.0.47.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
58
- maleo_foundation-0.0.47.dist-info/top_level.txt,sha256=_iBos3F_bhEOdjOnzeiEYSrCucasc810xXtLBXI8cQc,17
59
- maleo_foundation-0.0.47.dist-info/RECORD,,
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,,
@@ -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
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