Routing

Route Objects

When you call any sort of router function (e.g. get or post), it takes in a parameter that is either a function or a Route object. If it's a function, it's then converted to a Route, and if not, it's left alone. This structure allows variant order of decorators.

For example, the following both work just fine:

@get("/")
@query("a", str)
async def route(a: str):
    ...
@query("a", str)
@get("/")
async def route(a: str):
    ...

A Route object is a dataclass that contains the following attributes:

Route

Bases: Generic[P, T], LoadChecker

Standard Route Wrapper

Source code in src/view/routing.py
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
@dataclass
class Route(Generic[P, T], LoadChecker):
    """Standard Route Wrapper"""

    func: Callable[P, T]
    path: str | None
    method: Method
    inputs: list[RouteInput]
    doc: str | None = None
    cache_rate: int = -1
    errors: dict[int, ViewRoute] | None = None
    extra_types: dict[str, Any] = field(default_factory=dict)
    parts: list[str | Part[Any]] = field(default_factory=list)

    def error(self, status_code: int):
        def wrapper(handler: ViewRoute):
            if not self.errors:
                self.errors = {}

            self.errors[status_code] = handler
            return handler

        return wrapper

    def __repr__(self):
        return f"Route({self.method.name}(\"{self.path or '/???'}\"))"  # noqa

    __str__ = __repr__

    def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T:
        return self.func(*args, **kwargs)