From 0dbcd868a682816c6b26daa9a5557c57a1662298 Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Sun, 23 Jun 2024 11:17:51 +0300 Subject: [PATCH 1/3] Allow for custom name generation --- sanic/blueprints.py | 2 +- sanic/mixins/base.py | 36 ++++++++++++++++++++---------------- sanic/mixins/routes.py | 2 +- sanic/mixins/static.py | 2 +- sanic/router.py | 2 +- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 603f83af6f..1fdd67cf2a 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -391,7 +391,7 @@ def register(self, app, options): name = future.name if opt_name_prefix: name = f"{opt_name_prefix}_{future.name}" - name = app._generate_name(name) + name = app.generate_name(name) host = future.host or self.host if isinstance(host, list): host = tuple(host) diff --git a/sanic/mixins/base.py b/sanic/mixins/base.py index f37b2a5acc..990fbbe7ed 100644 --- a/sanic/mixins/base.py +++ b/sanic/mixins/base.py @@ -1,37 +1,41 @@ -from typing import Optional +from typing import Optional, Protocol, Union from sanic.base.meta import SanicMeta +class NameProtocol(Protocol): + name: str + + +class DunderNameProtocol(Protocol): + __name__: str + + class BaseMixin(metaclass=SanicMeta): - """Base class for some other mixins.""" + """Base class for various mixins.""" name: str strict_slashes: Optional[bool] - def _generate_name(self, *objects) -> str: - name = None - + def _generate_name( + self, *objects: Union[NameProtocol, DunderNameProtocol, str] + ) -> str: for obj in objects: if obj: if isinstance(obj, str): name = obj - break - - try: - name = obj.name - except AttributeError: - try: - name = obj.__name__ - except AttributeError: - continue else: - break + name = getattr(obj, "name", getattr(obj, "__name__", None)) - if not name: # noqa + if name: + break + else: raise ValueError("Could not generate a name for handler") if not name.startswith(f"{self.name}."): name = f"{self.name}.{name}" return name + + def generate_name(self, *objects) -> str: + return self._generate_name(*objects) diff --git a/sanic/mixins/routes.py b/sanic/mixins/routes.py index bc194db8fd..af6e4fee01 100644 --- a/sanic/mixins/routes.py +++ b/sanic/mixins/routes.py @@ -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) + name = self.generate_name(name, handler) if isinstance(host, str): host = frozenset([host]) diff --git a/sanic/mixins/static.py b/sanic/mixins/static.py index 88f7ab2613..ec17c485dd 100644 --- a/sanic/mixins/static.py +++ b/sanic/mixins/static.py @@ -112,7 +112,7 @@ def static( ``` """ # noqa: E501 - name = self._generate_name(name) + name = self.generate_name(name) if strict_slashes is None and self.strict_slashes is not None: strict_slashes = self.strict_slashes diff --git a/sanic/router.py b/sanic/router.py index 091172f362..785947380f 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -180,7 +180,7 @@ def find_route_by_view_name( route = self.name_index.get(view_name) if not route: - full_name = self.ctx.app._generate_name(view_name) + full_name = self.ctx.app.generate_name(view_name) route = self.name_index.get(full_name) if not route: From 3c88303362c51038811e524ce637ca8c439a29cb Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Sun, 23 Jun 2024 11:32:11 +0300 Subject: [PATCH 2/3] add type annotation --- sanic/mixins/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sanic/mixins/base.py b/sanic/mixins/base.py index 990fbbe7ed..1c38c21649 100644 --- a/sanic/mixins/base.py +++ b/sanic/mixins/base.py @@ -22,6 +22,7 @@ def _generate_name( ) -> str: for obj in objects: if obj: + name: Optional[str] if isinstance(obj, str): name = obj else: From 4092ee587fdb2ef7589162381def14bcc39205e1 Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Sun, 23 Jun 2024 12:30:47 +0300 Subject: [PATCH 3/3] Simpler flow --- sanic/mixins/base.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/sanic/mixins/base.py b/sanic/mixins/base.py index 1c38c21649..f56c1f8ca2 100644 --- a/sanic/mixins/base.py +++ b/sanic/mixins/base.py @@ -20,17 +20,19 @@ class BaseMixin(metaclass=SanicMeta): def _generate_name( self, *objects: Union[NameProtocol, DunderNameProtocol, str] ) -> str: + print(objects) + name: Optional[str] = None for obj in objects: - if obj: - name: Optional[str] - if isinstance(obj, str): - name = obj - else: - name = getattr(obj, "name", getattr(obj, "__name__", None)) - - if name: - break - else: + if not obj: + continue + if isinstance(obj, str): + name = obj + else: + name = getattr(obj, "name", getattr(obj, "__name__", None)) + + if name: + break + if not name or not isinstance(name, str): raise ValueError("Could not generate a name for handler") if not name.startswith(f"{self.name}."):