Route Groups

New in version 2.1.2.

Route Groups are a way of grouping routes together into a single class, where they can all access the members of the class. This is easier than having global shared state, and easily allows having “route” templates.

Creating a Route Group

All route groups descend from RouteGroup, or use RouteGroupType as the metaclass. The former uses the latter as its metaclass, which is a shorter version.

from kyoukai.routegroup import RouteGroup, RouteGroupType

# form 1, easiest form
class MyRouteGroup(RouteGroup):
    ...

# form 2, explicit metaclass
class MyRouteGroup(metaclass=RouteGroupType):
    ...

Note

By default, route groups have no magic __init__. You are free to implement this in whatever way you like, including passing parameters to it.

Adding Routes

To make your route group useful, you need to add some routes to it. The RouteGroup module includes a special decorator that marks a route function as a new Route during instance creation, route().

This method takes the same arguments as the regular route decorator; the only difference is that it returns the original function in the class body rather than returning a new Route object. Instead, certain attributes are set on the new function that are picked up during scanning, such as in_group.

from kyoukai.routegroup import RouteGroup, route

class MyRouteGroup(RouteGroup):
    @route("/heck", methods=("GET", "POST"))
    async def heck_em_up(self, ctx: HTTPRequestContext):
        return "get hecked"

This will register heck_em_up as a route on the new route group.

kyoukai.routegroup.route(url, methods=('GET', 'HEAD'), **kwargs)[source]

A companion function to the RouteGroup class. This follows Blueprint.route() in terms of arguments, and marks a function as a route inside the class.

This will return the original function, with some attributes attached:

  • in_group: Marks the function as in the route group.
  • rg_delegate: Internal. The type of function inside the group this is.
  • route_kwargs: Keyword arguments to provide to wrap_route.
  • route_url: The routing URL to provide to add_route.
  • route_methods: The methods for the route.
  • route_hooks: A defaultdict of route-specific hooks.

Additionally, the following methods are added.

  • hook: A decorator that adds a hook of type type_.
  • before_request: A decorator that adds a pre hook.
  • after_request: A decorator that adds a post hook.

New in version 2.1.1.

Changed in version 2.1.3: Added the ability to add route-specific hooks.

Changed in version 2.2.0: Now accepts an already edited function as the function to decorate - this will add a new routing url and method pair to the Route.routes.

Changed in version 2.2.2: Default methods changed to GET and HEAD.

Parameters:
  • url (str) – The routing URL of the route.
  • methods (Iterable[str]) – An iterable of methods for the route.

Error Handlers

New in version 2.1.3.

Route groups can also have group-specific error handlers, using errorhandler().

@errorhandler(500)
async def handle_errors(self, ctx, exc):
    ...
kyoukai.routegroup.errorhandler(startcode, endcode=None, step=None)[source]

A companion function to the RouteGroup class. This follows Blueprint.errorhandler() in terms of arguments.

Parameters:
  • startcode (int) – The error code to handle, for example 404. This also represents the start of an error range, if endcode is not None.
  • endcode (Optional[int]) – The end of the error code range to handle. Error handlers will be added for all requests between startcode and endcode.
  • step (Optional[int]) – The step for the error handler range.

Request Hooks

New in version 2.1.3.

Route groups can have both Blueprint-specific error handlers, and route-specific error handlers, using the helper functions.

For Blueprint-specific, you can use hook() (or, better, aliases before_request() and after_request()).

@before_request
async def before_req(self, ctx):
    ...

Adding route-specific hooks is possible by calling @route.hook on the newly wrapped function. This is achieved by setting a special decorator function on the function object modified by the route decorator.

@heck_em_up.before_req
async def whatever(self, ctx):
    ...
kyoukai.routegroup.hook(type_)[source]

Marks a function as a hook.

Parameters:type (str) – The type of hook to mark.
kyoukai.routegroup.before_request(func)[source]

Helper decorator to mark a function as a pre-request hook.

kyoukai.routegroup.after_request(func)[source]

Helper decorator to mark a function as a post-request hook.

@func.hook(type_: str)

Marks a function as a route-specific hook.

Parameters:type – The type of hook to add.
@func.before_request

Marks a function as a before-request hook.

@func.after_request

Marks a function as an after-request hook.

Registering the Group

Adding the group to your app is as simple as instantiating the group and calling Blueprint.add_route_group() with the instance.

rg = MyRouteGroup()
app.root.add_route_group(rg)

Of course, an alias for this exists on Kyoukai which redirects to the root blueprint.

Blueprint.add_route_group(group)[source]

Adds a route group to the current Blueprint.

Parameters:group (RouteGroup) – The RouteGroup to add.

Customizing the Blueprint

Route groups work by using an underlying Blueprint that is populated with all the routes from the class body during instantiation. The Blueprint can be customized by passing arguments in the class definition to the metaclass, which are stored and later used to create the new Blueprint object.

class MyRouteGroup(RouteGroup, prefix="/api/v1")
    ...

To get the blueprint object from a RouteGroup instance, you can use get_rg_bp().

kyoukai.routegroup.get_rg_bp(group)[source]

Gets the Blueprint created from a RouteGroup.