docs: def lti(app=None, request='any', error=default_error, role='any',
          *lti_args, **lti_kwargs):
      """
      LTI decorator
  
      :param: app - Flask App object (optional).
          :py:attr:`flask.current_app` is used if no object is passed in.
      :param: error - Callback if LTI throws exception (optional).
          :py:attr:`pylti.flask.default_error` is the default.
      :param: request - Request type from
          :py:attr:`pylti.common.LTI_REQUEST_TYPE`. (default: any)
      :param: roles - LTI Role (default: any)
      :return: wrapper
      """
  
      def _lti(function):
          """
          Inner LTI decorator
  
          :param: function:
          :return:
          """
  
          @wraps(function)
          def wrapper(*args, **kwargs):
              """
              Pass LTI reference to function or return error.
              """
              try:
                  the_lti = LTI(lti_args, lti_kwargs)
                  the_lti.verify()
                  the_lti._check_role()  # pylint: disable=protected-access
                  kwargs['lti'] = the_lti
                  return function(*args, **kwargs)
              except LTIException as lti_exception:
                  error = lti_kwargs.get('error')
                  exception = dict()
                  exception['exception'] = lti_exception
                  exception['kwargs'] = kwargs
                  exception['args'] = args
                  return error(exception=exception)
  
          return wrapper
  
      lti_kwargs['request'] = request
      lti_kwargs['error'] = error
      lti_kwargs['role'] = role
  
      if (not app) or isinstance(app, Flask):
          lti_kwargs['app'] = app
          return _lti
      else:
          # We are wrapping without arguments
          lti_kwargs['app'] = None
          return _lti(app)