From 79b05df22ff7ed7eb973a1f70475a58e50eb6852 Mon Sep 17 00:00:00 2001 From: artcg Date: Sat, 20 Mar 2021 17:50:07 +0100 Subject: [PATCH 1/3] fix?: recursion error on Sanic subclass init --- sanic/base.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sanic/base.py b/sanic/base.py index 5170614950..185449dfa9 100644 --- a/sanic/base.py +++ b/sanic/base.py @@ -16,9 +16,7 @@ def __init__(self, *args, **kwargs): nonlocal init nonlocal name - bases = [ - b for base in type(self).__bases__ for b in base.__bases__ - ] + bases = BaseSanic.__bases__ for base in bases: base.__init__(self, *args, **kwargs) From f022ad3e98e7db476bbbdd6536d510fcaa873d24 Mon Sep 17 00:00:00 2001 From: artcg Date: Sun, 21 Mar 2021 02:32:26 +0100 Subject: [PATCH 2/3] tests: add test case for sanic subclass initialisation --- tests/test_app.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/test_app.py b/tests/test_app.py index bfe7900c23..f096496a47 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -405,3 +405,10 @@ def test_app_set_context(app): retrieved = Sanic.get_app(app.name) assert retrieved.ctx.foo == 1 + + +def test_subclass_initialisation(): + class CustomSanic(Sanic): + pass + + CustomSanic("test_subclass_initialisation") From 1a3820950ece5e0150f7464fedecfe1c350f671b Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Sun, 21 Mar 2021 09:45:58 +0200 Subject: [PATCH 3/3] Remove BaseSanic metaclass --- sanic/base.py | 25 ++++--------------------- sanic/blueprints.py | 1 + 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/sanic/base.py b/sanic/base.py index 185449dfa9..368288c408 100644 --- a/sanic/base.py +++ b/sanic/base.py @@ -8,36 +8,19 @@ from sanic.mixins.signals import SignalMixin -class Base(type): - def __new__(cls, name, bases, attrs): - init = attrs.get("__init__") - - def __init__(self, *args, **kwargs): - nonlocal init - nonlocal name - - bases = BaseSanic.__bases__ - - for base in bases: - base.__init__(self, *args, **kwargs) - - if init: - init(self, *args, **kwargs) - - attrs["__init__"] = __init__ - return type.__new__(cls, name, bases, attrs) - - class BaseSanic( RouteMixin, MiddlewareMixin, ListenerMixin, ExceptionMixin, SignalMixin, - metaclass=Base, ): __fake_slots__: Tuple[str, ...] + def __init__(self, *args, **kwargs) -> None: + for base in BaseSanic.__bases__: + base.__init__(self, *args, **kwargs) # type: ignore + def __str__(self) -> str: return f"<{self.__class__.__name__} {self.name}>" diff --git a/sanic/blueprints.py b/sanic/blueprints.py index f8b0323c00..85b60ddc18 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -73,6 +73,7 @@ def __init__( version: Optional[int] = None, strict_slashes: Optional[bool] = None, ): + super().__init__() self._apps: Set[Sanic] = set() self.ctx = SimpleNamespace()