Apply key function to ``msg`` to obtain a key, look up routing table
        to obtain a handler function, then call the handler function with
        positional and keyword arguments, if any is returned by the key function.

        ``*aa`` and ``**kw`` are dummy placeholders for easy chaining.
        Regardless of any number of arguments returned by the key function,
        multi-level routing may be achieved like this::

            top_router.routing_table['key1'] = sub_router1.route
            top_router.routing_table['key2'] = sub_router2.route

def route(self, msg, *aa, **kw):
        """
        Apply key function to ``msg`` to obtain a key, look up routing table
        to obtain a handler function, then call the handler function with
        positional and keyword arguments, if any is returned by the key function.

        ``*aa`` and ``**kw`` are dummy placeholders for easy chaining.
        Regardless of any number of arguments returned by the key function,
        multi-level routing may be achieved like this::

            top_router.routing_table['key1'] = sub_router1.route
            top_router.routing_table['key2'] = sub_router2.route
        """
        k = self.key_function(msg)

        if isinstance(k, (tuple, list)):
            key, args, kwargs = {1: tuple(k) + ((),{}),
                                 2: tuple(k) + ({},),
                                 3: tuple(k),}[len(k)]
        else:
            key, args, kwargs = k, (), {}

        try:
            fn = self.routing_table[key]
        except KeyError as e:
            # Check for default handler, key=None
            if None in self.routing_table:
                fn = self.routing_table[None]
            else:
                raise RuntimeError('No handler for key: %s, and default handler not defined' % str(e.args))

        return fn(msg, *args, **kwargs)