From 7af2e62ff14ad1af95abe8ce32816b1709239e1a Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Thu, 16 Dec 2021 10:08:31 +0100 Subject: [PATCH 01/15] change github issues template --- .github/ISSUE_TEMPLATE/2-bug-report.md | 53 --------------- .github/ISSUE_TEMPLATE/3-feature-request.md | 33 ---------- .github/ISSUE_TEMPLATE/bug-report.yml | 73 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature-request.yml | 36 ++++++++++ 4 files changed, 109 insertions(+), 86 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/2-bug-report.md delete mode 100644 .github/ISSUE_TEMPLATE/3-feature-request.md create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yml create mode 100644 .github/ISSUE_TEMPLATE/feature-request.yml diff --git a/.github/ISSUE_TEMPLATE/2-bug-report.md b/.github/ISSUE_TEMPLATE/2-bug-report.md deleted file mode 100644 index 7c11706b7..000000000 --- a/.github/ISSUE_TEMPLATE/2-bug-report.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -name: Bug report -about: Report a bug to help improve this project ---- - -### Checklist - - - -- [ ] The bug is reproducible against the latest release and/or `master`. -- [ ] There are no similar issues or pull requests to fix it yet. - -### Describe the bug - - - -### To reproduce - - - -### Expected behavior - - - -### Actual behavior - - - -### Debugging material - - - -### Environment - -- OS: -- Python version: -- Starlette version: - -### Additional context - - diff --git a/.github/ISSUE_TEMPLATE/3-feature-request.md b/.github/ISSUE_TEMPLATE/3-feature-request.md deleted file mode 100644 index 97336f516..000000000 --- a/.github/ISSUE_TEMPLATE/3-feature-request.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project. ---- - -### Checklist - - - -- [ ] There are no similar issues or pull requests for this yet. -- [ ] I discussed this idea on the [community chat](https://gitter.im/encode/community) and feedback is positive. - -### Is your feature related to a problem? Please describe. - - - -## Describe the solution you would like. - - - -## Describe alternatives you considered - - - -## Additional context - - diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 000000000..966090b2f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,73 @@ +name: Bug report +description: Report a bug to help improve this project +body: + - type: checkboxes + id: checks + attributes: + label: Checklist + description: Please make sure you check all these items before submitting your bug report. + options: + - label: The bug is reproducible against the latest release or `master`. + required: true + - label: There are no similar issues or pull requests to fix it yet. + required: true + - type: textarea + id: describe + attributes: + label: Describe the bug + description: A clear and concise description of what the bug is. + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps to reproduce the bug + description: | + Provide a *minimal* example with steps to reproduce the bug locally. + NOTE: try to keep any external dependencies *at an absolute minimum*. + In other words, remove anything that doesn't make the bug go away. + validations: + required: false + - type: textarea + id: expected + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen. + validations: + required: false + - type: textarea + id: actual + attributes: + label: Actual behavior + description: A clear and concise description of what actually happened. + validations: + required: false + - type: textarea + id: notes + attributes: + label: Debugging material + description: | + Any tracebacks, screenshots, etc. that can help understanding the problem. + NOTE: + - Please list tracebacks in full (don't truncate them). + - Consider using `
` to make tracebacks/logs collapsible if they're very large (see https://gist.github.com/ericclemmons/b146fe5da72ca1f706b2ef72a20ac39d). + validations: + required: false + - type: textarea + id: environment + attributes: + label: Environment + description: Describe your environment. + placeholder: | + - OS / Python / Starlette version. + validations: + required: true + - type: textarea + id: additional + attributes: + label: Additional context + description: | + Any additional information that can help understanding the problem. + Eg. linked issues, or a description of what you were trying to achieve. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 000000000..baf791041 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,36 @@ +name: Feature Request +description: Suggest an idea for a feature that you would like to see in Starlette +body: + - type: checkboxes + id: checks + attributes: + label: Checklist + description: Please make sure you check all these items before submitting your feature request. + options: + - label: There are no similar issues or pull requests for this yet. + required: true + - label: I discussed this idea on the [community chat](https://gitter.im/encode/community) and feedback is positive. + required: true + - type: textarea + id: problem + attributes: + label: Is your feature related to a problem? Please describe. + description: A clear and concise description of what you are trying to achieve. + placeholder: I want to be able to [...] but I can't because [...] + - type: textarea + id: solution + attributes: + label: Describe the solution you would like. + description: | + A clear and concise description of what you would want to happen. + For API changes, try to provide a code snippet of what you would like the API to look like. + - type: textarea + id: alternatives + attributes: + label: Describe alternatives you considered + description: Please describe any alternative solutions or features you've considered to solve your problem and why they wouldn't solve it. + - type: textarea + id: additional + attributes: + label: Additional context + description: Provide any additional context, screenshots, trace backs, etc. about the feature here. From 6fa1401f0bf97b607188c111fef33bbfa0ca7557 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Sat, 15 Jan 2022 19:08:34 +0100 Subject: [PATCH 02/15] Add websocket.close reason --- docs/websockets.md | 2 +- starlette/testclient.py | 2 +- starlette/websockets.py | 26 +++++++++++++++++++++----- tests/test_websockets.py | 38 +++++++++++++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 8 deletions(-) diff --git a/docs/websockets.md b/docs/websockets.md index 43406aced..192162931 100644 --- a/docs/websockets.md +++ b/docs/websockets.md @@ -75,7 +75,7 @@ Use `websocket.receive_json(data, mode="binary")` to receive JSON over binary da ### Closing the connection -* `await websocket.close(code=1000)` +* `await websocket.close(code=1000, reason="Normal Closure")` ### Sending and receiving messages diff --git a/starlette/testclient.py b/starlette/testclient.py index 0b4bc78d1..833bc0c7f 100644 --- a/starlette/testclient.py +++ b/starlette/testclient.py @@ -352,7 +352,7 @@ async def _asgi_send(self, message: Message) -> None: def _raise_on_close(self, message: Message) -> None: if message["type"] == "websocket.close": - raise WebSocketDisconnect(message.get("code", 1000)) + raise WebSocketDisconnect(message.get("code", 1000), message.get("reason")) def send(self, message: Message) -> None: self._receive_queue.put(message) diff --git a/starlette/websockets.py b/starlette/websockets.py index 7632b28cf..3b51c6750 100644 --- a/starlette/websockets.py +++ b/starlette/websockets.py @@ -13,8 +13,9 @@ class WebSocketState(enum.Enum): class WebSocketDisconnect(Exception): - def __init__(self, code: int = 1000) -> None: + def __init__(self, code: int = None, reason: str = None) -> None: self.code = code + self.reason = reason class WebSocket(HTTPConnection): @@ -144,13 +145,28 @@ async def send_json(self, data: typing.Any, mode: str = "text") -> None: else: await self.send({"type": "websocket.send", "bytes": text.encode("utf-8")}) - async def close(self, code: int = 1000) -> None: - await self.send({"type": "websocket.close", "code": code}) + async def close(self, code: int = None, reason: str = None) -> None: + message: dict = {"type": "websocket.close"} + + if code is not None: + message["code"] = code + if reason is not None: + message["reason"] = reason + + await self.send(message) class WebSocketClose: - def __init__(self, code: int = 1000) -> None: + def __init__(self, code: int = None, reason: str = None) -> None: self.code = code + self.reason = reason async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: - await send({"type": "websocket.close", "code": self.code}) + message: dict = {"type": "websocket.close"} + + if self.code is not None: + message["code"] = self.code + if self.reason is not None: + message["reason"] = self.reason + + await send(message) diff --git a/tests/test_websockets.py b/tests/test_websockets.py index bf0253309..3205aeebb 100644 --- a/tests/test_websockets.py +++ b/tests/test_websockets.py @@ -2,7 +2,7 @@ import pytest from starlette import status -from starlette.websockets import WebSocket, WebSocketDisconnect +from starlette.websockets import WebSocket, WebSocketClose, WebSocketDisconnect def test_websocket_url(test_client_factory): @@ -391,3 +391,39 @@ async def mock_send(message): assert websocket == websocket assert websocket in {websocket} assert {websocket} == {websocket} + + +def test_websocket_close_reason(test_client_factory) -> None: + def app(scope): + async def asgi(receive, send): + websocket = WebSocket(scope, receive=receive, send=send) + await websocket.accept() + await websocket.close(code=1001, reason="Closing") + + return asgi + + client = test_client_factory(app) + with client.websocket_connect("/") as websocket: + with pytest.raises(WebSocketDisconnect) as exc: + websocket.receive_text() + assert exc.value.code == status.WS_1001_GOING_AWAY + assert exc.value.reason == "Closing" + + +def test_websocket_close_reason_manual(test_client_factory) -> None: + def app(scope): + async def asgi(receive, send): + websocket = WebSocket(scope, receive=receive, send=send) + await websocket.accept() + + websocket_close = WebSocketClose(code=1001, reason="Closing") + await websocket_close(scope, receive, send) + + return asgi + + client = test_client_factory(app) + with client.websocket_connect("/") as websocket: + with pytest.raises(WebSocketDisconnect) as exc: + websocket.receive_text() + assert exc.value.code == status.WS_1001_GOING_AWAY + assert exc.value.reason == "Closing" From e4c9567d50b0a2301098b5a561fb06483ba2c051 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Sat, 15 Jan 2022 19:49:00 +0100 Subject: [PATCH 03/15] Update docs/websockets.md Co-authored-by: Marcelo Trylesinski --- docs/websockets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/websockets.md b/docs/websockets.md index 192162931..1128bce43 100644 --- a/docs/websockets.md +++ b/docs/websockets.md @@ -75,7 +75,7 @@ Use `websocket.receive_json(data, mode="binary")` to receive JSON over binary da ### Closing the connection -* `await websocket.close(code=1000, reason="Normal Closure")` +* `await websocket.close(code=1000, reason=None)` ### Sending and receiving messages From dc5d143d57211d2b52456ee33f66c9cd8a401f93 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Sat, 15 Jan 2022 19:52:11 +0100 Subject: [PATCH 04/15] revert close code change --- starlette/websockets.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/starlette/websockets.py b/starlette/websockets.py index 3b51c6750..88bd80c9f 100644 --- a/starlette/websockets.py +++ b/starlette/websockets.py @@ -13,7 +13,7 @@ class WebSocketState(enum.Enum): class WebSocketDisconnect(Exception): - def __init__(self, code: int = None, reason: str = None) -> None: + def __init__(self, code: int = 1000, reason: str = None) -> None: self.code = code self.reason = reason @@ -145,11 +145,9 @@ async def send_json(self, data: typing.Any, mode: str = "text") -> None: else: await self.send({"type": "websocket.send", "bytes": text.encode("utf-8")}) - async def close(self, code: int = None, reason: str = None) -> None: - message: dict = {"type": "websocket.close"} + async def close(self, code: int = 1000, reason: str = None) -> None: + message = {"type": "websocket.close", "code": code} - if code is not None: - message["code"] = code if reason is not None: message["reason"] = reason @@ -157,15 +155,13 @@ async def close(self, code: int = None, reason: str = None) -> None: class WebSocketClose: - def __init__(self, code: int = None, reason: str = None) -> None: + def __init__(self, code: int = 1000, reason: str = None) -> None: self.code = code self.reason = reason async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: - message: dict = {"type": "websocket.close"} + message = {"type": "websocket.close", "code": self.code} - if self.code is not None: - message["code"] = self.code if self.reason is not None: message["reason"] = self.reason From 3b67063b4762ad8422115b61dcef54a6be02f7cf Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Sat, 15 Jan 2022 19:55:32 +0100 Subject: [PATCH 05/15] update send message --- starlette/websockets.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/starlette/websockets.py b/starlette/websockets.py index 88bd80c9f..77e7bc560 100644 --- a/starlette/websockets.py +++ b/starlette/websockets.py @@ -146,12 +146,10 @@ async def send_json(self, data: typing.Any, mode: str = "text") -> None: await self.send({"type": "websocket.send", "bytes": text.encode("utf-8")}) async def close(self, code: int = 1000, reason: str = None) -> None: - message = {"type": "websocket.close", "code": code} - - if reason is not None: - message["reason"] = reason - - await self.send(message) + if reason is None: + await self.send({"type": "websocket.close", "code": code}) + else: + await self.send({"type": "websocket.close", "code": code, "reason": reason}) class WebSocketClose: @@ -160,9 +158,9 @@ def __init__(self, code: int = 1000, reason: str = None) -> None: self.reason = reason async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: - message = {"type": "websocket.close", "code": self.code} - - if self.reason is not None: - message["reason"] = self.reason - - await send(message) + if self.reason is None: + await send({"type": "websocket.close", "code": self.code}) + else: + await send( + {"type": "websocket.close", "code": self.code, "reason": self.reason} + ) From 6f8987f4efae7c92d933c8c65094bb84a2b081e2 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Wed, 19 Jan 2022 10:34:54 +0100 Subject: [PATCH 06/15] add docs --- docs/templates.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/templates.md b/docs/templates.md index b67669920..181cd1fef 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -64,6 +64,20 @@ def test_homepage(): assert "request" in response.context ``` +## Customizing Jinja2 Environment + +`Jinja2Templates` accepts all options supported by Jinja2 `Environment`. +This will allow more control over the `Enivornment` instance created by Starlette. + +For the list of options available to `Environment` you can check Jinja2 documentation [here](https://jinja.palletsprojects.com/en/3.0.x/api/#jinja2.Environment) + +```python +from starlette.templating import Jinja2Templates + + +templates = Jinja2Templates(directory='templates', autoescape=False, auto_reload=True) +``` + ## Asynchronous template rendering Jinja2 supports async template rendering, however as a general rule From c32605fc2e7e9fe037e670fd22f44d168b5e72b0 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Wed, 19 Jan 2022 10:36:18 +0100 Subject: [PATCH 07/15] revert docs commit --- docs/templates.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index 181cd1fef..b67669920 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -64,20 +64,6 @@ def test_homepage(): assert "request" in response.context ``` -## Customizing Jinja2 Environment - -`Jinja2Templates` accepts all options supported by Jinja2 `Environment`. -This will allow more control over the `Enivornment` instance created by Starlette. - -For the list of options available to `Environment` you can check Jinja2 documentation [here](https://jinja.palletsprojects.com/en/3.0.x/api/#jinja2.Environment) - -```python -from starlette.templating import Jinja2Templates - - -templates = Jinja2Templates(directory='templates', autoescape=False, auto_reload=True) -``` - ## Asynchronous template rendering Jinja2 supports async template rendering, however as a general rule From 608c2bf8ebeac01e958d31b20d9fde6971ddfeb4 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Wed, 19 Jan 2022 10:38:51 +0100 Subject: [PATCH 08/15] update docs --- docs/templates.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/templates.md b/docs/templates.md index b67669920..181cd1fef 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -64,6 +64,20 @@ def test_homepage(): assert "request" in response.context ``` +## Customizing Jinja2 Environment + +`Jinja2Templates` accepts all options supported by Jinja2 `Environment`. +This will allow more control over the `Enivornment` instance created by Starlette. + +For the list of options available to `Environment` you can check Jinja2 documentation [here](https://jinja.palletsprojects.com/en/3.0.x/api/#jinja2.Environment) + +```python +from starlette.templating import Jinja2Templates + + +templates = Jinja2Templates(directory='templates', autoescape=False, auto_reload=True) +``` + ## Asynchronous template rendering Jinja2 supports async template rendering, however as a general rule From 0db01cf135a050e7f45ee07e4e0da95a9b36f8fc Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Fri, 21 Jan 2022 13:02:35 +0100 Subject: [PATCH 09/15] Update templates.md --- docs/templates.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/docs/templates.md b/docs/templates.md index 181cd1fef..b67669920 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -64,20 +64,6 @@ def test_homepage(): assert "request" in response.context ``` -## Customizing Jinja2 Environment - -`Jinja2Templates` accepts all options supported by Jinja2 `Environment`. -This will allow more control over the `Enivornment` instance created by Starlette. - -For the list of options available to `Environment` you can check Jinja2 documentation [here](https://jinja.palletsprojects.com/en/3.0.x/api/#jinja2.Environment) - -```python -from starlette.templating import Jinja2Templates - - -templates = Jinja2Templates(directory='templates', autoescape=False, auto_reload=True) -``` - ## Asynchronous template rendering Jinja2 supports async template rendering, however as a general rule From 4efbeaf5e264058ab9c688a37016b29f3b421264 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Fri, 21 Jan 2022 14:44:17 +0100 Subject: [PATCH 10/15] make reason available in all cases --- starlette/websockets.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/starlette/websockets.py b/starlette/websockets.py index 77e7bc560..b98827504 100644 --- a/starlette/websockets.py +++ b/starlette/websockets.py @@ -146,10 +146,7 @@ async def send_json(self, data: typing.Any, mode: str = "text") -> None: await self.send({"type": "websocket.send", "bytes": text.encode("utf-8")}) async def close(self, code: int = 1000, reason: str = None) -> None: - if reason is None: - await self.send({"type": "websocket.close", "code": code}) - else: - await self.send({"type": "websocket.close", "code": code, "reason": reason}) + await self.send({"type": "websocket.close", "code": code, "reason": reason}) class WebSocketClose: @@ -158,9 +155,6 @@ def __init__(self, code: int = 1000, reason: str = None) -> None: self.reason = reason async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: - if self.reason is None: - await send({"type": "websocket.close", "code": self.code}) - else: - await send( - {"type": "websocket.close", "code": self.code, "reason": self.reason} - ) + await send( + {"type": "websocket.close", "code": self.code, "reason": self.reason} + ) From 544dfd27cca2397e577aca16284fd24154f342e7 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Fri, 21 Jan 2022 16:18:44 +0100 Subject: [PATCH 11/15] Update with comments --- starlette/websockets.py | 8 +++++--- tests/test_websockets.py | 25 +++---------------------- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/starlette/websockets.py b/starlette/websockets.py index b98827504..6c399fa9f 100644 --- a/starlette/websockets.py +++ b/starlette/websockets.py @@ -146,13 +146,15 @@ async def send_json(self, data: typing.Any, mode: str = "text") -> None: await self.send({"type": "websocket.send", "bytes": text.encode("utf-8")}) async def close(self, code: int = 1000, reason: str = None) -> None: - await self.send({"type": "websocket.close", "code": code, "reason": reason}) + await self.send( + {"type": "websocket.close", "code": code, "reason": reason or ""} + ) class WebSocketClose: - def __init__(self, code: int = 1000, reason: str = None) -> None: + def __init__(self, code: int = 1000, reason: str = "") -> None: self.code = code - self.reason = reason + self.reason = reason or "" async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: await send( diff --git a/tests/test_websockets.py b/tests/test_websockets.py index 3205aeebb..849bc8756 100644 --- a/tests/test_websockets.py +++ b/tests/test_websockets.py @@ -2,7 +2,7 @@ import pytest from starlette import status -from starlette.websockets import WebSocket, WebSocketClose, WebSocketDisconnect +from starlette.websockets import WebSocket, WebSocketDisconnect def test_websocket_url(test_client_factory): @@ -398,7 +398,7 @@ def app(scope): async def asgi(receive, send): websocket = WebSocket(scope, receive=receive, send=send) await websocket.accept() - await websocket.close(code=1001, reason="Closing") + await websocket.close(code=1001, reason="Going Away") return asgi @@ -407,23 +407,4 @@ async def asgi(receive, send): with pytest.raises(WebSocketDisconnect) as exc: websocket.receive_text() assert exc.value.code == status.WS_1001_GOING_AWAY - assert exc.value.reason == "Closing" - - -def test_websocket_close_reason_manual(test_client_factory) -> None: - def app(scope): - async def asgi(receive, send): - websocket = WebSocket(scope, receive=receive, send=send) - await websocket.accept() - - websocket_close = WebSocketClose(code=1001, reason="Closing") - await websocket_close(scope, receive, send) - - return asgi - - client = test_client_factory(app) - with client.websocket_connect("/") as websocket: - with pytest.raises(WebSocketDisconnect) as exc: - websocket.receive_text() - assert exc.value.code == status.WS_1001_GOING_AWAY - assert exc.value.reason == "Closing" + assert exc.value.reason == "Going Away" From 14ebbf53c05936e5d206456d148804788f0a9b39 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Fri, 21 Jan 2022 16:20:37 +0100 Subject: [PATCH 12/15] update test --- tests/test_websockets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_websockets.py b/tests/test_websockets.py index 849bc8756..e46cefba8 100644 --- a/tests/test_websockets.py +++ b/tests/test_websockets.py @@ -398,7 +398,7 @@ def app(scope): async def asgi(receive, send): websocket = WebSocket(scope, receive=receive, send=send) await websocket.accept() - await websocket.close(code=1001, reason="Going Away") + await websocket.close(code=status.WS_1001_GOING_AWAY, reason="Going Away") return asgi From a172de7adcf2a588b3262b9198c5e697adc1816c Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Sat, 22 Jan 2022 11:19:27 +0100 Subject: [PATCH 13/15] Update websockets.py --- starlette/websockets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/starlette/websockets.py b/starlette/websockets.py index 6c399fa9f..fec9b210d 100644 --- a/starlette/websockets.py +++ b/starlette/websockets.py @@ -15,7 +15,7 @@ class WebSocketState(enum.Enum): class WebSocketDisconnect(Exception): def __init__(self, code: int = 1000, reason: str = None) -> None: self.code = code - self.reason = reason + self.reason = reason or "" class WebSocket(HTTPConnection): @@ -152,7 +152,7 @@ async def close(self, code: int = 1000, reason: str = None) -> None: class WebSocketClose: - def __init__(self, code: int = 1000, reason: str = "") -> None: + def __init__(self, code: int = 1000, reason: str = None) -> None: self.code = code self.reason = reason or "" From 277b6acb2111d0a7d5906958f872248743ca3700 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Sat, 22 Jan 2022 12:03:17 +0100 Subject: [PATCH 14/15] Update starlette/testclient.py Co-authored-by: Marcelo Trylesinski --- starlette/testclient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starlette/testclient.py b/starlette/testclient.py index 833bc0c7f..806c8dcb6 100644 --- a/starlette/testclient.py +++ b/starlette/testclient.py @@ -352,7 +352,7 @@ async def _asgi_send(self, message: Message) -> None: def _raise_on_close(self, message: Message) -> None: if message["type"] == "websocket.close": - raise WebSocketDisconnect(message.get("code", 1000), message.get("reason")) + raise WebSocketDisconnect(message.get("code", 1000), message.get("reason", "")) def send(self, message: Message) -> None: self._receive_queue.put(message) From ffec63d81ecf7d45d455085c5c00009a8c1b0e67 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Sat, 22 Jan 2022 12:05:31 +0100 Subject: [PATCH 15/15] lint --- starlette/testclient.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/starlette/testclient.py b/starlette/testclient.py index 806c8dcb6..c951767b4 100644 --- a/starlette/testclient.py +++ b/starlette/testclient.py @@ -352,7 +352,9 @@ async def _asgi_send(self, message: Message) -> None: def _raise_on_close(self, message: Message) -> None: if message["type"] == "websocket.close": - raise WebSocketDisconnect(message.get("code", 1000), message.get("reason", "")) + raise WebSocketDisconnect( + message.get("code", 1000), message.get("reason", "") + ) def send(self, message: Message) -> None: self._receive_queue.put(message)