vega-framework 0.1.35__py3-none-any.whl → 0.2.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.
- vega/cli/commands/add.py +9 -10
- vega/cli/commands/generate.py +15 -15
- vega/cli/commands/init.py +9 -8
- vega/cli/commands/web.py +8 -7
- vega/cli/main.py +4 -4
- vega/cli/scaffolds/__init__.py +6 -2
- vega/cli/scaffolds/vega_web.py +109 -0
- vega/cli/templates/__init__.py +34 -8
- vega/cli/templates/components.py +29 -13
- vega/cli/templates/project/ARCHITECTURE.md.j2 +13 -13
- vega/cli/templates/project/README.md.j2 +5 -5
- vega/cli/templates/web/app.py.j2 +5 -5
- vega/cli/templates/web/health_route.py.j2 +2 -2
- vega/cli/templates/web/main.py.j2 +2 -3
- vega/cli/templates/web/middleware.py.j2 +3 -3
- vega/cli/templates/web/router.py.j2 +2 -2
- vega/cli/templates/web/routes_init.py.j2 +3 -3
- vega/cli/templates/web/routes_init_autodiscovery.py.j2 +2 -2
- vega/cli/templates/web/users_route.py.j2 +2 -2
- vega/discovery/routes.py +13 -13
- vega/web/__init__.py +100 -0
- vega/web/application.py +234 -0
- vega/web/builtin_middlewares.py +288 -0
- vega/web/exceptions.py +151 -0
- vega/web/middleware.py +185 -0
- vega/web/request.py +120 -0
- vega/web/response.py +220 -0
- vega/web/route_middleware.py +266 -0
- vega/web/router.py +350 -0
- vega/web/routing.py +347 -0
- {vega_framework-0.1.35.dist-info → vega_framework-0.2.1.dist-info}/METADATA +10 -9
- {vega_framework-0.1.35.dist-info → vega_framework-0.2.1.dist-info}/RECORD +35 -24
- {vega_framework-0.1.35.dist-info → vega_framework-0.2.1.dist-info}/WHEEL +0 -0
- {vega_framework-0.1.35.dist-info → vega_framework-0.2.1.dist-info}/entry_points.txt +0 -0
- {vega_framework-0.1.35.dist-info → vega_framework-0.2.1.dist-info}/licenses/LICENSE +0 -0
vega/web/router.py
ADDED
@@ -0,0 +1,350 @@
|
|
1
|
+
"""Router class for Vega Web Framework"""
|
2
|
+
|
3
|
+
from typing import Any, Callable, List, Optional, Sequence, Type
|
4
|
+
|
5
|
+
from starlette.routing import Mount
|
6
|
+
|
7
|
+
from .routing import Route, route as create_route
|
8
|
+
|
9
|
+
|
10
|
+
class Router:
|
11
|
+
"""
|
12
|
+
HTTP Router for organizing endpoints.
|
13
|
+
|
14
|
+
Similar to FastAPI's APIRouter, this class allows you to group related
|
15
|
+
endpoints together with common configuration like prefix, tags, etc.
|
16
|
+
|
17
|
+
Args:
|
18
|
+
prefix: URL prefix for all routes (e.g., "/api/v1")
|
19
|
+
tags: Default tags for all routes
|
20
|
+
dependencies: Shared dependencies (future feature)
|
21
|
+
responses: Common response models (future feature)
|
22
|
+
|
23
|
+
Example:
|
24
|
+
router = Router(prefix="/users", tags=["users"])
|
25
|
+
|
26
|
+
@router.get("/{user_id}")
|
27
|
+
async def get_user(user_id: str):
|
28
|
+
return {"id": user_id, "name": "John"}
|
29
|
+
|
30
|
+
@router.post("")
|
31
|
+
async def create_user(request: Request):
|
32
|
+
data = await request.json()
|
33
|
+
return {"id": "new_id", **data}
|
34
|
+
"""
|
35
|
+
|
36
|
+
def __init__(
|
37
|
+
self,
|
38
|
+
prefix: str = "",
|
39
|
+
tags: Optional[List[str]] = None,
|
40
|
+
dependencies: Optional[Sequence[Any]] = None,
|
41
|
+
responses: Optional[dict] = None,
|
42
|
+
):
|
43
|
+
self.prefix = prefix
|
44
|
+
self.tags = tags or []
|
45
|
+
self.dependencies = dependencies or []
|
46
|
+
self.responses = responses or {}
|
47
|
+
self.routes: List[Route] = []
|
48
|
+
self.child_routers: List[tuple[Router, str, Optional[List[str]]]] = []
|
49
|
+
|
50
|
+
def add_route(
|
51
|
+
self,
|
52
|
+
path: str,
|
53
|
+
endpoint: Callable,
|
54
|
+
methods: List[str],
|
55
|
+
*,
|
56
|
+
name: Optional[str] = None,
|
57
|
+
include_in_schema: bool = True,
|
58
|
+
tags: Optional[List[str]] = None,
|
59
|
+
summary: Optional[str] = None,
|
60
|
+
description: Optional[str] = None,
|
61
|
+
response_model: Optional[Type] = None,
|
62
|
+
status_code: int = 200,
|
63
|
+
) -> None:
|
64
|
+
"""
|
65
|
+
Add a route to the router.
|
66
|
+
|
67
|
+
Args:
|
68
|
+
path: URL path pattern
|
69
|
+
endpoint: Handler function
|
70
|
+
methods: HTTP methods
|
71
|
+
name: Optional route name
|
72
|
+
include_in_schema: Include in API docs
|
73
|
+
tags: Route tags
|
74
|
+
summary: Short description
|
75
|
+
description: Longer description
|
76
|
+
response_model: Expected response type
|
77
|
+
status_code: Default status code
|
78
|
+
"""
|
79
|
+
# Merge router tags with route-specific tags
|
80
|
+
route_tags = (tags or []) + self.tags
|
81
|
+
|
82
|
+
route_obj = Route(
|
83
|
+
path=path,
|
84
|
+
endpoint=endpoint,
|
85
|
+
methods=methods,
|
86
|
+
name=name,
|
87
|
+
include_in_schema=include_in_schema,
|
88
|
+
tags=route_tags,
|
89
|
+
summary=summary,
|
90
|
+
description=description,
|
91
|
+
response_model=response_model,
|
92
|
+
status_code=status_code,
|
93
|
+
)
|
94
|
+
self.routes.append(route_obj)
|
95
|
+
|
96
|
+
def route(
|
97
|
+
self,
|
98
|
+
path: str,
|
99
|
+
methods: List[str],
|
100
|
+
*,
|
101
|
+
name: Optional[str] = None,
|
102
|
+
include_in_schema: bool = True,
|
103
|
+
tags: Optional[List[str]] = None,
|
104
|
+
summary: Optional[str] = None,
|
105
|
+
description: Optional[str] = None,
|
106
|
+
response_model: Optional[Type] = None,
|
107
|
+
status_code: int = 200,
|
108
|
+
) -> Callable:
|
109
|
+
"""
|
110
|
+
Decorator to add a route.
|
111
|
+
|
112
|
+
Example:
|
113
|
+
@router.route("/items", methods=["GET", "POST"])
|
114
|
+
async def items():
|
115
|
+
return {"items": []}
|
116
|
+
"""
|
117
|
+
|
118
|
+
def decorator(func: Callable) -> Callable:
|
119
|
+
self.add_route(
|
120
|
+
path=path,
|
121
|
+
endpoint=func,
|
122
|
+
methods=methods,
|
123
|
+
name=name,
|
124
|
+
include_in_schema=include_in_schema,
|
125
|
+
tags=tags,
|
126
|
+
summary=summary,
|
127
|
+
description=description,
|
128
|
+
response_model=response_model,
|
129
|
+
status_code=status_code,
|
130
|
+
)
|
131
|
+
return func
|
132
|
+
|
133
|
+
return decorator
|
134
|
+
|
135
|
+
def get(
|
136
|
+
self,
|
137
|
+
path: str,
|
138
|
+
*,
|
139
|
+
name: Optional[str] = None,
|
140
|
+
include_in_schema: bool = True,
|
141
|
+
tags: Optional[List[str]] = None,
|
142
|
+
summary: Optional[str] = None,
|
143
|
+
description: Optional[str] = None,
|
144
|
+
response_model: Optional[Type] = None,
|
145
|
+
status_code: int = 200,
|
146
|
+
) -> Callable:
|
147
|
+
"""
|
148
|
+
Decorator for GET requests.
|
149
|
+
|
150
|
+
Example:
|
151
|
+
@router.get("/items/{item_id}")
|
152
|
+
async def get_item(item_id: str):
|
153
|
+
return {"id": item_id}
|
154
|
+
"""
|
155
|
+
return self.route(
|
156
|
+
path,
|
157
|
+
methods=["GET"],
|
158
|
+
name=name,
|
159
|
+
include_in_schema=include_in_schema,
|
160
|
+
tags=tags,
|
161
|
+
summary=summary,
|
162
|
+
description=description,
|
163
|
+
response_model=response_model,
|
164
|
+
status_code=status_code,
|
165
|
+
)
|
166
|
+
|
167
|
+
def post(
|
168
|
+
self,
|
169
|
+
path: str,
|
170
|
+
*,
|
171
|
+
name: Optional[str] = None,
|
172
|
+
include_in_schema: bool = True,
|
173
|
+
tags: Optional[List[str]] = None,
|
174
|
+
summary: Optional[str] = None,
|
175
|
+
description: Optional[str] = None,
|
176
|
+
response_model: Optional[Type] = None,
|
177
|
+
status_code: int = 201,
|
178
|
+
) -> Callable:
|
179
|
+
"""
|
180
|
+
Decorator for POST requests.
|
181
|
+
|
182
|
+
Example:
|
183
|
+
@router.post("/items")
|
184
|
+
async def create_item(request: Request):
|
185
|
+
data = await request.json()
|
186
|
+
return {"id": "new", **data}
|
187
|
+
"""
|
188
|
+
return self.route(
|
189
|
+
path,
|
190
|
+
methods=["POST"],
|
191
|
+
name=name,
|
192
|
+
include_in_schema=include_in_schema,
|
193
|
+
tags=tags,
|
194
|
+
summary=summary,
|
195
|
+
description=description,
|
196
|
+
response_model=response_model,
|
197
|
+
status_code=status_code,
|
198
|
+
)
|
199
|
+
|
200
|
+
def put(
|
201
|
+
self,
|
202
|
+
path: str,
|
203
|
+
*,
|
204
|
+
name: Optional[str] = None,
|
205
|
+
include_in_schema: bool = True,
|
206
|
+
tags: Optional[List[str]] = None,
|
207
|
+
summary: Optional[str] = None,
|
208
|
+
description: Optional[str] = None,
|
209
|
+
response_model: Optional[Type] = None,
|
210
|
+
status_code: int = 200,
|
211
|
+
) -> Callable:
|
212
|
+
"""Decorator for PUT requests."""
|
213
|
+
return self.route(
|
214
|
+
path,
|
215
|
+
methods=["PUT"],
|
216
|
+
name=name,
|
217
|
+
include_in_schema=include_in_schema,
|
218
|
+
tags=tags,
|
219
|
+
summary=summary,
|
220
|
+
description=description,
|
221
|
+
response_model=response_model,
|
222
|
+
status_code=status_code,
|
223
|
+
)
|
224
|
+
|
225
|
+
def patch(
|
226
|
+
self,
|
227
|
+
path: str,
|
228
|
+
*,
|
229
|
+
name: Optional[str] = None,
|
230
|
+
include_in_schema: bool = True,
|
231
|
+
tags: Optional[List[str]] = None,
|
232
|
+
summary: Optional[str] = None,
|
233
|
+
description: Optional[str] = None,
|
234
|
+
response_model: Optional[Type] = None,
|
235
|
+
status_code: int = 200,
|
236
|
+
) -> Callable:
|
237
|
+
"""Decorator for PATCH requests."""
|
238
|
+
return self.route(
|
239
|
+
path,
|
240
|
+
methods=["PATCH"],
|
241
|
+
name=name,
|
242
|
+
include_in_schema=include_in_schema,
|
243
|
+
tags=tags,
|
244
|
+
summary=summary,
|
245
|
+
description=description,
|
246
|
+
response_model=response_model,
|
247
|
+
status_code=status_code,
|
248
|
+
)
|
249
|
+
|
250
|
+
def delete(
|
251
|
+
self,
|
252
|
+
path: str,
|
253
|
+
*,
|
254
|
+
name: Optional[str] = None,
|
255
|
+
include_in_schema: bool = True,
|
256
|
+
tags: Optional[List[str]] = None,
|
257
|
+
summary: Optional[str] = None,
|
258
|
+
description: Optional[str] = None,
|
259
|
+
response_model: Optional[Type] = None,
|
260
|
+
status_code: int = 204,
|
261
|
+
) -> Callable:
|
262
|
+
"""Decorator for DELETE requests."""
|
263
|
+
return self.route(
|
264
|
+
path,
|
265
|
+
methods=["DELETE"],
|
266
|
+
name=name,
|
267
|
+
include_in_schema=include_in_schema,
|
268
|
+
tags=tags,
|
269
|
+
summary=summary,
|
270
|
+
description=description,
|
271
|
+
response_model=response_model,
|
272
|
+
status_code=status_code,
|
273
|
+
)
|
274
|
+
|
275
|
+
def include_router(
|
276
|
+
self,
|
277
|
+
router: "Router",
|
278
|
+
prefix: str = "",
|
279
|
+
tags: Optional[List[str]] = None,
|
280
|
+
) -> None:
|
281
|
+
"""
|
282
|
+
Include another router's routes in this router.
|
283
|
+
|
284
|
+
Args:
|
285
|
+
router: Router to include
|
286
|
+
prefix: Additional prefix for included routes
|
287
|
+
tags: Additional tags for included routes
|
288
|
+
|
289
|
+
Example:
|
290
|
+
users_router = Router()
|
291
|
+
@users_router.get("/{user_id}")
|
292
|
+
async def get_user(user_id: str):
|
293
|
+
return {"id": user_id}
|
294
|
+
|
295
|
+
main_router = Router()
|
296
|
+
main_router.include_router(users_router, prefix="/users", tags=["users"])
|
297
|
+
"""
|
298
|
+
self.child_routers.append((router, prefix, tags))
|
299
|
+
|
300
|
+
def get_routes(self) -> List[Route]:
|
301
|
+
"""
|
302
|
+
Get all routes including child routers.
|
303
|
+
|
304
|
+
Returns:
|
305
|
+
List of Route objects with prefixes applied
|
306
|
+
"""
|
307
|
+
routes = []
|
308
|
+
|
309
|
+
# Add direct routes with prefix
|
310
|
+
for route in self.routes:
|
311
|
+
# Create a copy with the prefix applied
|
312
|
+
prefixed_route = Route(
|
313
|
+
path=self.prefix + route.path,
|
314
|
+
endpoint=route.endpoint,
|
315
|
+
methods=route.methods,
|
316
|
+
name=route.name,
|
317
|
+
include_in_schema=route.include_in_schema,
|
318
|
+
tags=route.tags,
|
319
|
+
summary=route.summary,
|
320
|
+
description=route.description,
|
321
|
+
response_model=route.response_model,
|
322
|
+
status_code=route.status_code,
|
323
|
+
)
|
324
|
+
routes.append(prefixed_route)
|
325
|
+
|
326
|
+
# Add child router routes
|
327
|
+
for child_router, child_prefix, child_tags in self.child_routers:
|
328
|
+
for route in child_router.get_routes():
|
329
|
+
# Apply additional prefix and tags
|
330
|
+
combined_prefix = self.prefix + child_prefix
|
331
|
+
combined_tags = route.tags + (child_tags or [])
|
332
|
+
|
333
|
+
prefixed_route = Route(
|
334
|
+
path=combined_prefix + route.path,
|
335
|
+
endpoint=route.endpoint,
|
336
|
+
methods=route.methods,
|
337
|
+
name=route.name,
|
338
|
+
include_in_schema=route.include_in_schema,
|
339
|
+
tags=combined_tags,
|
340
|
+
summary=route.summary,
|
341
|
+
description=route.description,
|
342
|
+
response_model=route.response_model,
|
343
|
+
status_code=route.status_code,
|
344
|
+
)
|
345
|
+
routes.append(prefixed_route)
|
346
|
+
|
347
|
+
return routes
|
348
|
+
|
349
|
+
|
350
|
+
__all__ = ["Router"]
|
vega/web/routing.py
ADDED
@@ -0,0 +1,347 @@
|
|
1
|
+
"""Routing utilities and decorators for Vega Web Framework"""
|
2
|
+
|
3
|
+
import inspect
|
4
|
+
from typing import Any, Callable, Dict, List, Optional, Type, get_type_hints
|
5
|
+
from functools import wraps
|
6
|
+
|
7
|
+
from starlette.routing import Route as StarletteRoute, Mount
|
8
|
+
from starlette.requests import Request as StarletteRequest
|
9
|
+
|
10
|
+
from .exceptions import HTTPException
|
11
|
+
from .request import Request
|
12
|
+
from .response import JSONResponse, Response, create_response
|
13
|
+
from .route_middleware import MiddlewareChain
|
14
|
+
|
15
|
+
|
16
|
+
class Route:
|
17
|
+
"""
|
18
|
+
Represents a single route in the application.
|
19
|
+
|
20
|
+
Args:
|
21
|
+
path: URL path pattern (e.g., "/users/{user_id}")
|
22
|
+
endpoint: Handler function
|
23
|
+
methods: HTTP methods (e.g., ["GET", "POST"])
|
24
|
+
name: Optional route name
|
25
|
+
include_in_schema: Whether to include in OpenAPI schema
|
26
|
+
tags: Tags for documentation
|
27
|
+
summary: Short description
|
28
|
+
description: Longer description
|
29
|
+
response_model: Expected response model type
|
30
|
+
status_code: Default status code
|
31
|
+
"""
|
32
|
+
|
33
|
+
def __init__(
|
34
|
+
self,
|
35
|
+
path: str,
|
36
|
+
endpoint: Callable,
|
37
|
+
methods: List[str],
|
38
|
+
name: Optional[str] = None,
|
39
|
+
include_in_schema: bool = True,
|
40
|
+
tags: Optional[List[str]] = None,
|
41
|
+
summary: Optional[str] = None,
|
42
|
+
description: Optional[str] = None,
|
43
|
+
response_model: Optional[Type] = None,
|
44
|
+
status_code: int = 200,
|
45
|
+
):
|
46
|
+
self.path = path
|
47
|
+
self.endpoint = endpoint
|
48
|
+
self.methods = methods
|
49
|
+
self.name = name or endpoint.__name__
|
50
|
+
self.include_in_schema = include_in_schema
|
51
|
+
self.tags = tags or []
|
52
|
+
self.summary = summary
|
53
|
+
self.description = description or inspect.getdoc(endpoint)
|
54
|
+
self.response_model = response_model
|
55
|
+
self.status_code = status_code
|
56
|
+
|
57
|
+
# Extract middleware from endpoint if decorated with @middleware
|
58
|
+
self.middlewares = getattr(endpoint, '_route_middlewares', [])
|
59
|
+
|
60
|
+
async def __call__(self, request: StarletteRequest) -> Response:
|
61
|
+
"""Execute the route handler"""
|
62
|
+
return await self.endpoint(request)
|
63
|
+
|
64
|
+
def to_starlette_route(self) -> StarletteRoute:
|
65
|
+
"""Convert to Starlette Route object"""
|
66
|
+
async def wrapped_endpoint(request: StarletteRequest) -> Response:
|
67
|
+
"""Wrapper that handles request/response conversion and exceptions"""
|
68
|
+
try:
|
69
|
+
# Use request directly - Request is already a subclass of StarletteRequest
|
70
|
+
vega_request = request
|
71
|
+
|
72
|
+
# Get function signature to determine how to call it
|
73
|
+
sig = inspect.signature(self.endpoint)
|
74
|
+
params = sig.parameters
|
75
|
+
|
76
|
+
# Prepare kwargs for function call
|
77
|
+
kwargs = {}
|
78
|
+
|
79
|
+
# Extract path parameters
|
80
|
+
path_params = request.path_params
|
81
|
+
|
82
|
+
# Check if function expects Request object
|
83
|
+
has_request_param = any(
|
84
|
+
param.annotation == Request or param.name == "request"
|
85
|
+
for param in params.values()
|
86
|
+
)
|
87
|
+
|
88
|
+
if has_request_param:
|
89
|
+
kwargs["request"] = vega_request
|
90
|
+
|
91
|
+
# Add path parameters
|
92
|
+
for param_name, param_value in path_params.items():
|
93
|
+
if param_name in params:
|
94
|
+
kwargs[param_name] = param_value
|
95
|
+
|
96
|
+
# Execute middleware chain if present
|
97
|
+
if self.middlewares:
|
98
|
+
middleware_chain = MiddlewareChain(self.middlewares)
|
99
|
+
# Remove request from kwargs since it's passed separately to middleware
|
100
|
+
handler_kwargs = {k: v for k, v in kwargs.items() if k != "request"}
|
101
|
+
return await middleware_chain.execute(
|
102
|
+
vega_request,
|
103
|
+
self.endpoint,
|
104
|
+
**handler_kwargs
|
105
|
+
)
|
106
|
+
|
107
|
+
# No middleware, call endpoint directly
|
108
|
+
if inspect.iscoroutinefunction(self.endpoint):
|
109
|
+
result = await self.endpoint(**kwargs)
|
110
|
+
else:
|
111
|
+
result = self.endpoint(**kwargs)
|
112
|
+
|
113
|
+
# Handle different return types
|
114
|
+
if isinstance(result, (Response, JSONResponse)):
|
115
|
+
return result
|
116
|
+
elif isinstance(result, dict):
|
117
|
+
return JSONResponse(content=result, status_code=self.status_code)
|
118
|
+
elif isinstance(result, (list, tuple)):
|
119
|
+
return JSONResponse(content=result, status_code=self.status_code)
|
120
|
+
elif isinstance(result, str):
|
121
|
+
return Response(content=result, status_code=self.status_code)
|
122
|
+
elif result is None:
|
123
|
+
return Response(content=b"", status_code=self.status_code)
|
124
|
+
else:
|
125
|
+
# Try to serialize as JSON
|
126
|
+
return JSONResponse(content=result, status_code=self.status_code)
|
127
|
+
|
128
|
+
except HTTPException as exc:
|
129
|
+
# Handle HTTP exceptions
|
130
|
+
return JSONResponse(
|
131
|
+
content={"detail": exc.detail},
|
132
|
+
status_code=exc.status_code,
|
133
|
+
headers=exc.headers,
|
134
|
+
)
|
135
|
+
except Exception as exc:
|
136
|
+
# Handle unexpected exceptions
|
137
|
+
return JSONResponse(
|
138
|
+
content={"detail": str(exc)},
|
139
|
+
status_code=500,
|
140
|
+
)
|
141
|
+
|
142
|
+
return StarletteRoute(
|
143
|
+
path=self.path,
|
144
|
+
endpoint=wrapped_endpoint,
|
145
|
+
methods=self.methods,
|
146
|
+
name=self.name,
|
147
|
+
)
|
148
|
+
|
149
|
+
|
150
|
+
def route(
|
151
|
+
path: str,
|
152
|
+
methods: List[str],
|
153
|
+
*,
|
154
|
+
name: Optional[str] = None,
|
155
|
+
include_in_schema: bool = True,
|
156
|
+
tags: Optional[List[str]] = None,
|
157
|
+
summary: Optional[str] = None,
|
158
|
+
description: Optional[str] = None,
|
159
|
+
response_model: Optional[Type] = None,
|
160
|
+
status_code: int = 200,
|
161
|
+
) -> Callable:
|
162
|
+
"""
|
163
|
+
Generic route decorator.
|
164
|
+
|
165
|
+
Args:
|
166
|
+
path: URL path pattern
|
167
|
+
methods: List of HTTP methods
|
168
|
+
name: Optional route name
|
169
|
+
include_in_schema: Whether to include in API docs
|
170
|
+
tags: Tags for documentation
|
171
|
+
summary: Short description
|
172
|
+
description: Longer description
|
173
|
+
response_model: Expected response type
|
174
|
+
status_code: Default HTTP status code
|
175
|
+
|
176
|
+
Example:
|
177
|
+
@route("/users", methods=["GET", "POST"])
|
178
|
+
async def users_handler():
|
179
|
+
return {"users": []}
|
180
|
+
"""
|
181
|
+
|
182
|
+
def decorator(func: Callable) -> Callable:
|
183
|
+
func._route_info = {
|
184
|
+
"path": path,
|
185
|
+
"methods": methods,
|
186
|
+
"name": name,
|
187
|
+
"include_in_schema": include_in_schema,
|
188
|
+
"tags": tags,
|
189
|
+
"summary": summary,
|
190
|
+
"description": description,
|
191
|
+
"response_model": response_model,
|
192
|
+
"status_code": status_code,
|
193
|
+
}
|
194
|
+
return func
|
195
|
+
|
196
|
+
return decorator
|
197
|
+
|
198
|
+
|
199
|
+
def get(
|
200
|
+
path: str,
|
201
|
+
*,
|
202
|
+
name: Optional[str] = None,
|
203
|
+
include_in_schema: bool = True,
|
204
|
+
tags: Optional[List[str]] = None,
|
205
|
+
summary: Optional[str] = None,
|
206
|
+
description: Optional[str] = None,
|
207
|
+
response_model: Optional[Type] = None,
|
208
|
+
status_code: int = 200,
|
209
|
+
) -> Callable:
|
210
|
+
"""
|
211
|
+
GET request decorator.
|
212
|
+
|
213
|
+
Example:
|
214
|
+
@get("/users/{user_id}")
|
215
|
+
async def get_user(user_id: str):
|
216
|
+
return {"id": user_id}
|
217
|
+
"""
|
218
|
+
return route(
|
219
|
+
path,
|
220
|
+
methods=["GET"],
|
221
|
+
name=name,
|
222
|
+
include_in_schema=include_in_schema,
|
223
|
+
tags=tags,
|
224
|
+
summary=summary,
|
225
|
+
description=description,
|
226
|
+
response_model=response_model,
|
227
|
+
status_code=status_code,
|
228
|
+
)
|
229
|
+
|
230
|
+
|
231
|
+
def post(
|
232
|
+
path: str,
|
233
|
+
*,
|
234
|
+
name: Optional[str] = None,
|
235
|
+
include_in_schema: bool = True,
|
236
|
+
tags: Optional[List[str]] = None,
|
237
|
+
summary: Optional[str] = None,
|
238
|
+
description: Optional[str] = None,
|
239
|
+
response_model: Optional[Type] = None,
|
240
|
+
status_code: int = 201,
|
241
|
+
) -> Callable:
|
242
|
+
"""
|
243
|
+
POST request decorator.
|
244
|
+
|
245
|
+
Example:
|
246
|
+
@post("/users")
|
247
|
+
async def create_user(request: Request):
|
248
|
+
data = await request.json()
|
249
|
+
return {"id": "new_user", **data}
|
250
|
+
"""
|
251
|
+
return route(
|
252
|
+
path,
|
253
|
+
methods=["POST"],
|
254
|
+
name=name,
|
255
|
+
include_in_schema=include_in_schema,
|
256
|
+
tags=tags,
|
257
|
+
summary=summary,
|
258
|
+
description=description,
|
259
|
+
response_model=response_model,
|
260
|
+
status_code=status_code,
|
261
|
+
)
|
262
|
+
|
263
|
+
|
264
|
+
def put(
|
265
|
+
path: str,
|
266
|
+
*,
|
267
|
+
name: Optional[str] = None,
|
268
|
+
include_in_schema: bool = True,
|
269
|
+
tags: Optional[List[str]] = None,
|
270
|
+
summary: Optional[str] = None,
|
271
|
+
description: Optional[str] = None,
|
272
|
+
response_model: Optional[Type] = None,
|
273
|
+
status_code: int = 200,
|
274
|
+
) -> Callable:
|
275
|
+
"""PUT request decorator."""
|
276
|
+
return route(
|
277
|
+
path,
|
278
|
+
methods=["PUT"],
|
279
|
+
name=name,
|
280
|
+
include_in_schema=include_in_schema,
|
281
|
+
tags=tags,
|
282
|
+
summary=summary,
|
283
|
+
description=description,
|
284
|
+
response_model=response_model,
|
285
|
+
status_code=status_code,
|
286
|
+
)
|
287
|
+
|
288
|
+
|
289
|
+
def patch(
|
290
|
+
path: str,
|
291
|
+
*,
|
292
|
+
name: Optional[str] = None,
|
293
|
+
include_in_schema: bool = True,
|
294
|
+
tags: Optional[List[str]] = None,
|
295
|
+
summary: Optional[str] = None,
|
296
|
+
description: Optional[str] = None,
|
297
|
+
response_model: Optional[Type] = None,
|
298
|
+
status_code: int = 200,
|
299
|
+
) -> Callable:
|
300
|
+
"""PATCH request decorator."""
|
301
|
+
return route(
|
302
|
+
path,
|
303
|
+
methods=["PATCH"],
|
304
|
+
name=name,
|
305
|
+
include_in_schema=include_in_schema,
|
306
|
+
tags=tags,
|
307
|
+
summary=summary,
|
308
|
+
description=description,
|
309
|
+
response_model=response_model,
|
310
|
+
status_code=status_code,
|
311
|
+
)
|
312
|
+
|
313
|
+
|
314
|
+
def delete(
|
315
|
+
path: str,
|
316
|
+
*,
|
317
|
+
name: Optional[str] = None,
|
318
|
+
include_in_schema: bool = True,
|
319
|
+
tags: Optional[List[str]] = None,
|
320
|
+
summary: Optional[str] = None,
|
321
|
+
description: Optional[str] = None,
|
322
|
+
response_model: Optional[Type] = None,
|
323
|
+
status_code: int = 204,
|
324
|
+
) -> Callable:
|
325
|
+
"""DELETE request decorator."""
|
326
|
+
return route(
|
327
|
+
path,
|
328
|
+
methods=["DELETE"],
|
329
|
+
name=name,
|
330
|
+
include_in_schema=include_in_schema,
|
331
|
+
tags=tags,
|
332
|
+
summary=summary,
|
333
|
+
description=description,
|
334
|
+
response_model=response_model,
|
335
|
+
status_code=status_code,
|
336
|
+
)
|
337
|
+
|
338
|
+
|
339
|
+
__all__ = [
|
340
|
+
"Route",
|
341
|
+
"route",
|
342
|
+
"get",
|
343
|
+
"post",
|
344
|
+
"put",
|
345
|
+
"patch",
|
346
|
+
"delete",
|
347
|
+
]
|