docs: def init_app(self, app, cls, callback=None):
          """
          Register routes for a given app and :class:`ClassView` class. At the
          time of this call, we will always be in the view class even if we were
          originally defined in a base class. :meth:`ClassView.init_app`
          ensures this. :meth:`init_app` therefore takes the liberty of adding
          additional attributes to ``self``:
  
          * :attr:`wrapped_func`: The function wrapped with all decorators added by the class
          * :attr:`view_func`: The view function registered as a Flask view handler
          * :attr:`endpoints`: The URL endpoints registered to this view handler
          """
          def view_func(**view_args):
              # view_func does not make any reference to variables from init_app to avoid creating
              # a closure. Instead, the code further below sticks all relevant variables into
              # view_func's namespace.
  
              # Instantiate the view class. We depend on its __init__ requiring no parameters
              viewinst = view_func.view_class()
              # Declare ourselves (the ViewHandler) as the current view. The wrapper makes
              # equivalence tests possible, such as ``self.current_handler == self.index``
              viewinst.current_handler = ViewHandlerWrapper(view_func.view, viewinst, view_func.view_class)
              # Place view arguments in the instance, in case they are needed outside the dispatch process
              viewinst.view_args = view_args
              # Place the view instance on the request stack for :obj:`current_view` to discover
              _request_ctx_stack.top.current_view = viewinst
              # Call the view instance's dispatch method. View classes can customise this for
              # desired behaviour.
              return viewinst.dispatch_request(view_func.wrapped_func, view_args)
  
          # Decorate the wrapped view function with the class's desired decorators.
          # Mixin classes may provide their own decorators, and all of them will be applied.
          # The oldest defined decorators (from mixins) will be applied first, and the
          # class's own decorators last. Within the list of decorators, we reverse the list
          # again, so that a list specified like this:
          #
          #     __decorators__ = [first, second]
          #
          # Has the same effect as writing this:
          #
          #     @first
          #     @second
          #     def myview(self):
          #         pass
          wrapped_func = self.func
          for base in reversed(cls.__mro__):
              if '__decorators__' in base.__dict__:
                  for decorator in reversed(base.__dict__['__decorators__']):
                      wrapped_func = decorator(wrapped_func)
                      wrapped_func.__name__ = self.name  # See below
  
          # Make view_func resemble the underlying view handler method...
          view_func = update_wrapper(view_func, wrapped_func)
          # ...but give view_func the name of the method in the class (self.name),
          # self.name will differ from __name__ only if the view handler method
          # was defined outside the class and then added to the class with a
          # different name.
          view_func.__name__ = self.name
  
          # Stick `wrapped_func` and `cls` into view_func to avoid creating a closure.
          view_func.wrapped_func = wrapped_func
          view_func.view_class = cls
          view_func.view = self
  
          # Keep a copy of these functions (we already have self.func)
          self.wrapped_func = wrapped_func
          self.view_func = view_func
  
          for class_rule, class_options in cls.__routes__:
              for method_rule, method_options in self.routes:
                  use_options = dict(method_options)
                  use_options.update(class_options)
                  endpoint = use_options.pop('endpoint', self.endpoint)
                  self.endpoints.add(endpoint)
                  use_rule = rulejoin(class_rule, method_rule)
                  app.add_url_rule(use_rule, endpoint, view_func, **use_options)
                  if callback:
                      callback(use_rule, endpoint, view_func, **use_options)