aboutsummaryrefslogtreecommitdiffstats
path: root/python/flask/views.py
diff options
context:
space:
mode:
authorJames Taylor <user234683@users.noreply.github.com>2019-08-09 22:01:04 -0700
committerJames Taylor <user234683@users.noreply.github.com>2019-08-09 22:01:04 -0700
commit2e75c6d9603f8a5edf6495f8d4fb3115a67d823c (patch)
tree8fb2d1bec2cf0e50c5fce6bc718f755485419db0 /python/flask/views.py
parentcc9283ad5332f59a69a91d9d0fab299779de513c (diff)
parentadc40bc760345a23678a01f27d7697dfd3811914 (diff)
downloadyt-local-2e75c6d9603f8a5edf6495f8d4fb3115a67d823c.tar.lz
yt-local-2e75c6d9603f8a5edf6495f8d4fb3115a67d823c.tar.xz
yt-local-2e75c6d9603f8a5edf6495f8d4fb3115a67d823c.zip
Merge flask framework and other stuff from master
Diffstat (limited to 'python/flask/views.py')
-rw-r--r--python/flask/views.py158
1 files changed, 158 insertions, 0 deletions
diff --git a/python/flask/views.py b/python/flask/views.py
new file mode 100644
index 0000000..1f2c997
--- /dev/null
+++ b/python/flask/views.py
@@ -0,0 +1,158 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.views
+ ~~~~~~~~~~~
+
+ This module provides class-based views inspired by the ones in Django.
+
+ :copyright: © 2010 by the Pallets team.
+ :license: BSD, see LICENSE for more details.
+"""
+
+from .globals import request
+from ._compat import with_metaclass
+
+
+http_method_funcs = frozenset(['get', 'post', 'head', 'options',
+ 'delete', 'put', 'trace', 'patch'])
+
+
+class View(object):
+ """Alternative way to use view functions. A subclass has to implement
+ :meth:`dispatch_request` which is called with the view arguments from
+ the URL routing system. If :attr:`methods` is provided the methods
+ do not have to be passed to the :meth:`~flask.Flask.add_url_rule`
+ method explicitly::
+
+ class MyView(View):
+ methods = ['GET']
+
+ def dispatch_request(self, name):
+ return 'Hello %s!' % name
+
+ app.add_url_rule('/hello/<name>', view_func=MyView.as_view('myview'))
+
+ When you want to decorate a pluggable view you will have to either do that
+ when the view function is created (by wrapping the return value of
+ :meth:`as_view`) or you can use the :attr:`decorators` attribute::
+
+ class SecretView(View):
+ methods = ['GET']
+ decorators = [superuser_required]
+
+ def dispatch_request(self):
+ ...
+
+ The decorators stored in the decorators list are applied one after another
+ when the view function is created. Note that you can *not* use the class
+ based decorators since those would decorate the view class and not the
+ generated view function!
+ """
+
+ #: A list of methods this view can handle.
+ methods = None
+
+ #: Setting this disables or force-enables the automatic options handling.
+ provide_automatic_options = None
+
+ #: The canonical way to decorate class-based views is to decorate the
+ #: return value of as_view(). However since this moves parts of the
+ #: logic from the class declaration to the place where it's hooked
+ #: into the routing system.
+ #:
+ #: You can place one or more decorators in this list and whenever the
+ #: view function is created the result is automatically decorated.
+ #:
+ #: .. versionadded:: 0.8
+ decorators = ()
+
+ def dispatch_request(self):
+ """Subclasses have to override this method to implement the
+ actual view function code. This method is called with all
+ the arguments from the URL rule.
+ """
+ raise NotImplementedError()
+
+ @classmethod
+ def as_view(cls, name, *class_args, **class_kwargs):
+ """Converts the class into an actual view function that can be used
+ with the routing system. Internally this generates a function on the
+ fly which will instantiate the :class:`View` on each request and call
+ the :meth:`dispatch_request` method on it.
+
+ The arguments passed to :meth:`as_view` are forwarded to the
+ constructor of the class.
+ """
+ def view(*args, **kwargs):
+ self = view.view_class(*class_args, **class_kwargs)
+ return self.dispatch_request(*args, **kwargs)
+
+ if cls.decorators:
+ view.__name__ = name
+ view.__module__ = cls.__module__
+ for decorator in cls.decorators:
+ view = decorator(view)
+
+ # We attach the view class to the view function for two reasons:
+ # first of all it allows us to easily figure out what class-based
+ # view this thing came from, secondly it's also used for instantiating
+ # the view class so you can actually replace it with something else
+ # for testing purposes and debugging.
+ view.view_class = cls
+ view.__name__ = name
+ view.__doc__ = cls.__doc__
+ view.__module__ = cls.__module__
+ view.methods = cls.methods
+ view.provide_automatic_options = cls.provide_automatic_options
+ return view
+
+
+class MethodViewType(type):
+ """Metaclass for :class:`MethodView` that determines what methods the view
+ defines.
+ """
+
+ def __init__(cls, name, bases, d):
+ super(MethodViewType, cls).__init__(name, bases, d)
+
+ if 'methods' not in d:
+ methods = set()
+
+ for key in http_method_funcs:
+ if hasattr(cls, key):
+ methods.add(key.upper())
+
+ # If we have no method at all in there we don't want to add a
+ # method list. This is for instance the case for the base class
+ # or another subclass of a base method view that does not introduce
+ # new methods.
+ if methods:
+ cls.methods = methods
+
+
+class MethodView(with_metaclass(MethodViewType, View)):
+ """A class-based view that dispatches request methods to the corresponding
+ class methods. For example, if you implement a ``get`` method, it will be
+ used to handle ``GET`` requests. ::
+
+ class CounterAPI(MethodView):
+ def get(self):
+ return session.get('counter', 0)
+
+ def post(self):
+ session['counter'] = session.get('counter', 0) + 1
+ return 'OK'
+
+ app.add_url_rule('/counter', view_func=CounterAPI.as_view('counter'))
+ """
+
+ def dispatch_request(self, *args, **kwargs):
+ meth = getattr(self, request.method.lower(), None)
+
+ # If the request method is HEAD and we don't have a handler for it
+ # retry with GET.
+ if meth is None and request.method == 'HEAD':
+ meth = getattr(self, 'get', None)
+
+ assert meth is not None, 'Unimplemented method %r' % request.method
+ return meth(*args, **kwargs)