ranchimallflo-api/py3.7/lib/python3.7/site-packages/quart/views.py

116 lines
3.5 KiB
Python

from typing import Any, Callable, List, Optional
from .globals import request
from .typing import ResponseReturnValue
http_method_funcs = frozenset([
'get', 'post', 'head', 'options', 'delete', 'put', 'trace', 'patch',
])
class View:
"""Use to define routes within a class structure.
A View subclass must implement the :meth:`dispatch_request` in
order to respond to requets. For automatic method finding based on
the request HTTP Verb see :class:`MethodView`.
An example usage is,
.. code-block:: python
class SimpleView:
methods = ['GET']
async def dispatch_request(id):
return f"ID is {id}"
app.add_url_rule('/<id>', view_func=SimpleView.as_view('simple'))
Note that class
Attributes:
decorators: A list of decorators to apply to a view
method. The decorators are applied in the order of
the list.
methods: List of methods this view allows.
provide_automatic_options: Override automatic OPTIONS
if set, to either True or False.
"""
decorators: List[Callable] = []
methods: Optional[List[str]] = None
provide_automatic_options: Optional[bool] = None
async def dispatch_request(self, *args: Any, **kwargs: Any) -> ResponseReturnValue:
"""Override and return a Response.
This will be called with the request view_args, i.e. any url
parameters.
"""
raise NotImplementedError()
@classmethod
def as_view(cls, name: str, *class_args: Any, **class_kwargs: Any) -> Callable:
async def view(*args: Any, **kwargs: Any) -> Callable:
self = view.view_class(*class_args, **class_kwargs) # type: ignore
return await self.dispatch_request(*args, **kwargs)
if cls.decorators:
view.__name__ = name
view.__module__ = cls.__module__
for decorator in cls.decorators:
view = decorator(view)
view.view_class: View = cls # type: ignore
view.__name__ = name
view.__doc__ = cls.__doc__
view.__module__ = cls.__module__
view.methods = cls.methods # type: ignore
view.provide_automatic_options = cls.provide_automatic_options # type: ignore
return view
class MethodViewType(type):
def __init__(cls, name, bases, attributes): # type: ignore # noqa
super().__init__(name, bases, attributes)
if 'methods' not in attributes:
methods = []
for key in http_method_funcs:
if hasattr(cls, key):
methods.append(key.upper())
if methods:
cls.methods = methods
class MethodView(View, metaclass=MethodViewType):
"""A HTTP Method (verb) specific view class.
This has an implementation of :meth:`dispathc_request` such that
it calls a method based on the verb i.e. GET requests are handled
by a `get` method. For example,
.. code-block:: python
class SimpleView(MethodView):
async def get(id):
return f"Get {id}"
async def post(id):
return f"Post {id}"
app.add_url_rule('/<id>', view_func=SimpleView.as_view('simple'))
"""
async def dispatch_request(self, *args: Any, **kwargs: Any) -> ResponseReturnValue:
handler = getattr(self, request.method.lower(), None)
if handler is None and request.method == 'HEAD':
handler = getattr(self, 'get', None)
return await handler(*args, **kwargs)