text: # -*- coding: utf-8 -*-
  """
      flask.views
      ~~~~~~~~~~~
  
      This module provides class-based views inspired by the ones in Django.
  
      :copyright: (c) 2011 by Armin Ronacher.
      :license: BSD, see LICENSE for more details.
  """
  from .globals import request
  
  
  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 for which methods this pluggable view can handle.
      methods = 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
          return view
  
  
  class MethodViewType(type):
  
      def __new__(cls, name, bases, d):
          rv = type.__new__(cls, name, bases, d)
          if 'methods' not in d:
              methods = set(rv.methods or [])
              for key in d:
                  if key in http_method_funcs:
                      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 baseclass or another subclass of a base method view
              # that does not introduce new methods).
              if methods:
                  rv.methods = sorted(methods)
          return rv
  
  
  class MethodView(View, metaclass=MethodViewType):
      """Like a regular class-based view but that dispatches requests to
      particular methods.  For instance if you implement a method called
      :meth:`get` it means you will response to ``'GET'`` requests and
      the :meth:`dispatch_request` implementation will automatically
      forward your request to that.  Also :attr:`options` is set for you
      automatically::
  
          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)
  