From d6037fc0986855c9b0f189a13a651ad7f18dee63 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Wed, 7 Jul 2021 01:01:05 -0700 Subject: [PATCH 01/18] Initial version of Blueprint.copy, with a test case. --- sanic/blueprints.py | 18 ++++++++++++++++++ tests/test_blueprint_copy.py | 24 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/test_blueprint_copy.py diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 1fa24e889d..3afe9355e1 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -3,6 +3,7 @@ import asyncio from collections import defaultdict +from copy import deepcopy from types import SimpleNamespace from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Set, Union @@ -144,6 +145,23 @@ def signal(self, event: str, *args, **kwargs): kwargs["apply"] = False return super().signal(event, *args, **kwargs) + def copy( + self, + name: str, + url_prefix: str = "", + version: Optional[Union[int, str, float]] = None, + strict_slashes: Optional[bool] = None, + version_prefix: str = "/v", + ): + new_bp = deepcopy(self) + new_bp.name = name + new_bp.url_prefix = url_prefix + new_bp.version = version + new_bp.strict_slashes = strict_slashes + new_bp.version_prefix = version_prefix + + return new_bp + @staticmethod def group( *blueprints, diff --git a/tests/test_blueprint_copy.py b/tests/test_blueprint_copy.py new file mode 100644 index 0000000000..022c11604f --- /dev/null +++ b/tests/test_blueprint_copy.py @@ -0,0 +1,24 @@ +from copy import deepcopy + +from sanic import Blueprint, Sanic, blueprints, response +from sanic.response import text + + +def test_bp_copy(app: Sanic): + bp1 = Blueprint("test1", version=1) + + @bp1.route("/page") + def handle_request(request): + return text("Hello world!") + + bp2 = bp1.copy(name="test2", version=2) + assert id(bp1) != id(bp2) + + app.blueprint(bp1) + app.blueprint(bp2) + + _, response = app.test_client.get("/v1/page") + assert "Hello world!" in response.text + + _, response = app.test_client.get("/v2/page") + assert "Hello world!" in response.text From 69c1a8e2acf388154dec68d4087ff48802036da5 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Tue, 13 Jul 2021 12:48:28 -0700 Subject: [PATCH 02/18] Improve copy method in blueprint, adding possibiliy to keep original attribute values. --- sanic/blueprints.py | 33 +++++++++++++++++++++++++-------- sanic/helpers.py | 14 ++++++++++++++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 5238f1babd..fea4c84ee2 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -13,6 +13,7 @@ from sanic.base import BaseSanic from sanic.blueprint_group import BlueprintGroup from sanic.exceptions import SanicException +from sanic.helpers import _default from sanic.models.futures import FutureRoute, FutureStatic from sanic.models.handler_types import ( ListenerType, @@ -148,17 +149,33 @@ def signal(self, event: str, *args, **kwargs): def copy( self, name: str, - url_prefix: str = "", - version: Optional[Union[int, str, float]] = None, - strict_slashes: Optional[bool] = None, - version_prefix: str = "/v", + url_prefix: str = _default, + version: Optional[Union[int, str, float]] = _default, + version_prefix: str = _default, + strict_slashes: Optional[bool] = _default, ): + """ + Copy a blueprint instance with some optional parameters to + override the values of attributes in the old instance. + + :param name: unique name of the blueprint + :param url_prefix: URL to be prefixed before all route URLs + :param host: IP Address of FQDN for the sanic server to use. + :param version: Blueprint Version + :param version_prefix: the prefix of the version number shown in the URL. + :param strict_slashes: Enforce the API urls are requested with a + training */* + """ new_bp = deepcopy(self) new_bp.name = name - new_bp.url_prefix = url_prefix - new_bp.version = version - new_bp.strict_slashes = strict_slashes - new_bp.version_prefix = version_prefix + if url_prefix != _default: + new_bp.url_prefix = url_prefix + if version != _default: + new_bp.version = version + if strict_slashes != _default: + new_bp.strict_slashes = strict_slashes + if version_prefix != _default: + new_bp.version_prefix = version_prefix return new_bp diff --git a/sanic/helpers.py b/sanic/helpers.py index 15ae7bf297..87d51b53ac 100644 --- a/sanic/helpers.py +++ b/sanic/helpers.py @@ -155,3 +155,17 @@ def import_string(module_name, package=None): if ismodule(obj): return obj return obj() + + +class Default: + """ + It is used to replace `None` or `object()` as a sentinel + that represents a default value. Sometimes we want to set + a value to `None` so we cannot use `None` to represent the + default value, and `object()` is hard to be typed. + """ + + pass + + +_default = Default() From be1c09e7da928e1cfc1cc003d1a46bc46111cc66 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Tue, 13 Jul 2021 12:51:56 -0700 Subject: [PATCH 03/18] Fix typing --- sanic/blueprints.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index fea4c84ee2..da26e3ddfa 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -13,7 +13,7 @@ from sanic.base import BaseSanic from sanic.blueprint_group import BlueprintGroup from sanic.exceptions import SanicException -from sanic.helpers import _default +from sanic.helpers import Default, _default from sanic.models.futures import FutureRoute, FutureStatic from sanic.models.handler_types import ( ListenerType, @@ -149,10 +149,10 @@ def signal(self, event: str, *args, **kwargs): def copy( self, name: str, - url_prefix: str = _default, - version: Optional[Union[int, str, float]] = _default, - version_prefix: str = _default, - strict_slashes: Optional[bool] = _default, + url_prefix: Optional[Union[str, Default]] = _default, + version: Optional[Union[int, str, float, Default]] = _default, + version_prefix: Optional[Union[str, Default]] = _default, + strict_slashes: Optional[Union[bool, Default]] = _default, ): """ Copy a blueprint instance with some optional parameters to From 0a8ee7be9d951b21f454c9d82b843838914e6717 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Tue, 13 Jul 2021 13:03:05 -0700 Subject: [PATCH 04/18] Fix typing 2 --- sanic/blueprints.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index da26e3ddfa..99453d1f34 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -151,11 +151,11 @@ def copy( name: str, url_prefix: Optional[Union[str, Default]] = _default, version: Optional[Union[int, str, float, Default]] = _default, - version_prefix: Optional[Union[str, Default]] = _default, + version_prefix: Union[str, Default] = _default, strict_slashes: Optional[Union[bool, Default]] = _default, ): """ - Copy a blueprint instance with some optional parameters to + Copy a blueprint instance with some optional parameters to override the values of attributes in the old instance. :param name: unique name of the blueprint @@ -168,13 +168,14 @@ def copy( """ new_bp = deepcopy(self) new_bp.name = name - if url_prefix != _default: + + if not isinstance(url_prefix, Default): new_bp.url_prefix = url_prefix - if version != _default: + if not isinstance(version, Default): new_bp.version = version - if strict_slashes != _default: + if not isinstance(strict_slashes, Default): new_bp.strict_slashes = strict_slashes - if version_prefix != _default: + if not isinstance(version_prefix, Default): new_bp.version_prefix = version_prefix return new_bp From 762c25e21a5b96ec6fa181efc445b462b7695fb4 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Tue, 13 Jul 2021 16:50:35 -0700 Subject: [PATCH 05/18] doc fix --- sanic/blueprints.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 5aec987ab5..836cb6c7e1 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -42,7 +42,7 @@ class Blueprint(BaseSanic): :param host: IP Address of FQDN for the sanic server to use. :param version: Blueprint Version :param strict_slashes: Enforce the API urls are requested with a - training */* + trailing */* """ __fake_slots__ = ( @@ -160,11 +160,10 @@ def copy( :param name: unique name of the blueprint :param url_prefix: URL to be prefixed before all route URLs - :param host: IP Address of FQDN for the sanic server to use. :param version: Blueprint Version :param version_prefix: the prefix of the version number shown in the URL. :param strict_slashes: Enforce the API urls are requested with a - training */* + trailing */* """ new_bp = deepcopy(self) new_bp.name = name From 80029d636dfa9073c67d2724678108ad923ba049 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Tue, 20 Jul 2021 20:07:37 -0500 Subject: [PATCH 06/18] Add reset method for init and reset bp instance; update copy method --- sanic/blueprints.py | 49 ++++++++++++++++++++++++++++++------ tests/test_blueprint_copy.py | 17 +++++++++++-- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 836cb6c7e1..40cef6fb2d 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -79,14 +79,9 @@ def __init__( ): super().__init__(name=name) - self._apps: Set[Sanic] = set() self.ctx = SimpleNamespace() - self.exceptions: List[RouteHandler] = [] self.host = host - self.listeners: Dict[str, List[ListenerType]] = {} - self.middlewares: List[MiddlewareType] = [] - self.routes: List[Route] = [] - self.statics: List[RouteHandler] = [] + self.reset() self.strict_slashes = strict_slashes self.url_prefix = ( url_prefix[:-1] @@ -95,7 +90,6 @@ def __init__( ) self.version = version self.version_prefix = version_prefix - self.websocket_routes: List[Route] = [] def __repr__(self) -> str: args = ", ".join( @@ -153,6 +147,8 @@ def copy( version: Optional[Union[int, str, float, Default]] = _default, version_prefix: Union[str, Default] = _default, strict_slashes: Optional[Union[bool, Default]] = _default, + with_registration: bool = True, + with_ctx: bool = False, ): """ Copy a blueprint instance with some optional parameters to @@ -164,7 +160,22 @@ def copy( :param version_prefix: the prefix of the version number shown in the URL. :param strict_slashes: Enforce the API urls are requested with a trailing */* + :param with_registration: whether register new blueprint instance with + sanic apps that were registered with the old instance or not. + :param with_ctx: whether `ctx` will be copied or not. """ + + attrs_backup = { + "_apps": self._apps, + "routes": self.routes, + "websocket_routes": self.websocket_routes, + "middlewares": self.middlewares, + "exceptions": self.exceptions, + "listeners": self.listeners, + "statics": self.statics, + } + + self.reset() new_bp = deepcopy(self) new_bp.name = name @@ -177,6 +188,21 @@ def copy( if not isinstance(version_prefix, Default): new_bp.version_prefix = version_prefix + for key, value in attrs_backup.items(): + setattr(self, key, value) + + if with_registration: + if len(new_bp._future_statics) > 0 and len(self._apps) > 0: + raise Exception( + "Static routes registered with the old blueprint instance, " + "cannot be registered again." + ) + for app in self._apps: + app.blueprint(new_bp) + + if not with_ctx: + new_bp.ctx = SimpleNamespace() + return new_bp @staticmethod @@ -329,6 +355,15 @@ async def dispatch(self, *args, **kwargs): *[app.dispatch(*args, **kwargs) for app in self.apps] ) + def reset(self): + self._apps: Set[Sanic] = set() + self.exceptions: List[RouteHandler] = [] + self.listeners: Dict[str, List[ListenerType]] = {} + self.middlewares: List[MiddlewareType] = [] + self.routes: List[Route] = [] + self.statics: List[RouteHandler] = [] + self.websocket_routes: List[Route] = [] + def event(self, event: str, timeout: Optional[Union[int, float]] = None): events = set() for app in self.apps: diff --git a/tests/test_blueprint_copy.py b/tests/test_blueprint_copy.py index 022c11604f..4bb7ccab2e 100644 --- a/tests/test_blueprint_copy.py +++ b/tests/test_blueprint_copy.py @@ -5,20 +5,33 @@ def test_bp_copy(app: Sanic): - bp1 = Blueprint("test1", version=1) + bp1 = Blueprint("test_bp1", version=1) @bp1.route("/page") def handle_request(request): return text("Hello world!") - bp2 = bp1.copy(name="test2", version=2) + bp2 = bp1.copy(name="test_bp2", version=2) assert id(bp1) != id(bp2) app.blueprint(bp1) app.blueprint(bp2) + bp3 = bp1.copy(name="test_bp3", version=3, with_registration=True) + bp4 = bp1.copy(name="test_bp4", version=4, with_ctx=True) + bp5 = bp1.copy(name="test_bp5", version=5, with_registration=False) + app.blueprint(bp5) _, response = app.test_client.get("/v1/page") assert "Hello world!" in response.text _, response = app.test_client.get("/v2/page") assert "Hello world!" in response.text + + _, response = app.test_client.get("/v3/page") + assert "Hello world!" in response.text + + _, response = app.test_client.get("/v4/page") + assert "Hello world!" in response.text + + _, response = app.test_client.get("/v5/page") + assert "Hello world!" in response.text From 0e90d9cdb603a1d4565a018eda95d00fd3a3c152 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Fri, 6 Aug 2021 13:27:19 -0500 Subject: [PATCH 07/18] Move reset method to above; try fix lint --- sanic/blueprints.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 40cef6fb2d..49a91e568e 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -91,6 +91,15 @@ def __init__( self.version = version self.version_prefix = version_prefix + def reset(self): + self._apps: Set[Sanic] = set() + self.exceptions: List[RouteHandler] = [] + self.listeners: Dict[str, List[ListenerType]] = {} + self.middlewares: List[MiddlewareType] = [] + self.routes: List[Route] = [] + self.statics: List[RouteHandler] = [] + self.websocket_routes: List[Route] = [] + def __repr__(self) -> str: args = ", ".join( [ @@ -157,7 +166,8 @@ def copy( :param name: unique name of the blueprint :param url_prefix: URL to be prefixed before all route URLs :param version: Blueprint Version - :param version_prefix: the prefix of the version number shown in the URL. + :param version_prefix: the prefix of the version number shown in the + URL. :param strict_slashes: Enforce the API urls are requested with a trailing */* :param with_registration: whether register new blueprint instance with @@ -194,8 +204,8 @@ def copy( if with_registration: if len(new_bp._future_statics) > 0 and len(self._apps) > 0: raise Exception( - "Static routes registered with the old blueprint instance, " - "cannot be registered again." + "Static routes registered with the old blueprint instance," + " cannot be registered again." ) for app in self._apps: app.blueprint(new_bp) @@ -355,15 +365,6 @@ async def dispatch(self, *args, **kwargs): *[app.dispatch(*args, **kwargs) for app in self.apps] ) - def reset(self): - self._apps: Set[Sanic] = set() - self.exceptions: List[RouteHandler] = [] - self.listeners: Dict[str, List[ListenerType]] = {} - self.middlewares: List[MiddlewareType] = [] - self.routes: List[Route] = [] - self.statics: List[RouteHandler] = [] - self.websocket_routes: List[Route] = [] - def event(self, event: str, timeout: Optional[Union[int, float]] = None): events = set() for app in self.apps: From 45dd2a08ff487a5f30fb9ac516d4dcf597daedad Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Fri, 6 Aug 2021 13:28:14 -0500 Subject: [PATCH 08/18] Update test bp copy --- tests/test_blueprint_copy.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_blueprint_copy.py b/tests/test_blueprint_copy.py index 4bb7ccab2e..9d87b4125e 100644 --- a/tests/test_blueprint_copy.py +++ b/tests/test_blueprint_copy.py @@ -19,6 +19,9 @@ def handle_request(request): bp3 = bp1.copy(name="test_bp3", version=3, with_registration=True) bp4 = bp1.copy(name="test_bp4", version=4, with_ctx=True) bp5 = bp1.copy(name="test_bp5", version=5, with_registration=False) + assert id(bp2) != id(bp3) + assert id(bp3) != id(bp4) + assert id(bp4) != id(bp5) app.blueprint(bp5) _, response = app.test_client.get("/v1/page") From d072ae3ae49a024d7a8b463f87fad72ef5e954cf Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Fri, 6 Aug 2021 13:28:58 -0500 Subject: [PATCH 09/18] make pretty --- sanic/blueprints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 49a91e568e..bd029c3b46 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -166,7 +166,7 @@ def copy( :param name: unique name of the blueprint :param url_prefix: URL to be prefixed before all route URLs :param version: Blueprint Version - :param version_prefix: the prefix of the version number shown in the + :param version_prefix: the prefix of the version number shown in the URL. :param strict_slashes: Enforce the API urls are requested with a trailing */* From 9c8f2c619a59f167cee61274dfde6f13e79e08d6 Mon Sep 17 00:00:00 2001 From: Zhiwei Date: Sat, 7 Aug 2021 16:03:58 -0500 Subject: [PATCH 10/18] Fix if statement logic Co-authored-by: Adam Hopkins --- sanic/blueprints.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index bd029c3b46..6307d3fa6b 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -201,8 +201,8 @@ def copy( for key, value in attrs_backup.items(): setattr(self, key, value) - if with_registration: - if len(new_bp._future_statics) > 0 and len(self._apps) > 0: + if with_registration and self._apps: + if new_bp._future_statics: raise Exception( "Static routes registered with the old blueprint instance," " cannot be registered again." From 1022a46dbea931360306f392c1f667d12b2a5fc0 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Sat, 7 Aug 2021 16:41:32 -0500 Subject: [PATCH 11/18] Change Exception to SanicException --- sanic/blueprints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 6307d3fa6b..248c787206 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -203,7 +203,7 @@ def copy( if with_registration and self._apps: if new_bp._future_statics: - raise Exception( + raise SanicException( "Static routes registered with the old blueprint instance," " cannot be registered again." ) From 3238aec55aec06a2b7187927fa24d5fe6a9ab594 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Sun, 8 Aug 2021 04:29:41 -0500 Subject: [PATCH 12/18] Move reset to the front of copy method. --- sanic/blueprints.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 248c787206..d8520f992a 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -91,15 +91,6 @@ def __init__( self.version = version self.version_prefix = version_prefix - def reset(self): - self._apps: Set[Sanic] = set() - self.exceptions: List[RouteHandler] = [] - self.listeners: Dict[str, List[ListenerType]] = {} - self.middlewares: List[MiddlewareType] = [] - self.routes: List[Route] = [] - self.statics: List[RouteHandler] = [] - self.websocket_routes: List[Route] = [] - def __repr__(self) -> str: args = ", ".join( [ @@ -149,6 +140,15 @@ def signal(self, event: str, *args, **kwargs): kwargs["apply"] = False return super().signal(event, *args, **kwargs) + def reset(self): + self._apps: Set[Sanic] = set() + self.exceptions: List[RouteHandler] = [] + self.listeners: Dict[str, List[ListenerType]] = {} + self.middlewares: List[MiddlewareType] = [] + self.routes: List[Route] = [] + self.statics: List[RouteHandler] = [] + self.websocket_routes: List[Route] = [] + def copy( self, name: str, From fb41b3e0b21281827f8924383f56daf759ab3437 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Sun, 8 Aug 2021 13:40:59 -0500 Subject: [PATCH 13/18] call reset at the beginning --- sanic/blueprints.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index d8520f992a..098fd48f94 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -78,10 +78,9 @@ def __init__( version_prefix: str = "/v", ): super().__init__(name=name) - + self.reset() self.ctx = SimpleNamespace() self.host = host - self.reset() self.strict_slashes = strict_slashes self.url_prefix = ( url_prefix[:-1] From 4ebb773e1af07792d36a9fba568fe32893867d5d Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Mon, 9 Aug 2021 02:46:04 -0500 Subject: [PATCH 14/18] Update copy blueprint tests --- tests/test_blueprint_copy.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/test_blueprint_copy.py b/tests/test_blueprint_copy.py index 9d87b4125e..bad2c85256 100644 --- a/tests/test_blueprint_copy.py +++ b/tests/test_blueprint_copy.py @@ -6,6 +6,8 @@ def test_bp_copy(app: Sanic): bp1 = Blueprint("test_bp1", version=1) + bp1.ctx.test = 1 + assert hasattr(bp1.ctx, "test") @bp1.route("/page") def handle_request(request): @@ -13,15 +15,26 @@ def handle_request(request): bp2 = bp1.copy(name="test_bp2", version=2) assert id(bp1) != id(bp2) + assert bp1._apps == bp2._apps == set() + assert not hasattr(bp2.ctx, "test") app.blueprint(bp1) app.blueprint(bp2) + bp3 = bp1.copy(name="test_bp3", version=3, with_registration=True) + assert id(bp1) != id(bp3) + assert bp1._apps == bp3._apps and bp3._apps + assert not hasattr(bp3.ctx, "test") + bp4 = bp1.copy(name="test_bp4", version=4, with_ctx=True) + assert id(bp1) != id(bp4) + assert bp4.ctx.test == 1 + bp5 = bp1.copy(name="test_bp5", version=5, with_registration=False) - assert id(bp2) != id(bp3) - assert id(bp3) != id(bp4) - assert id(bp4) != id(bp5) + assert id(bp1) != id(bp5) + assert not bp5._apps + assert bp1._apps != set() + app.blueprint(bp5) _, response = app.test_client.get("/v1/page") From e04cd750c5052ebd0f62be01133c5d9dfb63b8f9 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Mon, 9 Aug 2021 02:57:58 -0500 Subject: [PATCH 15/18] Add more attrs check in test cases --- tests/test_blueprint_copy.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_blueprint_copy.py b/tests/test_blueprint_copy.py index bad2c85256..d7f5032dcb 100644 --- a/tests/test_blueprint_copy.py +++ b/tests/test_blueprint_copy.py @@ -17,6 +17,11 @@ def handle_request(request): assert id(bp1) != id(bp2) assert bp1._apps == bp2._apps == set() assert not hasattr(bp2.ctx, "test") + assert len(bp2._future_exceptions) == len(bp1._future_exceptions) + assert len(bp2._future_listeners) == len(bp1._future_listeners) + assert len(bp2._future_middleware) == len(bp1._future_middleware) + assert len(bp2._future_routes) == len(bp1._future_routes) + assert len(bp2._future_signals) == len(bp1._future_signals) app.blueprint(bp1) app.blueprint(bp2) From 903de13c97bb13615818a4a7e1c51cbc5cc7caf4 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Mon, 9 Aug 2021 12:24:11 -0500 Subject: [PATCH 16/18] Add version_prefix override test --- tests/test_blueprint_copy.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_blueprint_copy.py b/tests/test_blueprint_copy.py index d7f5032dcb..c5daf0ee4b 100644 --- a/tests/test_blueprint_copy.py +++ b/tests/test_blueprint_copy.py @@ -56,3 +56,15 @@ def handle_request(request): _, response = app.test_client.get("/v5/page") assert "Hello world!" in response.text + + bp6 = bp1.copy( + name="test_bp6", + version=6, + with_registration=True, + version_prefix="/version", + ) + assert bp6._apps + assert bp6.version_prefix == "/version" + + _, response = app.test_client.get("/version6/page") + assert "Hello world!" in response.text From 8588c77842eac2aa6bdb6c778b3c00b86dfb77e7 Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Mon, 9 Aug 2021 20:58:24 +0300 Subject: [PATCH 17/18] Update sanic/blueprints.py --- sanic/blueprints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 098fd48f94..dfc8240cf0 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -171,7 +171,7 @@ def copy( trailing */* :param with_registration: whether register new blueprint instance with sanic apps that were registered with the old instance or not. - :param with_ctx: whether `ctx` will be copied or not. + :param with_ctx: whether ``ctx`` will be copied or not. """ attrs_backup = { From 0c2d3ec4bfae652d89bf6770fb36cd28c59033e3 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Mon, 9 Aug 2021 15:05:12 -0500 Subject: [PATCH 18/18] Fix --- tests/test_blueprint_copy.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/test_blueprint_copy.py b/tests/test_blueprint_copy.py index c5daf0ee4b..033e2e2041 100644 --- a/tests/test_blueprint_copy.py +++ b/tests/test_blueprint_copy.py @@ -42,6 +42,15 @@ def handle_request(request): app.blueprint(bp5) + bp6 = bp1.copy( + name="test_bp6", + version=6, + with_registration=True, + version_prefix="/version", + ) + assert bp6._apps + assert bp6.version_prefix == "/version" + _, response = app.test_client.get("/v1/page") assert "Hello world!" in response.text @@ -57,14 +66,5 @@ def handle_request(request): _, response = app.test_client.get("/v5/page") assert "Hello world!" in response.text - bp6 = bp1.copy( - name="test_bp6", - version=6, - with_registration=True, - version_prefix="/version", - ) - assert bp6._apps - assert bp6.version_prefix == "/version" - _, response = app.test_client.get("/version6/page") assert "Hello world!" in response.text