Example #1
0
    def _dispatch(self, state, remainder=None):
        """
        This method defines how the object dispatch mechanism works, including
        checking for security along the way.
        """
        if state.dispatcher is None:
            state.dispatcher = self
            state.add_controller('/', self)
        if remainder is None:
            remainder = state.path

        current_controller = state.controller

        #skip any empty urls
        if remainder and not (remainder[0]):
            return self._dispatch(state, remainder[1:])

        self._enter_controller(state, remainder)

        #we are plumb out of path, check for index
        if not remainder:
            if self._is_exposed(current_controller, 'index') and \
               method_matches_args(current_controller.index, state.params, remainder, self._use_lax_params):
                state.add_method(current_controller.index, remainder)
                return state
            #if there is no index, head up the tree
            #to see if there is a default or lookup method we can use
            return self._dispatch_first_found_default_or_lookup(
                state, remainder)

        current_path = state.path_translator(remainder[0])
        current_args = remainder[1:]

        #an exposed method matching the path is found
        if self._is_exposed(current_controller, current_path):
            #check to see if the argspec jives
            controller = getattr(current_controller, current_path)
            if method_matches_args(controller, state.params, current_args,
                                   self._use_lax_params):
                state.add_method(controller, current_args)
                return state

        #another controller is found
        current_controller = getattr(current_controller, current_path, None)
        if current_controller is not None:
            return self._dispatch_controller(current_path, current_controller,
                                             state, current_args)

        #dispatch not found
        return self._dispatch_first_found_default_or_lookup(state, remainder)
    def _dispatch(self, state, remainder=None):
        """
        This method defines how the object dispatch mechanism works, including
        checking for security along the way.
        """
        if state.dispatcher is None:
            state.dispatcher = self
            state.add_controller('/', self)
        if remainder is None:
            remainder = state.path
            
        current_controller = state.controller

        #skip any empty urls
        if remainder and not(remainder[0]):
            return self._dispatch(state, remainder[1:])

        self._enter_controller(state, remainder)

        #we are plumb out of path, check for index
        if not remainder:
            if self._is_exposed(current_controller, 'index') and \
               method_matches_args(current_controller.index, state.params, remainder, self._use_lax_params):
                state.add_method(current_controller.index, remainder)
                return state
            #if there is no index, head up the tree
            #to see if there is a default or lookup method we can use
            return self._dispatch_first_found_default_or_lookup(state, remainder)


        current_path = state.path_translator(remainder[0])
        current_args = remainder[1:]

        #an exposed method matching the path is found
        if self._is_exposed(current_controller, current_path):
            #check to see if the argspec jives
            controller = getattr(current_controller, current_path)
            if method_matches_args(controller, state.params, current_args, self._use_lax_params):
                state.add_method(controller, current_args)
                return state

        #another controller is found
        current_controller = getattr(current_controller, current_path, None)
        if current_controller is not None:
            return self._dispatch_controller(current_path, current_controller,
                                             state, current_args)

        #dispatch not found
        return self._dispatch_first_found_default_or_lookup(state, remainder)
Example #3
0
    def _dispatch_first_found_default_or_lookup(self, state, remainder):
        """
        When the dispatch has reached the end of the tree but not found an
        applicable method, so therefore we head back up the branches of the
        tree until we found a method which matches with a default or lookup method.
        """

        if not state._notfound_stack:
            if self._use_index_fallback:
                #see if there is an index
                current_controller = state.controller
                method = getattr(current_controller, 'index', None)
                if method:
                    if method_matches_args(method, state.params, remainder, self._use_lax_params):
                        state.add_method(current_controller.index, remainder)
                        return state
            raise HTTPNotFound
        else:
        
            m_type, meth, m_remainder, warning = state._notfound_stack.pop()

            if m_type == 'lookup':
                new_controller, new_remainder = meth(*m_remainder)
                state.add_controller(new_controller.__class__.__name__, new_controller)
                dispatcher = getattr(new_controller, '_dispatch', self._dispatch)
                r = dispatcher(state, new_remainder)
                return r
            elif m_type == 'default':
                state.add_method(meth, m_remainder)
                state.dispatcher = self
                return state
Example #4
0
    def _handle_custom_method(self, method, state, remainder):
        current_controller = state.controller
        method_name = method
        http_method = state.request.method
        method = self._find_first_exposed(
            current_controller,
            ('%s_%s' %
             (http_method, method_name), method_name, 'post_%s' % method_name))

        if method and method_matches_args(method, state.params, remainder,
                                          self._use_lax_params):
            state.set_action(method, remainder)
            return state

        # there might be a sub-controller with a custom method, let's go see
        if remainder:
            sub_controller = getattr(current_controller, remainder[0], None)
            if sub_controller:
                current = remainder[0]
                remainder = remainder[1:]
                r = self._dispatch_controller(current, sub_controller, state,
                                              remainder)
                if r:
                    return r
        return self._dispatch_first_found_default_or_lookup(state, remainder)
Example #5
0
    def _handle_delete(self, http_method, state, remainder):
        current_controller = state.controller
        method = self._find_first_exposed(current_controller,
                                          ('post_delete', 'delete'))

        if method and method_matches_args(method, state.params, remainder,
                                          self._use_lax_params):
            state.add_method(method, remainder)
            return state

        #you may not send a delete request to a non-delete function
        if remainder and self._is_exposed(current_controller, remainder[0]):
            raise HTTPMethodNotAllowed

        # there might be a sub-controller with a delete method, let's go see
        if remainder:
            sub_controller = getattr(current_controller, remainder[0], None)
            if sub_controller:
                remainder = remainder[1:]
                state.current_controller = sub_controller
                state.path = remainder
                r = self._dispatch_controller(remainder[0], sub_controller,
                                              state, remainder)
                if r:
                    return r
        return self._dispatch_first_found_default_or_lookup(state, remainder)
Example #6
0
    def _handle_get(self, method, state, remainder):
        current_controller = state.controller
        if not remainder:
            method = self._find_first_exposed(current_controller,
                                              ('get_all', 'get'))
            if method:
                state.set_action(method, remainder)
                return state
            if self._is_exposed(current_controller, 'get_one'):
                method = current_controller.get_one
                if method and method_matches_args(
                        method, state.params, remainder, self._use_lax_params):
                    state.set_action(method, remainder)
                    return state
            return self._dispatch_first_found_default_or_lookup(
                state, remainder)

        #test for "delete", "edit" or "new"
        r = self._handle_delete_edit_or_new(state, remainder)
        if r is not None:
            return r

        #test for custom REST-like attribute
        r = self._handle_custom_get(state, remainder)
        if r is not None:
            return r

        current_path = state.translate_path_piece(remainder[0])
        if self._is_exposed(current_controller, current_path):
            state.set_action(getattr(current_controller, current_path),
                             remainder[1:])
            return state

        if self._is_controller(current_controller, current_path):
            current_controller = getattr(current_controller, current_path)
            return self._dispatch_controller(current_path, current_controller,
                                             state, remainder[1:])

        method = self._find_first_exposed(current_controller,
                                          ('get_one', 'get'))
        if method and method_matches_args(method, state.params, remainder,
                                          self._use_lax_params):
            state.set_action(method, remainder)
            return state

        return self._dispatch_first_found_default_or_lookup(state, remainder)
Example #7
0
    def _handle_custom_get(self, state, remainder):
        controller = state.controller
        method_name = remainder[-1]

        current_controller = state.controller

        get_method = self._find_first_exposed(current_controller, ("get_%s" % method_name, method_name))
        if get_method:
            new_remainder = remainder[:-1]
            if method_matches_args(get_method, state.params, new_remainder, self._use_lax_params):
                state.set_action(get_method, new_remainder)
                return state
Example #8
0
    def _handle_custom_get(self, state, remainder):
        controller = state.controller
        method_name = remainder[-1]

        current_controller = state.controller

        get_method = self._find_first_exposed(current_controller, ('get_%s' % method_name, method_name))
        if get_method:
            new_remainder = remainder[:-1]
            if method_matches_args(get_method, state.params, new_remainder, self._use_lax_params):
                state.add_method(get_method, new_remainder)
                return state
Example #9
0
    def _handle_get(self, method, state, remainder):
        current_controller = state.controller
        if not remainder:
            method = self._find_first_exposed(current_controller, ("get_all", "get"))
            if method:
                state.set_action(method, remainder)
                return state
            if self._is_exposed(current_controller, "get_one"):
                method = current_controller.get_one
                if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
                    state.set_action(method, remainder)
                    return state
            return self._dispatch_first_found_default_or_lookup(state, remainder)

        # test for "delete", "edit" or "new"
        r = self._handle_delete_edit_or_new(state, remainder)
        if r is not None:
            return r

        # test for custom REST-like attribute
        r = self._handle_custom_get(state, remainder)
        if r is not None:
            return r

        current_path = state.translate_path_piece(remainder[0])
        if self._is_exposed(current_controller, current_path):
            state.set_action(getattr(current_controller, current_path), remainder[1:])
            return state

        if self._is_controller(current_controller, current_path):
            current_controller = getattr(current_controller, current_path)
            return self._dispatch_controller(current_path, current_controller, state, remainder[1:])

        method = self._find_first_exposed(current_controller, ("get_one", "get"))
        if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
            state.set_action(method, remainder)
            return state

        return self._dispatch_first_found_default_or_lookup(state, remainder)
Example #10
0
    def _handle_delete_edit_or_new(self, state, remainder):
        method_name = remainder[-1]
        if method_name not in ('new', 'edit', 'delete'):
            return
        if method_name == 'delete':
            method_name = 'get_delete'

        current_controller = state.controller

        if self._is_exposed(current_controller, method_name):
            method = getattr(current_controller, method_name)
            new_remainder = remainder[:-1]
            if method and method_matches_args(method, state.params, new_remainder, self._use_lax_params):
                state.add_method(method, new_remainder)
                return state
Example #11
0
    def _handle_delete_edit_or_new(self, state, remainder):
        method_name = remainder[-1]
        if method_name not in ("new", "edit", "delete"):
            return

        if method_name == "delete":
            method_name = "get_delete"

        current_controller = state.controller

        if self._is_exposed(current_controller, method_name):
            method = getattr(current_controller, method_name)
            new_remainder = remainder[:-1]
            if method and method_matches_args(method, state.params, new_remainder, self._use_lax_params):
                state.set_action(method, new_remainder)
                return state
    def _handle_delete_edit_or_new(self, state, remainder):
        method_name = remainder[-1]
        if method_name not in ('new', 'edit', 'delete'):
            return

        if method_name == 'delete':
            method_name = 'get_delete'

        current_controller = state.controller

        if self._is_exposed(current_controller, method_name):
            method = getattr(current_controller, method_name)
            new_remainder = remainder[:-1]
            if method and method_matches_args(method, state.params, new_remainder, self._use_lax_params):
                state.add_method(method, new_remainder)
                return state
Example #13
0
    def _handle_put_or_post(self, http_method, state, remainder):
        current_controller = state.controller
        if remainder:
            current_path = remainder[0]
            if self._is_exposed(current_controller, current_path):
                state.set_action(getattr(current_controller, current_path), remainder[1:])
                return state

            if self._is_controller(current_controller, current_path):
                current_controller = getattr(current_controller, current_path)
                return self._dispatch_controller(current_path, current_controller, state, remainder[1:])

        method = self._find_first_exposed(current_controller, [http_method])
        if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
            state.set_action(method, remainder)
            return state

        return self._dispatch_first_found_default_or_lookup(state, remainder)
Example #14
0
    def _handle_put_or_post(self, method, state, remainder):
        current_controller = state.controller
        if remainder:
            current_path = remainder[0]
            if self._is_exposed(current_controller, current_path):
                state.add_method(getattr(current_controller, current_path), remainder[1:])
                return state

            if self._is_controller(current_controller, current_path):
                current_controller = getattr(current_controller, current_path)
                return self._dispatch_controller(current_path, current_controller, state, remainder[1:])

        method_name = method
        method = self._find_first_exposed(current_controller, [method,])
        if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
            state.add_method(method, remainder)
            return state

        return self._dispatch_first_found_default_or_lookup(state, remainder)
Example #15
0
    def _handle_delete(self, http_method, state, remainder):
        current_controller = state.controller
        method = self._find_first_exposed(current_controller, ("post_delete", "delete"))

        if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
            state.set_action(method, remainder)
            return state

        # you may not send a delete request to a non-delete function
        if remainder and self._is_exposed(current_controller, remainder[0]):
            raise HTTPMethodNotAllowed

        # there might be a sub-controller with a delete method, let's go see
        if remainder:
            sub_controller = getattr(current_controller, remainder[0], None)
            if sub_controller:
                remainder = remainder[1:]
                r = self._dispatch_controller(remainder[0], sub_controller, state, remainder)
                if r:
                    return r
        return self._dispatch_first_found_default_or_lookup(state, remainder)
Example #16
0
    def _handle_custom_method(self, method, state, remainder):
        current_controller = state.controller
        method_name = method
        http_method = state.request.method
        method = self._find_first_exposed(
            current_controller, ("%s_%s" % (http_method, method_name), method_name, "post_%s" % method_name)
        )

        if method and method_matches_args(method, state.params, remainder, self._use_lax_params):
            state.set_action(method, remainder)
            return state

        # there might be a sub-controller with a custom method, let's go see
        if remainder:
            sub_controller = getattr(current_controller, remainder[0], None)
            if sub_controller:
                current = remainder[0]
                remainder = remainder[1:]
                r = self._dispatch_controller(current, sub_controller, state, remainder)
                if r:
                    return r
        return self._dispatch_first_found_default_or_lookup(state, remainder)