From d63ed11ccfa175d16595c58e5287a69627bb545c Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Fri, 3 Sep 2021 20:50:03 +0200 Subject: [PATCH] Make error messages more error friendly. Avoid weird exception chaining to assertion errors. --- docs/project/changelog.rst | 11 +++++++++++ src/websockets/exceptions.py | 5 +++-- src/websockets/uri.py | 17 +++++++++-------- tests/test_exceptions.py | 4 ++-- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/docs/project/changelog.rst b/docs/project/changelog.rst index 07942783f..b9329d7b5 100644 --- a/docs/project/changelog.rst +++ b/docs/project/changelog.rst @@ -56,6 +56,15 @@ They may change at any time. If you raise :exc:`~exceptions.ConnectionClosed` or a subclass — rather than catch them when websockets raises them — you must change your code. +.. note:: + + **Version 10.0 adds a ``msg`` parameter to** ``InvalidURI.__init__`` **.** + + If you raise :exc:`~exceptions.InvalidURI` — rather than catch them when + websockets raises them — you must change your code. + +Also: + * Added compatibility with Python 3.10. * Added :func:`~websockets.broadcast` to send a message to many clients. @@ -150,6 +159,8 @@ They may change at any time. from websockets.client import connect from websockets.server import serve +Also: + * Added compatibility with Python 3.9. * Added support for IRIs in addition to URIs. diff --git a/src/websockets/exceptions.py b/src/websockets/exceptions.py index b3462484f..6bbea324c 100644 --- a/src/websockets/exceptions.py +++ b/src/websockets/exceptions.py @@ -374,11 +374,12 @@ class InvalidURI(WebSocketException): """ - def __init__(self, uri: str) -> None: + def __init__(self, uri: str, msg: str) -> None: self.uri = uri + self.msg = msg def __str__(self) -> str: - return f"{self.uri} isn't a valid URI" + return f"{self.uri} isn't a valid URI: {self.msg}" class PayloadTooBig(WebSocketException): diff --git a/src/websockets/uri.py b/src/websockets/uri.py index c99c3f16e..6fc2684f0 100644 --- a/src/websockets/uri.py +++ b/src/websockets/uri.py @@ -54,18 +54,19 @@ def parse_uri(uri: str) -> WebSocketURI: """ parsed = urllib.parse.urlparse(uri) - try: - assert parsed.scheme in ["ws", "wss"] - assert parsed.params == "" - assert parsed.fragment == "" - assert parsed.hostname is not None - except AssertionError as exc: - raise exceptions.InvalidURI(uri) from exc + if parsed.scheme not in ["ws", "wss"]: + raise exceptions.InvalidURI(uri, "scheme isn't ws or wss") + if parsed.hostname is None: + raise exceptions.InvalidURI(uri, "hostame isn't provided") + if parsed.fragment != "": + raise exceptions.InvalidURI(uri, "fragment identifier is meaningless") secure = parsed.scheme == "wss" host = parsed.hostname port = parsed.port or (443 if secure else 80) resource_name = parsed.path or "/" + if parsed.params: + resource_name += ";" + parsed.params if parsed.query: resource_name += "?" + parsed.query user_info = None @@ -73,7 +74,7 @@ def parse_uri(uri: str) -> WebSocketURI: # urllib.parse.urlparse accepts URLs with a username but without a # password. This doesn't make sense for HTTP Basic Auth credentials. if parsed.password is None: - raise exceptions.InvalidURI(uri) + raise exceptions.InvalidURI(uri, "username provided without password") user_info = (parsed.username, parsed.password) try: diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index e172cdd02..3ede25fdb 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -142,8 +142,8 @@ def test_str(self): "WebSocket connection isn't established yet", ), ( - InvalidURI("|"), - "| isn't a valid URI", + InvalidURI("|", "not at all!"), + "| isn't a valid URI: not at all!", ), ( PayloadTooBig("payload length exceeds limit: 2 > 1 bytes"),