Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto generate route name #2928

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 15 additions & 4 deletions sanic/app.py
Expand Up @@ -223,6 +223,7 @@
"strict_slashes",
"websocket_enabled",
"websocket_tasks",
"unique_route_name_generate",
)

_app_registry: ClassVar[Dict[str, "Sanic"]] = {}
Expand All @@ -247,7 +248,9 @@
inspector: bool = False,
inspector_class: Optional[Type[Inspector]] = None,
certloader_class: Optional[Type[CertLoader]] = None,
) -> None: ...
unique_route_name_generate: bool = False,
) -> None:
...

Check warning on line 253 in sanic/app.py

View check run for this annotation

Codecov / codecov/patch

sanic/app.py#L253

Added line #L253 was not covered by tests

@overload
def __init__(
Expand All @@ -268,7 +271,9 @@
inspector: bool = False,
inspector_class: Optional[Type[Inspector]] = None,
certloader_class: Optional[Type[CertLoader]] = None,
) -> None: ...
unique_route_name_generate: bool = False,
) -> None:
...

Check warning on line 276 in sanic/app.py

View check run for this annotation

Codecov / codecov/patch

sanic/app.py#L276

Added line #L276 was not covered by tests

@overload
def __init__(
Expand All @@ -289,7 +294,9 @@
inspector: bool = False,
inspector_class: Optional[Type[Inspector]] = None,
certloader_class: Optional[Type[CertLoader]] = None,
) -> None: ...
unique_route_name_generate: bool = False,
) -> None:
...

Check warning on line 299 in sanic/app.py

View check run for this annotation

Codecov / codecov/patch

sanic/app.py#L299

Added line #L299 was not covered by tests

@overload
def __init__(
Expand All @@ -310,7 +317,9 @@
inspector: bool = False,
inspector_class: Optional[Type[Inspector]] = None,
certloader_class: Optional[Type[CertLoader]] = None,
) -> None: ...
unique_route_name_generate: bool = False,
) -> None:
...

Check warning on line 322 in sanic/app.py

View check run for this annotation

Codecov / codecov/patch

sanic/app.py#L322

Added line #L322 was not covered by tests

def __init__(
self,
Expand All @@ -330,6 +339,7 @@
inspector: bool = False,
inspector_class: Optional[Type[Inspector]] = None,
certloader_class: Optional[Type[CertLoader]] = None,
unique_route_name_generate: bool = False,
) -> None:
super().__init__(name=name)
# logging
Expand Down Expand Up @@ -386,6 +396,7 @@
self.strict_slashes: bool = strict_slashes
self.websocket_enabled: bool = False
self.websocket_tasks: Set[Future[Any]] = set()
self.unique_route_name_generate = unique_route_name_generate

# Register alternative method names
self.go_fast = self.run
Expand Down
3 changes: 3 additions & 0 deletions sanic/blueprints.py
Expand Up @@ -117,6 +117,7 @@ class Blueprint(BaseSanic):
"version",
"version_prefix",
"websocket_routes",
"unique_route_name_generate",
)

def __init__(
Expand All @@ -127,6 +128,7 @@ def __init__(
version: Optional[Union[int, str, float]] = None,
strict_slashes: Optional[bool] = None,
version_prefix: str = "/v",
unique_route_name_generate: bool = False,
):
super().__init__(name=name)
self.reset()
Expand All @@ -142,6 +144,7 @@ def __init__(
)
self.version = version
self.version_prefix = version_prefix
self.unique_route_name_generate = unique_route_name_generate

def __repr__(self) -> str:
args = ", ".join(
Expand Down
11 changes: 10 additions & 1 deletion sanic/mixins/base.py
Expand Up @@ -9,13 +9,15 @@ class BaseMixin(metaclass=SanicMeta):
name: str
strict_slashes: Optional[bool]

def _generate_name(self, *objects) -> str:
def _generate_name(self, *objects, unique_route_name_generate=False, methods=None, uri=None) -> str:
name = None
_named_route = False

for obj in objects:
if obj:
if isinstance(obj, str):
name = obj
_named_route = True
break

try:
Expand All @@ -32,6 +34,13 @@ def _generate_name(self, *objects) -> str:
raise ValueError("Could not generate a name for handler")

if not name.startswith(f"{self.name}."):
if unique_route_name_generate and not _named_route:
if methods:
methods = "-".join(methods)
name = f"{name}_{methods}"
if uri:
uri = uri.replace("/", "S")
name = f"{name}_{uri}"
name = f"{self.name}.{name}"

return name
4 changes: 3 additions & 1 deletion sanic/mixins/routes.py
Expand Up @@ -139,7 +139,9 @@ def decorator(handler):
# variable will be a tuple of (existing routes, handler fn)
_, handler = handler

name = self._generate_name(name, handler)
name = self._generate_name(
name, handler, unique_route_name_generate=self.unique_route_name_generate, methods=methods, uri=uri
)

if isinstance(host, str):
host = frozenset([host])
Expand Down
33 changes: 33 additions & 0 deletions tests/test_blueprints.py
Expand Up @@ -308,6 +308,39 @@ def handler2(request):
assert "test_bp_with_host_list.test_bp_host.handler2" in route_names


def test_bp_with_auto_name_generate(app: Sanic):
bp = Blueprint(
"test_bp_host",
url_prefix="/test1",
host=["example.com", "sub.example.com"],
unique_route_name_generate=True,
)

@bp.route("/")
def handler1(request):
return text("Hello")

@bp.route("/", host=["sub1.example.com"])
def handler2(request):
return text("Hello subdomain!")

@bp.route("/route_multiple_method", methods=["GET", "POST"])
def handler3(request):
return text("Hello subdomain!")

@bp.route("/route_with_name", methods=["GET", "POST"], name="handler3")
def handler3(request):
return text("Hello subdomain!")

app.blueprint(bp)

route_names = [r.name for r in app.router.routes]
assert "test_bp_with_auto_name_generate.test_bp_host.handler1_GET_S" in route_names
assert "test_bp_with_auto_name_generate.test_bp_host.handler2_GET_S" in route_names
assert "test_bp_with_auto_name_generate.test_bp_host.handler3_GET-POST_Sroute_multiple_method" in route_names
assert "test_bp_with_auto_name_generate.test_bp_host.handler3" in route_names


def test_several_bp_with_host_list(app: Sanic):
bp = Blueprint(
"test_text",
Expand Down