Skip to content

Commit

Permalink
Make error messages more error friendly.
Browse files Browse the repository at this point in the history
Avoid weird exception chaining to assertion errors.
  • Loading branch information
aaugustin committed Sep 3, 2021
1 parent 1b0b2de commit 88ae5eb
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 12 deletions.
11 changes: 11 additions & 0 deletions docs/project/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
5 changes: 3 additions & 2 deletions src/websockets/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
15 changes: 7 additions & 8 deletions src/websockets/uri.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,12 @@ 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, "hostname isn't provided")
if parsed.fragment != "":
raise exceptions.InvalidURI(uri, "fragment identifier is meaningless")

secure = parsed.scheme == "wss"
host = parsed.hostname
Expand All @@ -73,7 +72,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:
Expand Down
4 changes: 2 additions & 2 deletions tests/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
5 changes: 5 additions & 0 deletions tests/test_uri.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
"ws://localhost/path?query",
WebSocketURI(False, "localhost", 80, "/path?query", None),
),
(
"ws://localhost/path;params",
WebSocketURI(False, "localhost", 80, "/path;params", None),
),
(
"WS://LOCALHOST/PATH?QUERY",
WebSocketURI(False, "localhost", 80, "/PATH?QUERY", None),
Expand All @@ -39,6 +43,7 @@
"https://localhost/",
"ws://localhost/path#fragment",
"ws://user@localhost/",
"ws:///path",
]


Expand Down

0 comments on commit 88ae5eb

Please sign in to comment.