alpha-python 0.1.0__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.
- alpha/__init__.py +0 -0
- alpha/adapters/__init__.py +0 -0
- alpha/adapters/sqla_unit_of_work.py +120 -0
- alpha/domain/__init__.py +0 -0
- alpha/domain/models/__init__.py +0 -0
- alpha/domain/models/base_model.py +25 -0
- alpha/encoder.py +62 -0
- alpha/exceptions.py +99 -0
- alpha/factories/__init__.py +0 -0
- alpha/factories/_type_conversion_matrix.py +233 -0
- alpha/factories/_type_mapping.py +29 -0
- alpha/factories/class_factories.py +496 -0
- alpha/factories/default_field_factory.py +50 -0
- alpha/factories/field_iterator.py +188 -0
- alpha/factories/logging_handler_factory.py +86 -0
- alpha/factories/model_class_factory.py +176 -0
- alpha/factories/models/__init__.py +0 -0
- alpha/factories/models/factory_classes.py +20 -0
- alpha/factories/request_factory.py +211 -0
- alpha/factories/response_factory.py +186 -0
- alpha/factories/type_factories.py +204 -0
- alpha/infra/__init__.py +0 -0
- alpha/infra/database/__init__.py +0 -0
- alpha/infra/database/sql_alchemy_database.py +159 -0
- alpha/infra/database/sql_alchemy_view.py +48 -0
- alpha/infra/models/__init__.py +0 -0
- alpha/infra/models/filter_operators.py +98 -0
- alpha/infra/models/json_patch.py +21 -0
- alpha/infra/models/order_by.py +69 -0
- alpha/infra/models/query_clause.py +45 -0
- alpha/infra/models/search_filter.py +586 -0
- alpha/interfaces/__init__.py +0 -0
- alpha/interfaces/attrs_instance.py +10 -0
- alpha/interfaces/dataclass_instance.py +11 -0
- alpha/interfaces/factories.py +102 -0
- alpha/interfaces/openapi_model.py +21 -0
- alpha/interfaces/patchable.py +8 -0
- alpha/interfaces/sql_database.py +36 -0
- alpha/interfaces/sql_mapper.py +23 -0
- alpha/interfaces/sql_repository.py +380 -0
- alpha/interfaces/token_factory.py +56 -0
- alpha/interfaces/unit_of_work.py +53 -0
- alpha/interfaces/updateable.py +7 -0
- alpha/py.typed +0 -0
- alpha/repositories/__init__.py +0 -0
- alpha/repositories/default_sql_repository.py +679 -0
- alpha/repositories/models/__init__.py +0 -0
- alpha/repositories/models/repository_model.py +16 -0
- alpha/services/__init__.py +0 -0
- alpha/services/authentication_service.py +71 -0
- alpha/utils/__init__.py +0 -0
- alpha/utils/_http_codes.py +148 -0
- alpha/utils/is_attrs.py +18 -0
- alpha/utils/logging_configurator.py +133 -0
- alpha/utils/logging_level_checker.py +26 -0
- alpha/utils/response_object.py +26 -0
- alpha/utils/version_check.py +17 -0
- alpha_python-0.1.0.dist-info/METADATA +22 -0
- alpha_python-0.1.0.dist-info/RECORD +62 -0
- alpha_python-0.1.0.dist-info/WHEEL +5 -0
- alpha_python-0.1.0.dist-info/licenses/LICENSE +21 -0
- alpha_python-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
from contextlib import suppress
|
|
3
|
+
|
|
4
|
+
import jsonpatch
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class JsonPatch(jsonpatch.JsonPatch):
|
|
8
|
+
def __init__(self, *args, **kwargs):
|
|
9
|
+
super().__init__(*args, **kwargs)
|
|
10
|
+
self.update_dates()
|
|
11
|
+
|
|
12
|
+
def update_dates(self) -> None:
|
|
13
|
+
"""Post init to ensure that if a date can be formated to isoformat this
|
|
14
|
+
is done.
|
|
15
|
+
"""
|
|
16
|
+
for update in self:
|
|
17
|
+
if isinstance(update['value'], str):
|
|
18
|
+
with suppress(ValueError):
|
|
19
|
+
update['value'] = datetime.datetime.fromisoformat(
|
|
20
|
+
update['value']
|
|
21
|
+
)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from enum import Enum, auto
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from sqlalchemy import BinaryExpression
|
|
6
|
+
from sqlalchemy.orm import Query
|
|
7
|
+
from sqlalchemy.orm.attributes import InstrumentedAttribute
|
|
8
|
+
|
|
9
|
+
from alpha.infra.models.query_clause import QueryClause
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Order(Enum):
|
|
13
|
+
ASC = auto()
|
|
14
|
+
DESC = auto()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class OrderBy(QueryClause):
|
|
19
|
+
field: str | InstrumentedAttribute[Any] = ""
|
|
20
|
+
order: Order = Order.ASC
|
|
21
|
+
|
|
22
|
+
def __post_init__(self) -> None:
|
|
23
|
+
super().__post_init__()
|
|
24
|
+
self.__class__ = self._get_filter_class()
|
|
25
|
+
|
|
26
|
+
def _get_filter_class(self):
|
|
27
|
+
match self.order:
|
|
28
|
+
case Order.ASC:
|
|
29
|
+
return AscendingOrder
|
|
30
|
+
case Order.DESC:
|
|
31
|
+
return DescendingOrder
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AscendingOrder(OrderBy):
|
|
35
|
+
@property
|
|
36
|
+
def filter_statement(self) -> BinaryExpression[Any]:
|
|
37
|
+
"""Returns a lesser then filter statement
|
|
38
|
+
|
|
39
|
+
Returns
|
|
40
|
+
-------
|
|
41
|
+
Filter statement
|
|
42
|
+
"""
|
|
43
|
+
if self._instrumented_attr:
|
|
44
|
+
return self._instrumented_attr.asc()
|
|
45
|
+
self._raise_instrumented_attr_exception()
|
|
46
|
+
|
|
47
|
+
def query_clause(self, query: Query[Any]):
|
|
48
|
+
if self._instrumented_attr:
|
|
49
|
+
return query.order_by(self._instrumented_attr.asc())
|
|
50
|
+
self._raise_instrumented_attr_exception()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class DescendingOrder(OrderBy):
|
|
54
|
+
@property
|
|
55
|
+
def filter_statement(self) -> BinaryExpression[Any]:
|
|
56
|
+
"""Returns a lesser then filter statement
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
Filter statement
|
|
61
|
+
"""
|
|
62
|
+
if self._instrumented_attr:
|
|
63
|
+
return self._instrumented_attr.desc()
|
|
64
|
+
self._raise_instrumented_attr_exception()
|
|
65
|
+
|
|
66
|
+
def query_clause(self, query: Query[Any]):
|
|
67
|
+
if self._instrumented_attr:
|
|
68
|
+
return query.order_by(self._instrumented_attr.desc())
|
|
69
|
+
self._raise_instrumented_attr_exception()
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from sqlalchemy.orm.attributes import InstrumentedAttribute
|
|
5
|
+
from sqlalchemy.orm.query import Query
|
|
6
|
+
|
|
7
|
+
from alpha import exceptions
|
|
8
|
+
from alpha.domain.models.base_model import BaseDomainModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class QueryClause:
|
|
13
|
+
field: str | InstrumentedAttribute[str]
|
|
14
|
+
_domain_model: BaseDomainModel | None = None
|
|
15
|
+
_instrumented_attr: InstrumentedAttribute[Any] | None = None
|
|
16
|
+
|
|
17
|
+
def __post_init__(self) -> None:
|
|
18
|
+
# Get key name if field is an instrumented attribute
|
|
19
|
+
if isinstance(self.field, InstrumentedAttribute):
|
|
20
|
+
self._instrumented_attr = self.field
|
|
21
|
+
self.field = self.field.key
|
|
22
|
+
|
|
23
|
+
# Try to get the instrumented attribute if only a field name is given
|
|
24
|
+
self.set_domain_model()
|
|
25
|
+
|
|
26
|
+
def query_clause(self, query: Query[Any]) -> Query[Any]:
|
|
27
|
+
raise NotImplementedError
|
|
28
|
+
|
|
29
|
+
def set_domain_model(self, model: BaseDomainModel | None = None):
|
|
30
|
+
self._domain_model = model
|
|
31
|
+
|
|
32
|
+
if not self._instrumented_attr:
|
|
33
|
+
if self._domain_model:
|
|
34
|
+
self._instrumented_attr = getattr(
|
|
35
|
+
self._domain_model, self.field # type: ignore
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def _raise_instrumented_attr_exception(self):
|
|
39
|
+
raise exceptions.InstrumentedAttributeMissing(
|
|
40
|
+
"""
|
|
41
|
+
The 'field' attribute needs to be of an \
|
|
42
|
+
sqlalchemy.orm.InstrumentedAttribute type, or specify the mapped domain model \
|
|
43
|
+
by adding the _domain_model attribute
|
|
44
|
+
"""
|
|
45
|
+
)
|