Skip to content

Commit

Permalink
Fix reverse lookup for CBV
Browse files Browse the repository at this point in the history
  • Loading branch information
tarsil committed Jan 19, 2025
1 parent edae183 commit 45893f8
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 5 deletions.
2 changes: 1 addition & 1 deletion esmerald/routing/apis/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ def get_routes(
route_kwargs = {
"path": path,
"handler": route_handler,
"name": name or route_handler.fn.__name__,
"name": name or route_handler.name or route_handler.fn.__name__,
"middleware": middleware,
"interceptors": interceptors,
"permissions": permissions,
Expand Down
15 changes: 11 additions & 4 deletions esmerald/routing/gateways.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
import warnings
from typing import TYPE_CHECKING, Any, Callable, List, Optional, Sequence, Union, cast

from lilya._internal._path import clean_path
Expand Down Expand Up @@ -283,10 +284,16 @@ def __init__(

self.methods = getattr(handler, "http_methods", None)

if name and isinstance(handler, View):
warnings.warn(
"When using a class based view, the name will be automatically generated from the class name if the handlers of the Class based view are not specified. This can cause problems with reverse lookup.",
UserWarning,
stacklevel=2,
)

if not name:
if not isinstance(handler, View):
if not handler.name:
name = clean_string(handler.fn.__name__)
name = handler.name or clean_string(handler.fn.__name__)
else:
name = clean_string(handler.__class__.__name__)

Expand Down Expand Up @@ -330,14 +337,14 @@ def __init__(
if self.is_handler(self.handler): # type: ignore
if self.operation_id or handler.operation_id is not None:
handler_id = self.generate_operation_id(
name=self.name,
name=self.name or "",
handler=self.handler, # type: ignore
)
self.operation_id = f"{operation_id}_{handler_id}" if operation_id else handler_id

elif not handler.operation_id:
handler.operation_id = self.generate_operation_id(
name=self.name,
name=self.name or "",
handler=self.handler, # type: ignore
)

Expand Down
53 changes: 53 additions & 0 deletions tests/routing/test_path_lookup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import pytest
from lilya.compat import reverse

from esmerald import Controller, Gateway, Include, get, post
from esmerald.testclient import create_client


@get("/hello")
async def get_hello() -> str:
return "Hello World"


@post("/new")
async def post_new() -> str:
return "New World"


class TestController(Controller):
@get("/int", name="int")
async def get_int(self, id: int) -> int:
return id


routes = [
Include(
"/api",
routes=[
Include(
routes=[
Gateway(handler=get_hello, name="hello"),
Gateway(handler=post_new, name="new"),
Gateway(handler=TestController, name="test"),
],
name="v1",
),
],
name="api",
),
]


@pytest.mark.filterwarnings(r"ignore" r":UserWarning")
def test_can_reverse_lookup(test_client_factory):
with create_client(routes=routes) as client:
app = client.app

assert app.path_for("api:v1:hello") == "/api/hello"
assert app.path_for("api:v1:new") == "/api/new"
assert reverse("api:v1:hello") == "/api/hello"
assert reverse("api:v1:new") == "/api/new"

assert app.path_for("api:v1:int") == "/api/int"
assert reverse("api:v1:int") == "/api/int"

0 comments on commit 45893f8

Please sign in to comment.