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 d63ed11
Show file tree
Hide file tree
Showing 4 changed files with 25 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
17 changes: 9 additions & 8 deletions src/websockets/uri.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,27 @@ 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
if parsed.username is not None:
# 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

0 comments on commit d63ed11

Please sign in to comment.