Add convenience for annotated handlers (#2225)

This commit is contained in:
Adam Hopkins
2021-08-30 20:04:44 +03:00
committed by GitHub
parent f32ef20b74
commit 2e5c288fea
2 changed files with 66 additions and 0 deletions

View File

@@ -1,5 +1,9 @@
from __future__ import annotations
from functools import lru_cache
from inspect import signature
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
from uuid import UUID
from sanic_routing import BaseRouter # type: ignore
from sanic_routing.exceptions import NoMethod # type: ignore
@@ -106,6 +110,8 @@ class Router(BaseRouter):
version = str(version).strip("/").lstrip("v")
uri = "/".join([f"{version_prefix}{version}", uri.lstrip("/")])
uri = self._normalize(uri, handler)
params = dict(
path=uri,
handler=handler,
@@ -187,3 +193,24 @@ class Router(BaseRouter):
raise SanicException(
f"Invalid route: {route}. Parameter names cannot use '__'."
)
def _normalize(self, uri: str, handler: RouteHandler) -> str:
if "<" not in uri:
return uri
sig = signature(handler)
mapping = {
param.name: param.annotation.__name__.lower()
for param in sig.parameters.values()
if param.annotation in (str, int, float, UUID)
}
reconstruction = []
for part in uri.split("/"):
if part.startswith("<") and ":" not in part:
name = part[1:-1]
annotation = mapping.get(name)
if annotation:
part = f"<{name}:{annotation}>"
reconstruction.append(part)
return "/".join(reconstruction)