muffin-rest 11.0.1__py3-none-any.whl → 12.0.1__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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Union, cast
5
+ from typing import TYPE_CHECKING, cast
6
6
 
7
7
  from peewee import Field
8
8
 
@@ -11,6 +11,7 @@ from muffin_rest.sorting import Sort, Sorting
11
11
  from .utils import get_model_field_by_name
12
12
 
13
13
  if TYPE_CHECKING:
14
+ from . import PWRESTHandler
14
15
  from .types import TVCollection
15
16
 
16
17
 
@@ -34,14 +35,13 @@ class PWSorting(Sorting):
34
35
  """Prepare collection for sorting."""
35
36
  return collection.order_by()
36
37
 
37
- def convert(self, obj: Union[str, Field, PWSort], **meta):
38
+ def convert(self, obj: str | Field | PWSort, **meta):
38
39
  """Prepare sorters."""
39
- from . import PWRESTHandler
40
40
 
41
41
  if isinstance(obj, PWSort):
42
42
  return obj
43
43
 
44
- handler = cast(PWRESTHandler, self.handler)
44
+ handler = cast("PWRESTHandler", self.handler)
45
45
 
46
46
  if isinstance(obj, Field):
47
47
  name, field = obj.name, obj
@@ -2,14 +2,14 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Optional
5
+ from typing import TYPE_CHECKING
6
6
  from warnings import warn
7
7
 
8
8
  if TYPE_CHECKING:
9
9
  from peewee import Field
10
10
 
11
11
 
12
- def get_model_field_by_name(handler, name: str, *, stacklevel=5) -> Optional[Field]:
12
+ def get_model_field_by_name(handler, name: str, *, stacklevel=5) -> Field | None:
13
13
  """Get model field by name."""
14
14
  fields = handler.meta.model._meta.fields
15
15
  candidate = fields.get(name)
muffin_rest/sorting.py CHANGED
@@ -1,15 +1,16 @@
1
1
  """Implement sorting."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import TYPE_CHECKING, Any, Generator, Iterable, Mapping, Sequence, cast
5
6
 
6
- from .types import TVCollection
7
7
  from .utils import Mutate, Mutator
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from muffin import Request
11
11
 
12
12
  from .handler import RESTBase
13
+ from .types import TVCollection
13
14
 
14
15
  SORT_PARAM = "sort"
15
16
 
@@ -60,14 +61,14 @@ class Sorting(Mutator):
60
61
 
61
62
  def convert(self, obj, **meta) -> Sort:
62
63
  """Prepare sorters."""
63
- sort = cast(Sort, super(Sorting, self).convert(obj, **meta))
64
+ sort = cast("Sort", super(Sorting, self).convert(obj, **meta))
64
65
  if sort.meta.get("default"):
65
66
  self.default.append(sort)
66
67
  return sort
67
68
 
68
69
  def sort_default(self, collection: TVCollection) -> TVCollection:
69
70
  """Sort by default."""
70
- return cast(TVCollection, sorted(collection))
71
+ return cast("TVCollection", sorted(collection))
71
72
 
72
73
  @property
73
74
  def openapi(self):
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, Optional, cast
5
+ from typing import TYPE_CHECKING, Any, cast
6
6
 
7
7
  import marshmallow as ma
8
8
  import sqlalchemy as sa
@@ -18,11 +18,10 @@ if TYPE_CHECKING:
18
18
  from muffin import Request
19
19
  from muffin_databases import Plugin as Database
20
20
 
21
- from muffin_rest.types import TVData
22
21
 
23
22
  from .types import TVResource
24
23
 
25
- ModelConverter._get_field_name = lambda _, prop_or_column: str(prop_or_column.key) # type: ignore[method-assign]
24
+ ModelConverter._get_field_name = lambda _, prop_or_column: str(prop_or_column.key) # type: ignore[assignment]
26
25
 
27
26
 
28
27
  class SQLAlchemyAutoSchema(BaseSQLAlchemyAutoSchema):
@@ -101,7 +100,7 @@ class SARESTOptions(RESTOptions):
101
100
  "unknown": self.schema_unknown,
102
101
  "table": self.table,
103
102
  "include_fk": True,
104
- "dump_only": (self.name_id,),
103
+ "dump_only": (self.pk,),
105
104
  },
106
105
  **self.schema_meta,
107
106
  ),
@@ -125,7 +124,7 @@ class SARESTHandler(RESTHandler[TVResource]):
125
124
  *,
126
125
  limit: int = 0,
127
126
  offset: int = 0,
128
- ) -> tuple[sa.sql.Select, Optional[int]]:
127
+ ) -> tuple[sa.sql.Select, int | None]:
129
128
  """Paginate the collection."""
130
129
  sqs = self.collection.order_by(None).subquery()
131
130
  qs = sa.select(sa.func.count()).select_from(sqs)
@@ -134,7 +133,7 @@ class SARESTHandler(RESTHandler[TVResource]):
134
133
  total = await self.meta.database.fetch_val(qs)
135
134
  return self.collection.offset(offset).limit(limit), total
136
135
 
137
- async def get(self, request, *, resource: Optional[TVResource] = None) -> Any:
136
+ async def get(self, request, *, resource: TVResource | None = None) -> Any:
138
137
  """Get resource or collection of resources."""
139
138
  if resource:
140
139
  return await self.dump(request, resource)
@@ -142,9 +141,9 @@ class SARESTHandler(RESTHandler[TVResource]):
142
141
  rows = await self.meta.database.fetch_all(self.collection)
143
142
  return await self.dump(request, rows, many=True)
144
143
 
145
- async def prepare_resource(self, request: Request) -> Optional[TVResource]:
144
+ async def prepare_resource(self, request: Request) -> TVResource | None:
146
145
  """Load a resource."""
147
- pk = request["path_params"].get(self.meta.name_id)
146
+ pk = request["path_params"].get("pk")
148
147
  if not pk:
149
148
  return None
150
149
 
@@ -152,19 +151,19 @@ class SARESTHandler(RESTHandler[TVResource]):
152
151
  resource = await self.meta.database.fetch_one(qs)
153
152
  if resource is None:
154
153
  raise APIError.NOT_FOUND("Resource not found")
155
- return cast(TVResource, dict(resource))
154
+ return cast("TVResource", dict(resource))
156
155
 
157
156
  def get_schema(
158
- self, request: Request, *, resource: Optional[TVResource] = None, **schema_options
157
+ self, request: Request, *, resource: TVResource | None = None, **schema_options
159
158
  ) -> ma.Schema:
160
159
  """Initialize marshmallow schema for serialization/deserialization."""
161
160
  return super().get_schema(request, instance=resource, **schema_options)
162
161
 
163
- async def save(self, _: Request, resource: TVData[TVResource], *, update=False):
162
+ async def save(self, request: Request, resource: TVResource, *, update=False):
164
163
  """Save the given resource."""
165
164
  meta = self.meta
166
165
  insert_query = meta.table.insert()
167
- table_pk = cast(sa.Column, meta.table_pk)
166
+ table_pk = cast("sa.Column", meta.table_pk)
168
167
  if update:
169
168
  update_query = self.meta.table.update().where(table_pk == resource[table_pk.name]) # type: ignore[call-overload]
170
169
  await meta.database.execute(update_query, resource)
@@ -174,14 +173,14 @@ class SARESTHandler(RESTHandler[TVResource]):
174
173
 
175
174
  return resource
176
175
 
177
- async def remove(self, request: Request, resource: Optional[TVResource] = None):
176
+ async def remove(self, request: Request, resource: TVResource | None = None):
178
177
  """Remove the given resource."""
179
- table_pk = cast(sa.Column, self.meta.table_pk)
178
+ table_pk = cast("sa.Column", self.meta.table_pk)
180
179
  pks = [resource[table_pk.name]] if resource else await request.data()
181
180
  if not pks:
182
181
  raise APIError.NOT_FOUND()
183
182
 
184
- delete = self.meta.table.delete().where(table_pk.in_(cast(list[Any], pks)))
183
+ delete = self.meta.table.delete().where(table_pk.in_(cast("list[Any]", pks)))
185
184
  await self.meta.database.execute(delete)
186
185
 
187
186
  delete = remove
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, ClassVar, Union, cast
5
+ from typing import TYPE_CHECKING, Any, ClassVar, cast
6
6
 
7
7
  from sqlalchemy import Column
8
8
 
@@ -11,6 +11,7 @@ from muffin_rest.filters import Filter, Filters
11
11
  if TYPE_CHECKING:
12
12
  from muffin_rest.types import TFilterValue
13
13
 
14
+ from . import SARESTHandler
14
15
  from .types import TVCollection
15
16
 
16
17
 
@@ -49,11 +50,10 @@ class SAFilters(Filters):
49
50
 
50
51
  MUTATE_CLASS = SAFilter
51
52
 
52
- def convert(self, obj: Union[str, Column, SAFilter], **meta):
53
+ def convert(self, obj: str | Column | SAFilter, **meta):
53
54
  """Convert params to filters."""
54
- from . import SARESTHandler
55
55
 
56
- handler = cast(SARESTHandler, self.handler)
56
+ handler = cast("SARESTHandler", self.handler)
57
57
 
58
58
  if isinstance(obj, SAFilter):
59
59
  if obj.field is None:
@@ -1,13 +1,15 @@
1
1
  """Support sorting for SQLAlchemy ORM."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
- from typing import TYPE_CHECKING, Union, cast
5
+ from typing import TYPE_CHECKING, cast
5
6
 
6
7
  from sqlalchemy import Column
7
8
 
8
9
  from muffin_rest.sorting import Sort, Sorting
9
10
 
10
11
  if TYPE_CHECKING:
12
+ from . import SARESTHandler
11
13
  from .types import TVCollection
12
14
 
13
15
 
@@ -15,7 +17,11 @@ class SASort(Sort):
15
17
  """Sorter for Peewee."""
16
18
 
17
19
  async def apply(
18
- self, collection: TVCollection, *, desc: bool = False, **_,
20
+ self,
21
+ collection: TVCollection,
22
+ *,
23
+ desc: bool = False,
24
+ **_,
19
25
  ) -> TVCollection:
20
26
  """Sort the collection."""
21
27
  field = self.field
@@ -30,21 +36,20 @@ class SASorting(Sorting):
30
36
 
31
37
  MUTATE_CLASS = SASort
32
38
 
33
- def convert(self, obj: Union[str, Column, SASort], **meta):
39
+ def convert(self, obj: str | Column | SASort, **meta):
34
40
  """Prepare sorters."""
35
- from . import SARESTHandler
36
41
 
37
42
  if isinstance(obj, SASort):
38
43
  return obj
39
44
 
40
- handler = cast(SARESTHandler, self.handler)
45
+ handler = cast("SARESTHandler", self.handler)
41
46
 
42
47
  if isinstance(obj, Column):
43
48
  name, field = obj.name, obj
44
49
 
45
50
  else:
46
51
  name = obj
47
- field = meta.get("field", handler.meta.table.c.get(name))
52
+ field = meta.get("field", handler.meta.table.c.get(name)) # type: ignore[assignment]
48
53
 
49
54
  if field is not None:
50
55
  sort = self.MUTATE_CLASS(name, field=field, **meta)
muffin_rest/types.py CHANGED
@@ -4,7 +4,6 @@ from typing import (
4
4
  Awaitable,
5
5
  Callable,
6
6
  TypeVar,
7
- Union,
8
7
  )
9
8
 
10
9
  if TYPE_CHECKING:
@@ -14,7 +13,6 @@ from muffin import Request
14
13
 
15
14
  TVCollection = TypeVar("TVCollection", bound=Any)
16
15
  TVResource = TypeVar("TVResource", bound=Any)
17
- TVData = Union[TVResource, list[TVResource]]
18
16
  TAuth = Callable[[Request], Awaitable]
19
17
  TVAuth = TypeVar("TVAuth", bound=TAuth)
20
18
  TVHandler = TypeVar("TVHandler", bound=type["RESTBase"])
@@ -0,0 +1,176 @@
1
+ Metadata-Version: 2.3
2
+ Name: muffin-rest
3
+ Version: 12.0.1
4
+ Summary: The package provides enhanced support for writing REST APIs with Muffin framework
5
+ License: MIT
6
+ Keywords: rest,api,muffin,asgi,asyncio,trio
7
+ Author: Kirill Klenov
8
+ Author-email: horneds@gmail.com
9
+ Requires-Python: >=3.10,<4.0
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Framework :: AsyncIO
12
+ Classifier: Framework :: Trio
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Internet :: WWW/HTTP
22
+ Provides-Extra: peewee
23
+ Provides-Extra: sqlalchemy
24
+ Provides-Extra: yaml
25
+ Requires-Dist: apispec (>=6,<7)
26
+ Requires-Dist: marshmallow (>=3,<4)
27
+ Requires-Dist: marshmallow-peewee ; extra == "peewee"
28
+ Requires-Dist: marshmallow-sqlalchemy ; extra == "sqlalchemy"
29
+ Requires-Dist: muffin
30
+ Requires-Dist: muffin-databases ; extra == "sqlalchemy"
31
+ Requires-Dist: muffin-peewee-aio ; extra == "peewee"
32
+ Requires-Dist: pyyaml ; extra == "yaml"
33
+ Requires-Dist: sqlalchemy ; extra == "sqlalchemy"
34
+ Project-URL: Homepage, https://github.com/klen/muffin-rest
35
+ Project-URL: Repository, https://github.com/klen/muffin-rest
36
+ Description-Content-Type: text/markdown
37
+
38
+ # Muffin‑REST
39
+
40
+ **Muffin‑REST** simplifies building RESTful APIs with [Muffin](https://github.com/klen/muffin) by offering:
41
+
42
+ - Declarative `API` class with resource registration
43
+ - Built-in filtering, sorting, pagination, and search
44
+ - Support for:
45
+ - [Peewee ORM](http://docs.peewee-orm.com/en/latest/) via `PeeweeEndpoint`
46
+ - [SQLAlchemy Core](https://docs.sqlalchemy.org/en/14/core/) via `SAEndpoint`
47
+ - [MongoDB](https://www.mongodb.com/) via `MongoEndpoint`
48
+ - [Swagger/OpenAPI](https://swagger.io/) autodocumentation
49
+ - Works with asyncio, Trio, and Curio
50
+
51
+ [![Tests Status](https://github.com/klen/muffin-rest/workflows/tests/badge.svg)](https://github.com/klen/muffin-rest/actions)
52
+ [![PyPI Version](https://img.shields.io/pypi/v/muffin-rest)](https://pypi.org/project/muffin-rest/)
53
+ [![Python Versions](https://img.shields.io/pypi/pyversions/muffin-rest)](https://pypi.org/project/muffin-rest/)
54
+
55
+ ## Requirements
56
+
57
+ - Python >= 3.10
58
+ - Trio requires Peewee backend
59
+
60
+ ## Installation
61
+
62
+ Install core package:
63
+
64
+ ```bash
65
+ pip install muffin-rest
66
+ ```
67
+
68
+ Add optional backend support:
69
+
70
+ - SQLAlchemy Core: `pip install muffin-rest[sqlalchemy]`
71
+ - Peewee ORM: `pip install muffin-rest[peewee]`
72
+ - YAML support for Swagger: `pip install muffin-rest[yaml]`
73
+
74
+ ## Quickstart (Peewee example)
75
+
76
+ ```python
77
+ from muffin import Application
78
+ from muffin_rest import API
79
+ from muffin_rest.peewee import PeeweeEndpoint
80
+ from models import User # your Peewee model
81
+
82
+ app = Application("myapp")
83
+ api = API(title="User Service", version="1.0")
84
+
85
+ @api.route
86
+ class UsersEndpoint(PeeweeEndpoint):
87
+ class Meta:
88
+ model = User
89
+ lookup_field = "id"
90
+ filters = ["name", "email"]
91
+ ordering = ["-created_at"]
92
+
93
+ api.setup(app, prefix="/api", swagger=True)
94
+ ```
95
+
96
+ Endpoints available:
97
+
98
+ - `GET /api/users/` — list with pagination, search, filtering
99
+ - `POST /api/users/` — create
100
+ - `GET /api/users/{id}/` — retrieve
101
+ - `PUT /api/users/{id}/` — replace
102
+ - `PATCH /api/users/{id}/` — update
103
+ - `DELETE /api/users/{id}/` — remove
104
+ - Docs: `/api/docs/`, OpenAPI spec: `/api/openapi.json`
105
+
106
+ ## Usage with SQLAlchemy
107
+
108
+ ```python
109
+ from muffin_rest import API
110
+ from muffin_rest.sqlalchemy import SAEndpoint
111
+ from models import my_table, db_engine
112
+
113
+ api = API()
114
+ @api.route
115
+ class MySAEndpoint(SAEndpoint):
116
+ class Meta:
117
+ table = my_table
118
+ database = db_engine
119
+
120
+ api.setup(app)
121
+ ```
122
+
123
+ ## Usage with MongoDB
124
+
125
+ ```python
126
+ from muffin_rest import API
127
+ from muffin_rest.mongo import MongoEndpoint
128
+ from models import mongo_collection
129
+
130
+ api = API()
131
+ @api.route
132
+ class MyMongoEndpoint(MongoEndpoint):
133
+ class Meta:
134
+ collection = mongo_collection
135
+
136
+ api.setup(app)
137
+ ```
138
+
139
+ ## Advanced Configuration
140
+
141
+ Customize Swagger and routes via constructor:
142
+
143
+ ```python
144
+ api = API(
145
+ title="Service API",
146
+ version="2.1",
147
+ swagger_ui=True,
148
+ openapi_path="/api/openapi.json",
149
+ docs_path="/api/docs/"
150
+ )
151
+ ```
152
+
153
+ ## Contributing & Examples
154
+
155
+ - See `examples/` for live application demos
156
+ - Tests in `tests/` focus on filtering, pagination, status codes
157
+ - Check `CHANGELOG.md` for latest changes
158
+
159
+ ## Bug Tracker
160
+
161
+ Report bugs or request features:
162
+ https://github.com/klen/muffin-rest/issues
163
+
164
+ ## Contributing
165
+
166
+ Repo: https://github.com/klen/muffin-rest
167
+ Pull requests, example additions, docs improvements welcome!
168
+
169
+ ## Contributors
170
+
171
+ - [klen](https://github.com/klen) (Kirill Klenov)
172
+
173
+ ## License
174
+
175
+ Licensed under the [MIT license](http://opensource.org/licenses/MIT).
176
+
@@ -0,0 +1,39 @@
1
+ muffin_rest/__init__.py,sha256=JnwsHQNDmJpOqETeIjjPheG891T5WQ0JBaiEV72Wcmg,1242
2
+ muffin_rest/api.py,sha256=bdbXMPiZi5yXf7_u3XB_gaGDHZKzDPqnnFnrwHoO1Rs,3799
3
+ muffin_rest/errors.py,sha256=Todg7CrCE1ufOsyyARI2Bv-RqNPH4Rl1p-Tkpq7VYrA,1151
4
+ muffin_rest/filters.py,sha256=nWlwDLuId-mmP3tgZjp1joYCVx0k9ekV42fPIMMKphM,5920
5
+ muffin_rest/handler.py,sha256=qpG4ioIagdYqGFOrlT7pBx-0czgS2ZI3AvqKXz9EzcA,10762
6
+ muffin_rest/limits.py,sha256=Fnlu4Wj3B-BzpahLK-rDbd1GEd7CEQ3zxyOD0vee7GE,2007
7
+ muffin_rest/marshmallow.py,sha256=-MyMKiaMTfiWw4y-4adpfoQd05HV1vEKqSXJh8eD3xg,548
8
+ muffin_rest/mongo/__init__.py,sha256=oPfTF_cG4LD1TDm-RoyxhSS1pVDXConCKQf9rz2QlZM,4644
9
+ muffin_rest/mongo/filters.py,sha256=yIxIDVqMn6SoDgVhCqiTxYetw0hoaf_3jIvX2Vnizok,964
10
+ muffin_rest/mongo/schema.py,sha256=y4OEPQnlV_COTIIQ3cKmpqDpD2r18eAWn0rijQldWm0,1205
11
+ muffin_rest/mongo/sorting.py,sha256=iJBnaFwE7g_JMwpGpQkoqSqbQK9XULx1K3skiRRgLgY,870
12
+ muffin_rest/mongo/types.py,sha256=jaODScgwwYbzHis3DY4bPzU1ahiMJMSwquH5_Thi-Gg,200
13
+ muffin_rest/mongo/utils.py,sha256=jirD2Hxk28Wadpq_F08t40dYBygq6W1_0cD3261kCgo,3949
14
+ muffin_rest/openapi.py,sha256=VrkyZr_T0ykAQsvkFQ_yarZ-Zs55AmAGf4aNLsUdjGA,8715
15
+ muffin_rest/options.py,sha256=VO1d7nzKSxPw9QidNiyNSfMDX46ZCK0a-iFbJyzNXEE,2227
16
+ muffin_rest/peewee/__init__.py,sha256=94DSj_ftT6fbPksHlBv40AH2HWaiZommUFOMN2jd9a4,129
17
+ muffin_rest/peewee/filters.py,sha256=8CqleDEn4vVQvBLXEaGOjM2N7sY117EQ4GThPhlDPE8,2494
18
+ muffin_rest/peewee/handler.py,sha256=qu-ma1zhMGvzVbqpBEdSkify2UbffT58SLjWUoT_1ws,5418
19
+ muffin_rest/peewee/openapi.py,sha256=ktgsmB9wFNvcTbTaDkMQFLdQxk3osDFW5LkUSFVjcQo,1093
20
+ muffin_rest/peewee/options.py,sha256=TimJtErC9e8B7BRiEkHiBZd71_bZbYr-FE2PIlQvfH0,1455
21
+ muffin_rest/peewee/schemas.py,sha256=hQG2UKR7gEMsz0n75L3tvkVzUX3baXMJ94emgIc1Scw,439
22
+ muffin_rest/peewee/sorting.py,sha256=aBtQkj3iSo6XjBZ8evJuprIkhv1nHFi7wFb0an6Dn34,1963
23
+ muffin_rest/peewee/types.py,sha256=cgCXhpGHkImKwudA1lulZHz5oJswHH168AiW5MhZRCM,155
24
+ muffin_rest/peewee/utils.py,sha256=8wTSKmjeD3qtF5NFHX1wkBn4jiXFvCzNEK9WW7r_JmI,693
25
+ muffin_rest/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
+ muffin_rest/redoc.html,sha256=GtuHIMvTuSi8Ro6bgI-G8VB94AljMyfjcZseqtBmGCY,559
27
+ muffin_rest/schemas.py,sha256=BW3dF82C6Q6STs4tZjej1x8Ii1rI3EZUJZR4mNNKmu4,875
28
+ muffin_rest/sorting.py,sha256=nu4SGW5uxLETJIywE-1UTCCya9QAvYWcq-P8dPWQixI,2822
29
+ muffin_rest/sqlalchemy/__init__.py,sha256=pZt_3t8I4uU8WssrksdEn8LXS0ytKT4NHioTpFqKDiw,6312
30
+ muffin_rest/sqlalchemy/filters.py,sha256=Lf1nPOQjDT7Nv1HAwowfWYTHWCrIMpw-4aWwoaNVlVU,2475
31
+ muffin_rest/sqlalchemy/sorting.py,sha256=qmzP18ongriCGs2Ok_OllEybqWgppU-Kakg0JL1DM_M,1690
32
+ muffin_rest/sqlalchemy/types.py,sha256=Exm-zAQCtPAwXvYcCTtPRqSa-wTEWRcH_v2YSsJkB6s,198
33
+ muffin_rest/swagger.html,sha256=2uGLu_KpkYf925KnDKHBJmV9pm6OHn5C3BWScESsUS8,1736
34
+ muffin_rest/types.py,sha256=5NY9gPTIptv6U2Qab2xMXlS_jZuTuR0bquFFwWRURcA,510
35
+ muffin_rest/utils.py,sha256=c08E4HJ4SLYC-91GKPEbsyKTZ4sZbTN4qDqJbNg_HTE,2076
36
+ muffin_rest-12.0.1.dist-info/LICENSE,sha256=xHPkOZhjyKBMOwXpWn9IB_BVLjrrMxv2M9slKkHj2hM,1082
37
+ muffin_rest-12.0.1.dist-info/METADATA,sha256=dXgMCxDzBPevm7z9iHGm7okdhQCIRX-R8RGCHUwdjWo,4912
38
+ muffin_rest-12.0.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
39
+ muffin_rest-12.0.1.dist-info/RECORD,,
@@ -1,182 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: muffin-rest
3
- Version: 11.0.1
4
- Summary: The package provides enhanced support for writing REST APIs with Muffin framework
5
- License: MIT
6
- Keywords: rest,api,muffin,asgi,asyncio,trio
7
- Author: Kirill Klenov
8
- Author-email: horneds@gmail.com
9
- Requires-Python: >=3.9,<4.0
10
- Classifier: Development Status :: 5 - Production/Stable
11
- Classifier: Framework :: AsyncIO
12
- Classifier: Framework :: Trio
13
- Classifier: Intended Audience :: Developers
14
- Classifier: License :: OSI Approved :: MIT License
15
- Classifier: Programming Language :: Python
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.9
18
- Classifier: Programming Language :: Python :: 3.10
19
- Classifier: Programming Language :: Python :: 3.11
20
- Classifier: Programming Language :: Python :: 3.12
21
- Classifier: Programming Language :: Python :: 3.13
22
- Classifier: Topic :: Internet :: WWW/HTTP
23
- Provides-Extra: peewee
24
- Provides-Extra: sqlalchemy
25
- Provides-Extra: yaml
26
- Requires-Dist: apispec (>=6,<7)
27
- Requires-Dist: marshmallow (>=3,<4)
28
- Requires-Dist: marshmallow-peewee ; extra == "peewee"
29
- Requires-Dist: marshmallow-sqlalchemy ; extra == "sqlalchemy"
30
- Requires-Dist: muffin (>=0,<1)
31
- Requires-Dist: muffin-databases ; extra == "sqlalchemy"
32
- Requires-Dist: muffin-peewee-aio ; extra == "peewee"
33
- Requires-Dist: pyyaml ; extra == "yaml"
34
- Requires-Dist: sqlalchemy ; extra == "sqlalchemy"
35
- Project-URL: Homepage, https://github.com/klen/muffin-rest
36
- Project-URL: Repository, https://github.com/klen/muffin-rest
37
- Description-Content-Type: text/x-rst
38
-
39
- Muffin-REST
40
- ###########
41
-
42
- .. _description:
43
-
44
- **Muffin-REST** -- provides enhanced support for writing REST APIs with Muffin_.
45
-
46
-
47
- .. _badges:
48
-
49
- .. image:: https://github.com/klen/muffin-rest/workflows/tests/badge.svg
50
- :target: https://github.com/klen/muffin-rest/actions
51
- :alt: Tests Status
52
-
53
- .. image:: https://img.shields.io/pypi/v/muffin-rest
54
- :target: https://pypi.org/project/muffin-rest/
55
- :alt: PYPI Version
56
-
57
- .. image:: https://img.shields.io/pypi/pyversions/muffin-rest
58
- :target: https://pypi.org/project/muffin-rest/
59
- :alt: Python Versions
60
-
61
- ----------
62
-
63
- .. _features:
64
-
65
- Features
66
- --------
67
-
68
- - API class to simplify the creation of REST APIs;
69
- - Automatic filtering and sorting for resources;
70
- - Support for `Peewee ORM`_, Mongo_, `SQLAlchemy Core`_;
71
- - Auto documentation with Swagger_;
72
-
73
- .. _contents:
74
-
75
- .. contents::
76
-
77
- .. _requirements:
78
-
79
- Requirements
80
- =============
81
-
82
- - python >= 3.9
83
-
84
- .. note:: Trio is only supported with Peewee ORM
85
-
86
- .. _installation:
87
-
88
- Installation
89
- =============
90
-
91
- **Muffin-REST** should be installed using pip: ::
92
-
93
- pip install muffin-rest
94
-
95
- With `SQLAlchemy Core`_ support: ::
96
-
97
- pip install muffin-rest[sqlalchemy]
98
-
99
- With `Peewee ORM`_ support: ::
100
-
101
- pip install muffin-rest[peewee]
102
-
103
- With YAML support for autodocumentation: ::
104
-
105
- pip install muffin-rest[yaml]
106
-
107
- .. _usage:
108
-
109
- Usage
110
- =====
111
-
112
- Create an API:
113
-
114
- .. code-block:: python
115
-
116
- from muffin_rest import API
117
-
118
- api = API()
119
-
120
- Create endpoints and connect them to the API (example for sqlalchemy):
121
-
122
- .. code-block:: python
123
-
124
- from muffin_rest.sqlalchemy import SAEndpoint
125
- from project.api import api
126
-
127
- @api.route
128
- class MyEndpoint(SAEndpoint):
129
-
130
- class Meta:
131
- table = MyTable
132
- database = db
133
-
134
- Connect it to your Muffin_ application:
135
-
136
- .. code-block:: python
137
-
138
- from project.api import api
139
-
140
- api.setup(app, prefix='/api/v1')
141
-
142
-
143
- .. _bugtracker:
144
-
145
- Bug tracker
146
- ===========
147
-
148
- If you have any suggestions, bug reports or
149
- annoyances please report them to the issue tracker
150
- at https://github.com/klen/muffin-rest/issues
151
-
152
- .. _contributing:
153
-
154
- Contributing
155
- ============
156
-
157
- Development of Muffin-REST happens at: https://github.com/klen/muffin-rest
158
-
159
-
160
- Contributors
161
- =============
162
-
163
- * klen_ (Kirill Klenov)
164
-
165
- .. _license:
166
-
167
- License
168
- ========
169
-
170
- Licensed under a `MIT license`_.
171
-
172
- .. _links:
173
-
174
- .. _klen: https://github.com/klen
175
- .. _Muffin: https://github.com/klen/muffin
176
- .. _Swagger: https://swagger.io/tools/swagger-ui/
177
- .. _Mongo: https://www.mongodb.com/
178
- .. _Peewee ORM: http://docs.peewee-orm.com/en/latest/
179
- .. _SqlAlchemy Core: https://docs.sqlalchemy.org/en/14/core/
180
-
181
- .. _MIT license: http://opensource.org/licenses/MIT
182
-