Require stricter object names (#2146)
This commit is contained in:
parent
72a745bfd5
commit
ba374139f4
@ -135,13 +135,8 @@ class Sanic(BaseSanic):
|
|||||||
register: Optional[bool] = None,
|
register: Optional[bool] = None,
|
||||||
dumps: Optional[Callable[..., str]] = None,
|
dumps: Optional[Callable[..., str]] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__()
|
super().__init__(name=name)
|
||||||
|
|
||||||
if name is None:
|
|
||||||
raise SanicException(
|
|
||||||
"Sanic instance cannot be unnamed. "
|
|
||||||
"Please use Sanic(name='your_application_name') instead.",
|
|
||||||
)
|
|
||||||
# logging
|
# logging
|
||||||
if configure_logging:
|
if configure_logging:
|
||||||
logging.config.dictConfig(log_config or LOGGING_CONFIG_DEFAULTS)
|
logging.config.dictConfig(log_config or LOGGING_CONFIG_DEFAULTS)
|
||||||
@ -161,7 +156,6 @@ class Sanic(BaseSanic):
|
|||||||
self.is_running = False
|
self.is_running = False
|
||||||
self.is_stopping = False
|
self.is_stopping = False
|
||||||
self.listeners: Dict[str, List[ListenerType]] = defaultdict(list)
|
self.listeners: Dict[str, List[ListenerType]] = defaultdict(list)
|
||||||
self.name = name
|
|
||||||
self.named_request_middleware: Dict[str, Deque[MiddlewareType]] = {}
|
self.named_request_middleware: Dict[str, Deque[MiddlewareType]] = {}
|
||||||
self.named_response_middleware: Dict[str, Deque[MiddlewareType]] = {}
|
self.named_response_middleware: Dict[str, Deque[MiddlewareType]] = {}
|
||||||
self.request_class = request_class
|
self.request_class = request_class
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
from typing import Any, Tuple
|
from typing import Any, Tuple
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
|
||||||
|
from sanic.exceptions import SanicException
|
||||||
from sanic.mixins.exceptions import ExceptionMixin
|
from sanic.mixins.exceptions import ExceptionMixin
|
||||||
from sanic.mixins.listeners import ListenerMixin
|
from sanic.mixins.listeners import ListenerMixin
|
||||||
from sanic.mixins.middleware import MiddlewareMixin
|
from sanic.mixins.middleware import MiddlewareMixin
|
||||||
@ -8,6 +11,9 @@ from sanic.mixins.routes import RouteMixin
|
|||||||
from sanic.mixins.signals import SignalMixin
|
from sanic.mixins.signals import SignalMixin
|
||||||
|
|
||||||
|
|
||||||
|
VALID_NAME = re.compile(r"^[a-zA-Z][a-zA-Z0-9_\-]*$")
|
||||||
|
|
||||||
|
|
||||||
class BaseSanic(
|
class BaseSanic(
|
||||||
RouteMixin,
|
RouteMixin,
|
||||||
MiddlewareMixin,
|
MiddlewareMixin,
|
||||||
@ -17,7 +23,25 @@ class BaseSanic(
|
|||||||
):
|
):
|
||||||
__fake_slots__: Tuple[str, ...]
|
__fake_slots__: Tuple[str, ...]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs) -> None:
|
def __init__(self, name: str = None, *args, **kwargs) -> None:
|
||||||
|
class_name = self.__class__.__name__
|
||||||
|
|
||||||
|
if name is None:
|
||||||
|
raise SanicException(
|
||||||
|
f"{class_name} instance cannot be unnamed. "
|
||||||
|
"Please use Sanic(name='your_application_name') instead.",
|
||||||
|
)
|
||||||
|
|
||||||
|
if not VALID_NAME.match(name):
|
||||||
|
warn(
|
||||||
|
f"{class_name} instance named '{name}' uses a format that is"
|
||||||
|
f"deprecated. Starting in version 21.12, {class_name} objects "
|
||||||
|
"be named only using alphanumeric characters, _, or -.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.name = name
|
||||||
|
|
||||||
for base in BaseSanic.__bases__:
|
for base in BaseSanic.__bases__:
|
||||||
base.__init__(self, *args, **kwargs) # type: ignore
|
base.__init__(self, *args, **kwargs) # type: ignore
|
||||||
|
|
||||||
@ -36,6 +60,7 @@ class BaseSanic(
|
|||||||
f"Setting variables on {self.__class__.__name__} instances is "
|
f"Setting variables on {self.__class__.__name__} instances is "
|
||||||
"deprecated and will be removed in version 21.9. You should "
|
"deprecated and will be removed in version 21.9. You should "
|
||||||
f"change your {self.__class__.__name__} instance to use "
|
f"change your {self.__class__.__name__} instance to use "
|
||||||
f"instance.ctx.{name} instead."
|
f"instance.ctx.{name} instead.",
|
||||||
|
DeprecationWarning,
|
||||||
)
|
)
|
||||||
super().__setattr__(name, value)
|
super().__setattr__(name, value)
|
||||||
|
@ -62,19 +62,20 @@ class Blueprint(BaseSanic):
|
|||||||
"strict_slashes",
|
"strict_slashes",
|
||||||
"url_prefix",
|
"url_prefix",
|
||||||
"version",
|
"version",
|
||||||
|
"version_prefix",
|
||||||
"websocket_routes",
|
"websocket_routes",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str = None,
|
||||||
url_prefix: Optional[str] = None,
|
url_prefix: Optional[str] = None,
|
||||||
host: Optional[str] = None,
|
host: Optional[str] = None,
|
||||||
version: Optional[Union[int, str, float]] = None,
|
version: Optional[Union[int, str, float]] = None,
|
||||||
strict_slashes: Optional[bool] = None,
|
strict_slashes: Optional[bool] = None,
|
||||||
version_prefix: str = "/v",
|
version_prefix: str = "/v",
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__(name=name)
|
||||||
|
|
||||||
self._apps: Set[Sanic] = set()
|
self._apps: Set[Sanic] = set()
|
||||||
self.ctx = SimpleNamespace()
|
self.ctx = SimpleNamespace()
|
||||||
@ -82,7 +83,6 @@ class Blueprint(BaseSanic):
|
|||||||
self.host = host
|
self.host = host
|
||||||
self.listeners: Dict[str, List[ListenerType]] = {}
|
self.listeners: Dict[str, List[ListenerType]] = {}
|
||||||
self.middlewares: List[MiddlewareType] = []
|
self.middlewares: List[MiddlewareType] = []
|
||||||
self.name = name
|
|
||||||
self.routes: List[Route] = []
|
self.routes: List[Route] = []
|
||||||
self.statics: List[RouteHandler] = []
|
self.statics: List[RouteHandler] = []
|
||||||
self.strict_slashes = strict_slashes
|
self.strict_slashes = strict_slashes
|
||||||
|
@ -26,10 +26,11 @@ from sanic.views import CompositionView
|
|||||||
|
|
||||||
|
|
||||||
class RouteMixin:
|
class RouteMixin:
|
||||||
|
name: str
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs) -> None:
|
def __init__(self, *args, **kwargs) -> None:
|
||||||
self._future_routes: Set[FutureRoute] = set()
|
self._future_routes: Set[FutureRoute] = set()
|
||||||
self._future_statics: Set[FutureStatic] = set()
|
self._future_statics: Set[FutureStatic] = set()
|
||||||
self.name = ""
|
|
||||||
self.strict_slashes: Optional[bool] = False
|
self.strict_slashes: Optional[bool] = False
|
||||||
|
|
||||||
def _apply_route(self, route: FutureRoute) -> List[Route]:
|
def _apply_route(self, route: FutureRoute) -> List[Route]:
|
||||||
|
@ -389,7 +389,7 @@ def test_app_no_registry_env():
|
|||||||
|
|
||||||
|
|
||||||
def test_app_set_attribute_warning(app):
|
def test_app_set_attribute_warning(app):
|
||||||
with pytest.warns(UserWarning) as record:
|
with pytest.warns(DeprecationWarning) as record:
|
||||||
app.foo = 1
|
app.foo = 1
|
||||||
|
|
||||||
assert len(record) == 1
|
assert len(record) == 1
|
||||||
|
@ -41,3 +41,48 @@ def test_bp_repr_with_values(bp):
|
|||||||
'Blueprint(name="my_bp", url_prefix="/foo", host="example.com", '
|
'Blueprint(name="my_bp", url_prefix="/foo", host="example.com", '
|
||||||
"version=3, strict_slashes=True)"
|
"version=3, strict_slashes=True)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"name",
|
||||||
|
(
|
||||||
|
"something",
|
||||||
|
"some-thing",
|
||||||
|
"some_thing",
|
||||||
|
"Something",
|
||||||
|
"SomeThing",
|
||||||
|
"Some-Thing",
|
||||||
|
"Some_Thing",
|
||||||
|
"SomeThing123",
|
||||||
|
"something123",
|
||||||
|
"some-thing123",
|
||||||
|
"some_thing123",
|
||||||
|
"some-Thing123",
|
||||||
|
"some_Thing123",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_names_okay(name):
|
||||||
|
app = Sanic(name)
|
||||||
|
bp = Blueprint(name)
|
||||||
|
|
||||||
|
assert app.name == name
|
||||||
|
assert bp.name == name
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"name",
|
||||||
|
(
|
||||||
|
"123something",
|
||||||
|
"some thing",
|
||||||
|
"something!",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_names_not_okay(name):
|
||||||
|
with pytest.warns(DeprecationWarning):
|
||||||
|
app = Sanic(name)
|
||||||
|
|
||||||
|
with pytest.warns(DeprecationWarning):
|
||||||
|
bp = Blueprint(name)
|
||||||
|
|
||||||
|
assert app.name == name
|
||||||
|
assert bp.name == name
|
||||||
|
@ -1028,7 +1028,7 @@ def test_blueprint_registered_multiple_apps():
|
|||||||
|
|
||||||
def test_bp_set_attribute_warning():
|
def test_bp_set_attribute_warning():
|
||||||
bp = Blueprint("bp")
|
bp = Blueprint("bp")
|
||||||
with pytest.warns(UserWarning) as record:
|
with pytest.warns(DeprecationWarning) as record:
|
||||||
bp.foo = 1
|
bp.foo = 1
|
||||||
|
|
||||||
assert len(record) == 1
|
assert len(record) == 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user