Skip to content

Commit

Permalink
Add auto name generation feature to routes in Sanic
Browse files Browse the repository at this point in the history
The ability to automatically generate names for routes has been added to Sanic. This feature is controlled by the 'generate_name' parameter available in the application, blueprint, and route definitions. Additionally, comprehensive tests have been added to ensure the correct functionality of this new feature.
  • Loading branch information
hamed committed Mar 22, 2024
1 parent 479e89a commit 58ed970
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 3 deletions.
7 changes: 7 additions & 0 deletions sanic/app.py
Expand Up @@ -223,6 +223,7 @@ class to use for the application. Defaults to `None`.
"strict_slashes",
"websocket_enabled",
"websocket_tasks",
"generate_name",
)

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

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

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

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

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

# 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",
"generate_name",
)

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",
generate_name: 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.generate_name = generate_name

def __repr__(self) -> str:
args = ", ".join(
Expand Down
4 changes: 2 additions & 2 deletions sanic/mixins/base.py
Expand Up @@ -9,7 +9,7 @@ class BaseMixin(metaclass=SanicMeta):
name: str
strict_slashes: Optional[bool]

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

Expand All @@ -34,7 +34,7 @@ def _generate_name(self, *objects, methods=None, uri=None) -> str:
raise ValueError("Could not generate a name for handler")

if not name.startswith(f"{self.name}."):
if not named_route:
if route_generate and not named_route:
if methods:
methods = "_".join(methods)
name = f"{name}_{methods}"
Expand Down
2 changes: 1 addition & 1 deletion sanic/mixins/routes.py
Expand Up @@ -139,7 +139,7 @@ def decorator(handler):
# variable will be a tuple of (existing routes, handler fn)
_, handler = handler

name = self._generate_name(name, handler, methods=methods, uri=uri)
name = self._generate_name(name, handler, route_generate=self.generate_name, methods=methods, uri=uri)

if isinstance(host, str):
host = frozenset([host])
Expand Down
28 changes: 28 additions & 0 deletions tests/test_blueprints.py
Expand Up @@ -308,6 +308,34 @@ 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"],
generate_name=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_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_/" in route_names
assert "test_bp_with_auto_name_generate.test_bp_host.handler2_GET_/" 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

0 comments on commit 58ed970

Please sign in to comment.