blackbull.router¶
blackbull.router
¶
Route registration and dispatch.
RouteGroup is re-exported lazily from app to avoid a circular import. Handler and middleware contracts are in docs/guide/routing.md.
QUERY = 'QUERY'
module-attribute
¶
The HTTP QUERY method (RFC 10008) — safe, idempotent, cacheable, with a request body.
http.HTTPMethod has no QUERY member (RFC 10008 postdates the 3.15
feature freeze; earliest stdlib arrival is 3.16), so BlackBull exports the
method as a plain string usable anywhere a method is accepted::
from blackbull import QUERY
@app.route(path='/search', methods=[QUERY])
async def search(body: bytes): ...
Because http.HTTPMethod is a StrEnum, this string stays equal- and
hash-compatible with a future HTTPMethod.QUERY member — routes
registered with it need no migration.
ConfigurationError
¶
Bases: Exception
Raised by Router.validate() when route definitions are inconsistent.
ErrorRouter
¶
Resolve error handlers by exception MRO, status, then default.
__call__(key)
¶
Decorator form: @errors(HTTPStatus.NOT_FOUND).
__setitem__(key, fn)
¶
Register fn as the handler for a status or an exception class.
The status must be 4xx or 5xx: the annotation admits any
HTTPStatus, but registering a handler for, say, 200 raises
ValueError.
resolve(exc_class, status=None)
¶
Use status after an exception MRO miss, before the default.
HTTPException
¶
Bases: Exception
An exception carrying the HTTP status the dispatcher should report.
Raising this from a handler — or from the framework's own request-body
adapter — makes BlackBull._dispatch answer with status instead of
the generic 500, and (for 4xx) log it quietly as a client error rather
than dumping a server traceback. detail is an optional
human-readable message surfaced in development-mode error pages.
MethodNotApplicable
¶
Bases: Exception
Raised when the path exists but the HTTP method is not allowed.
PathNotRegistered
¶
Bases: KeyError
Raised when no registered path matches the requested path.
RouteInfo
¶
Bases: NamedTuple
Immutable snapshot of a single registered route entry.
Returned by BlackBull.get_routes. One entry is produced per
(route, method) pair — a route registered with
methods=[GET, POST] yields two RouteInfo records.
Attributes:
| Name | Type | Description |
|---|---|---|
method |
str
|
HTTP method string (e.g. |
path |
str
|
URL template (e.g. |
name |
str
|
Endpoint name, or |
Router
¶
String paths live in the routing trie (sole store, including
{param} segments); raw re.Pattern routes live in
self._raw_regex and are scanned only on a trie miss.
cache_max
property
writable
¶
The lookup cache's entry bound; 0 disables caching. Writable, so the cache can be retuned after construction.
__contains__(item)
¶
Accept either a plain str (path only) or a (path, method, scheme) tuple. True when the path was registered verbatim as a string route, or when any raw re.Pattern route matches it.
__getitem__(key)
¶
key: (path: str, method: str | HTTPMethod, scheme: Scheme)
The query→miss→resolve→store flow; _resolve does the matching.
A repeat of the same key skips resolution entirely after the first hit.
__setitem__(key, value)
¶
Register value under (path, methods) or (path, methods,
scheme), routing the path to whichever of the two stores the class
docstring describes. An omitted scheme is stored as _ANY_SCHEME.
get_routes()
¶
Return a snapshot of all registered routes as RouteInfo.
Routes are returned in registration order. A route registered with
multiple methods (e.g. methods=[GET, POST]) produces one entry
per method, in the order the methods were declared. The returned
list is a fresh shallow copy — callers may sort, filter, or mutate
it without affecting the live router.
register_converter(type_, converter)
¶
Register converter to turn a handler that returns type_ into a sendable (a Response, str/bytes, or JSON-able).
route(methods=[HTTPMethod.GET], path='/', scheme=Scheme.http, functions=[], middlewares=[], name=None, accept_query=None)
¶
Register a function or middleware chain in the routing table.
Three calling conventions:
1. Decorator with no extra middlewares (functions and middlewares
both empty) — returns a decorator via route_fn.
2. functions=[...] — registers a pre-built chain immediately;
returns None (same as before).
3. middlewares=[...] — returns a decorator; the decorated handler is
appended to the middleware list before the chain is registered.
name registers the route for use with url_path_for().
accept_query is documented on BlackBull.route, which
delegates here.
route_fn(methods=[HTTPMethod.GET], path='/', scheme=Scheme.http, name=None, accept_query=None)
¶
Return a decorator that registers the decorated handler.
See BlackBull.route for accept_query.
url_path_for(name, /, **params)
¶
Return the path for the named route with params substituted.
Raises KeyError if the name is unknown, ValueError if required params are missing.
validate()
¶
Check all route definitions for consistency, then freeze the router.
Checks performed:
- Every converter spec names a known converter.
- Every path param appears in the handler signature (simplified handlers).
- Converter output type matches the handler's annotation.
Raises ConfigurationError listing all violations found.
Sets self._frozen = True on success so no further routes can
be added. Called once at app boot from BlackBull.run
or serve — handler bugs that violate the contract
surface before the first request is served, not after.
UnprocessableQuery
¶
Bases: HTTPException
RFC 10008 §2.2 — a well-formed QUERY whose contents cannot be processed.
Raise this from a QUERY handler when the request media type was accepted
(so 400/415 do not apply) but the query itself is semantically invalid —
references an unknown field, violates a constraint, etc. The dispatcher
answers 422 Unprocessable Content and, being an HTTPException
subclass, it flows through the normal error-router path and quiet 4xx
logging.
request_media_type(conn)
¶
Return the request's media type (Content-Type sans parameters),
lowercased; '' when no Content-Type is present.