muffin-rest 9.2.0__tar.gz → 9.4.0__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.
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/PKG-INFO +1 -1
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/filters.py +17 -4
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/mongo/filters.py +3 -2
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/peewee/filters.py +6 -4
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/sqlalchemy/filters.py +6 -6
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/types.py +3 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/pyproject.toml +1 -1
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/LICENSE +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/README.rst +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/__init__.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/api.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/errors.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/handler.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/limits.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/marshmallow.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/mongo/__init__.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/mongo/schema.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/mongo/sorting.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/mongo/types.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/mongo/utils.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/openapi.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/options.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/peewee/__init__.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/peewee/handler.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/peewee/openapi.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/peewee/options.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/peewee/schemas.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/peewee/sorting.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/peewee/types.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/peewee/utils.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/py.typed +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/redoc.html +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/schemas.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/sorting.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/sqlalchemy/__init__.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/sqlalchemy/sorting.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/sqlalchemy/types.py +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/swagger.html +0 -0
- {muffin_rest-9.2.0 → muffin_rest-9.4.0}/muffin_rest/utils.py +0 -0
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
"""Support API filters."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
|
|
4
5
|
import operator
|
|
5
6
|
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Iterable, Mapping, Optional # py39
|
|
6
7
|
|
|
7
8
|
import marshmallow as ma
|
|
8
|
-
from asgi_tools._compat import json_loads
|
|
9
|
+
from asgi_tools._compat import json_loads
|
|
9
10
|
|
|
10
11
|
from .utils import Mutate, Mutator
|
|
11
12
|
|
|
12
13
|
if TYPE_CHECKING:
|
|
13
14
|
from muffin import Request
|
|
14
15
|
|
|
16
|
+
from muffin_rest.types import TFilterOps, TFilterValue
|
|
17
|
+
|
|
15
18
|
from .types import TVCollection
|
|
16
19
|
|
|
17
20
|
FILTERS_PARAM = "where"
|
|
@@ -87,7 +90,7 @@ class Filter(Mutate):
|
|
|
87
90
|
|
|
88
91
|
return ops, collection
|
|
89
92
|
|
|
90
|
-
async def filter(self, collection, *ops:
|
|
93
|
+
async def filter(self, collection, *ops: TFilterValue) -> Any:
|
|
91
94
|
"""Apply the filter to collection."""
|
|
92
95
|
|
|
93
96
|
def validator(obj):
|
|
@@ -95,12 +98,22 @@ class Filter(Mutate):
|
|
|
95
98
|
|
|
96
99
|
return [item for item in collection if validator(item)]
|
|
97
100
|
|
|
98
|
-
def
|
|
101
|
+
def get_simple_value(self, ops: TFilterOps) -> Any:
|
|
102
|
+
"""Get simple value from filter's data.
|
|
103
|
+
|
|
104
|
+
In case of simple filter, return the value.
|
|
105
|
+
"""
|
|
106
|
+
if not ops:
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
return ops[0][1]
|
|
110
|
+
|
|
111
|
+
def parse(self, data: Mapping) -> TFilterOps:
|
|
99
112
|
"""Parse operator and value from filter's data."""
|
|
100
113
|
value = data.get(self.name, ma.missing)
|
|
101
114
|
return tuple(self._parse(value))
|
|
102
115
|
|
|
103
|
-
def _parse(self, value):
|
|
116
|
+
def _parse(self, value) -> Iterable[TFilterValue]:
|
|
104
117
|
deserialize = self.schema_field.deserialize
|
|
105
118
|
if isinstance(value, dict):
|
|
106
119
|
for op, val in value.items():
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"""Support filters for Mongo."""
|
|
2
2
|
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import ClassVar
|
|
4
4
|
|
|
5
5
|
from muffin_rest.filters import Filter, Filters
|
|
6
|
+
from muffin_rest.types import TFilterValue
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class MongoFilter(Filter):
|
|
@@ -21,7 +22,7 @@ class MongoFilter(Filter):
|
|
|
21
22
|
"$ends": lambda _, v: ("$regex", f"{ v }$"),
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
async def filter(self, collection, *ops:
|
|
25
|
+
async def filter(self, collection, *ops: TFilterValue):
|
|
25
26
|
"""Apply the filter."""
|
|
26
27
|
return collection.find({self.field: dict(op(self.name, v) for op, v in ops)})
|
|
27
28
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Support filters for Peewee ORM."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
|
|
4
5
|
import operator
|
|
5
6
|
from functools import reduce
|
|
6
|
-
from typing import
|
|
7
|
+
from typing import TYPE_CHECKING, ClassVar, Union, cast
|
|
7
8
|
|
|
8
9
|
from peewee import ColumnBase, Field, ModelSelect
|
|
9
10
|
|
|
@@ -11,6 +12,9 @@ from muffin_rest.filters import Filter, Filters
|
|
|
11
12
|
|
|
12
13
|
from .utils import get_model_field_by_name
|
|
13
14
|
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from muffin_rest.types import TFilterValue
|
|
17
|
+
|
|
14
18
|
|
|
15
19
|
class PWFilter(Filter):
|
|
16
20
|
"""Support Peewee."""
|
|
@@ -33,9 +37,7 @@ class PWFilter(Filter):
|
|
|
33
37
|
|
|
34
38
|
list_ops = (*Filter.list_ops, "$between")
|
|
35
39
|
|
|
36
|
-
async def filter(
|
|
37
|
-
self, collection: ModelSelect, *ops: tuple[Callable, Any], **kwargs
|
|
38
|
-
) -> ModelSelect:
|
|
40
|
+
async def filter(self, collection: ModelSelect, *ops: TFilterValue) -> ModelSelect:
|
|
39
41
|
"""Apply the filters to Peewee QuerySet.."""
|
|
40
42
|
column = self.field
|
|
41
43
|
if isinstance(column, ColumnBase):
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import TYPE_CHECKING, Any,
|
|
5
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Union, cast
|
|
6
6
|
|
|
7
7
|
from sqlalchemy import Column
|
|
8
8
|
|
|
9
9
|
from muffin_rest.filters import Filter, Filters
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
|
+
from muffin_rest.types import TFilterValue
|
|
13
|
+
|
|
12
14
|
from .types import TVCollection
|
|
13
15
|
|
|
14
16
|
|
|
@@ -29,17 +31,15 @@ class SAFilter(Filter):
|
|
|
29
31
|
|
|
30
32
|
list_ops = (*Filter.list_ops, "$between")
|
|
31
33
|
|
|
32
|
-
async def filter(
|
|
33
|
-
self, collection: TVCollection, *ops: tuple[Callable, Any], **kwargs
|
|
34
|
-
) -> TVCollection:
|
|
34
|
+
async def filter(self, collection: TVCollection, *ops: TFilterValue) -> TVCollection:
|
|
35
35
|
"""Apply the filters to SQLAlchemy Select."""
|
|
36
36
|
column = self.field
|
|
37
37
|
if ops and column is not None:
|
|
38
|
-
return self.query(collection, column, *ops
|
|
38
|
+
return self.query(collection, column, *ops)
|
|
39
39
|
|
|
40
40
|
return collection
|
|
41
41
|
|
|
42
|
-
def query(self, select: TVCollection, column: Column, *ops
|
|
42
|
+
def query(self, select: TVCollection, column: Column, *ops: TFilterValue) -> TVCollection:
|
|
43
43
|
"""Filter a select."""
|
|
44
44
|
return select.where(*[op(column, val) for op, val in ops])
|
|
45
45
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|