Repository: huge-success/sanic
Pull request #1880 (2020-06-28 11:30:01)

Add handler names for websockets for url_for usage
Accomplishes what #1696 set out to do, but was unable after change to #1853 

codecov[bot]: # [Codecov](https://codecov.io/gh/huge-success/sanic/pull/1880?src=pr&el=h1) Report
> Merging [#1880](https://codecov.io/gh/huge-success/sanic/pull/1880?src=pr&el=desc) into [master](https://codecov.io/gh/huge-success/sanic/commit/761eef7d967d7930bef3f3edcecb9d977fb17e3d&el=desc) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/huge-success/sanic/pull/1880/graphs/tree.svg?width=650&height=150&src=pr&token=NqLbJHUqoR)](https://codecov.io/gh/huge-success/sanic/pull/1880?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master    #1880   +/-   ##
=======================================
  Coverage   91.70%   91.70%           
=======================================
  Files          27       27           
  Lines        3000     3001    +1     
  Branches      544      544           
=======================================
+ Hits         2751     2752    +1     
  Misses        171      171           
  Partials       78       78           
```


| [Impacted Files](https://codecov.io/gh/huge-success/sanic/pull/1880?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [sanic/blueprints.py](https://codecov.io/gh/huge-success/sanic/pull/1880/diff?src=pr&el=tree#diff-c2FuaWMvYmx1ZXByaW50cy5weQ==) | `95.97% <100.00%> (+0.02%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/huge-success/sanic/pull/1880?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/huge-success/sanic/pull/1880?src=pr&el=footer). Last update [761eef7...ccc4e00](https://codecov.io/gh/huge-success/sanic/pull/1880?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/sanic/blueprints.py b/sanic/blueprints.py
index 42599342..cf5eee5e 100644
--- a/sanic/blueprints.py
+++ b/sanic/blueprints.py
@@ -283,6 +283,13 @@ class Blueprint:
             strict_slashes = self.strict_slashes
 
         def decorator(handler):
+            nonlocal uri
+            nonlocal host
+            nonlocal strict_slashes
+            nonlocal version
+            nonlocal name
+
+            name = f"{self.name}.{name or handler.__name__}"
             route = FutureRoute(
                 handler, uri, [], host, strict_slashes, False, version, name
             )


Test patch:
diff --git a/tests/test_blueprints.py b/tests/test_blueprints.py
index 00bee043..4978b51e 100644
--- a/tests/test_blueprints.py
+++ b/tests/test_blueprints.py
@@ -253,7 +253,11 @@ def test_several_bp_with_host(app):
 
 
 def test_bp_with_host_list(app):
-    bp = Blueprint("test_bp_host", url_prefix="/test1", host=["example.com", "sub.example.com"])
+    bp = Blueprint(
+        "test_bp_host",
+        url_prefix="/test1",
+        host=["example.com", "sub.example.com"],
+    )
 
     @bp.route("/")
     def handler1(request):
@@ -279,8 +283,16 @@ def test_bp_with_host_list(app):
 
 
 def test_several_bp_with_host_list(app):
-    bp = Blueprint("test_text", url_prefix="/test", host=["example.com", "sub.example.com"])
-    bp2 = Blueprint("test_text2", url_prefix="/test", host=["sub1.example.com", "sub2.example.com"])
+    bp = Blueprint(
+        "test_text",
+        url_prefix="/test",
+        host=["example.com", "sub.example.com"],
+    )
+    bp2 = Blueprint(
+        "test_text2",
+        url_prefix="/test",
+        host=["sub1.example.com", "sub2.example.com"],
+    )
 
     @bp.route("/")
     def handler(request):
diff --git a/tests/test_multiprocessing.py b/tests/test_multiprocessing.py
index ef1db52f..59be2df7 100644
--- a/tests/test_multiprocessing.py
+++ b/tests/test_multiprocessing.py
@@ -88,10 +88,11 @@ def test_pickle_app_with_bp(app, protocol):
     assert up_p_app.is_request_stream is False
     assert response.text == "Hello"
 
+
 @pytest.mark.parametrize("protocol", [3, 4])
 def test_pickle_app_with_static(app, protocol):
     app.route("/")(handler)
-    app.static('/static', "/tmp/static")
+    app.static("/static", "/tmp/static")
     p_app = pickle.dumps(app, protocol=protocol)
     del app
     up_p_app = pickle.loads(p_app)
diff --git a/tests/test_reloader.py b/tests/test_reloader.py
index 5eccb801..50798833 100644
--- a/tests/test_reloader.py
+++ b/tests/test_reloader.py
@@ -1,8 +1,8 @@
 import os
 import secrets
 import sys
-from contextlib import suppress
 
+from contextlib import suppress
 from subprocess import PIPE, Popen, TimeoutExpired
 from tempfile import TemporaryDirectory
 from textwrap import dedent
@@ -23,16 +23,20 @@ try:
 except ImportError:
     flags = 0
 
+
 def terminate(proc):
     if flags:
         proc.send_signal(CTRL_BREAK_EVENT)
     else:
         proc.terminate()
 
+
 def write_app(filename, **runargs):
     text = secrets.token_urlsafe()
     with open(filename, "w") as f:
-        f.write(dedent(f"""\
+        f.write(
+            dedent(
+                f"""\
             import os
             from sanic import Sanic
 
@@ -45,9 +49,11 @@ def write_app(filename, **runargs):
             if __name__ == "__main__":
                 app.run(**{runargs!r})
             """
-        ))
+            )
+        )
     return text
 
+
 def scanner(proc):
     for line in proc.stdout:
         line = line.decode().strip()
@@ -59,14 +65,26 @@ def scanner(proc):
 argv = dict(
     script=[sys.executable, "reloader.py"],
     module=[sys.executable, "-m", "reloader"],
-    sanic=[sys.executable, "-m", "sanic", "--port", "42104", "--debug", "reloader.app"],
+    sanic=[
+        sys.executable,
+        "-m",
+        "sanic",
+        "--port",
+        "42104",
+        "--debug",
+        "reloader.app",
+    ],
 )
 
-@pytest.mark.parametrize("runargs, mode", [
-    (dict(port=42102, auto_reload=True), "script"),
-    (dict(port=42103, debug=True), "module"),
-    (dict(), "sanic"),
-])
+
+@pytest.mark.parametrize(
+    "runargs, mode",
+    [
+        (dict(port=42102, auto_reload=True), "script"),
+        (dict(port=42103, debug=True), "module"),
+        (dict(), "sanic"),
+    ],
+)
 async def test_reloader_live(runargs, mode):
     with TemporaryDirectory() as tmpdir:
         filename = os.path.join(tmpdir, "reloader.py")
diff --git a/tests/test_response.py b/tests/test_response.py
index d3ed294b..625317d5 100644
--- a/tests/test_response.py
+++ b/tests/test_response.py
@@ -614,7 +614,7 @@ def test_response_body_bytes_deprecated(app):
     with warnings.catch_warnings(record=True) as w:
         warnings.simplefilter("always")
 
-        HTTPResponse(body_bytes=b'bytes')
+        HTTPResponse(body_bytes=b"bytes")
 
         assert len(w) == 1
         assert issubclass(w[0].category, DeprecationWarning)
diff --git a/tests/test_url_for.py b/tests/test_url_for.py
index e77d6d82..2d692f2e 100644
--- a/tests/test_url_for.py
+++ b/tests/test_url_for.py
@@ -1,3 +1,8 @@
+import asyncio
+
+from sanic.blueprints import Blueprint
+
+
 def test_routes_with_host(app):
     @app.route("/")
     @app.route("/", name="hostindex", host="example.com")
@@ -13,3 +18,46 @@ def test_routes_with_host(app):
         app.url_for("hostpath", _external=True)
         == "http://path.example.com/path"
     )
+
+
+def test_websocket_bp_route_name(app):
+    """Tests that blueprint websocket route is named."""
+    event = asyncio.Event()
+    bp = Blueprint("test_bp", url_prefix="/bp")
+
+    @bp.get("/main")
+    async def main(request):
+        ...
+
+    @bp.websocket("/route")
+    async def test_route(request, ws):
+        event.set()
+
+    @bp.websocket("/route2")
+    async def test_route2(request, ws):
+        event.set()
+
+    @bp.websocket("/route3", name="foobar_3")
+    async def test_route3(request, ws):
+        event.set()
+
+    app.blueprint(bp)
+
+    uri = app.url_for("test_bp.main")
+    assert uri == "/bp/main"
+
+    uri = app.url_for("test_bp.test_route")
+    assert uri == "/bp/route"
+    request, response = app.test_client.websocket(uri)
+    assert response.opened is True
+    assert event.is_set()
+
+    event.clear()
+    uri = app.url_for("test_bp.test_route2")
+    assert uri == "/bp/route2"
+    request, response = app.test_client.websocket(uri)
+    assert response.opened is True
+    assert event.is_set()
+
+    uri = app.url_for("test_bp.foobar_3")
+    assert uri == "/bp/route3"