Skip to content

Commit 8d055eb

Browse files
committed
Deprecate aliases pointing to the legacy implementation.
1 parent a942fcc commit 8d055eb

File tree

10 files changed

+99
-100
lines changed

10 files changed

+99
-100
lines changed

docs/howto/upgrade.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ For context, the ``websockets`` package is structured as follows:
7171
* The new implementation is found in the ``websockets.asyncio`` package.
7272
* The original implementation was moved to the ``websockets.legacy`` package.
7373
* The ``websockets`` package provides aliases for convenience. They were
74-
switched to the new implementation in version 14.0.
74+
switched to the new implementation in version 14.0 or deprecated when there
75+
isn't an equivalent API.
7576
* The ``websockets.client`` and ``websockets.server`` packages provide aliases
7677
for backwards-compatibility with earlier versions of websockets. They will
7778
be deprecated together with the original implementation.

docs/project/changelog.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ Backwards-incompatible changes
5252
If you're using any of them, then you must follow the :doc:`upgrade guide
5353
<../howto/upgrade>` immediately.
5454

55+
.. admonition:: The legacy :mod:`asyncio` implementation is now deprecated.
56+
:class: caution
57+
58+
Aliases for deprecated API were removed from ``__all__``. As a consequence,
59+
they cannot be imported e.g. with ``from websockets import *`` anymore.
60+
5561
.. _13.1:
5662

5763
13.1

src/websockets/__init__.py

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,6 @@
4343
"ProtocolError",
4444
"SecurityError",
4545
"WebSocketException",
46-
"WebSocketProtocolError",
47-
# .legacy.auth
48-
"BasicAuthWebSocketServerProtocol",
49-
"basic_auth_protocol_factory",
50-
# .legacy.client
51-
"WebSocketClientProtocol",
52-
# .legacy.exceptions
53-
"AbortHandshake",
54-
"InvalidMessage",
55-
"InvalidStatusCode",
56-
"RedirectHandshake",
57-
# .legacy.protocol
58-
"WebSocketCommonProtocol",
59-
# .legacy.server
60-
"WebSocketServer",
61-
"WebSocketServerProtocol",
6246
# .server
6347
"ServerProtocol",
6448
# .typing
@@ -99,21 +83,7 @@
9983
ProtocolError,
10084
SecurityError,
10185
WebSocketException,
102-
WebSocketProtocolError,
10386
)
104-
from .legacy.auth import (
105-
BasicAuthWebSocketServerProtocol,
106-
basic_auth_protocol_factory,
107-
)
108-
from .legacy.client import WebSocketClientProtocol
109-
from .legacy.exceptions import (
110-
AbortHandshake,
111-
InvalidMessage,
112-
InvalidStatusCode,
113-
RedirectHandshake,
114-
)
115-
from .legacy.protocol import WebSocketCommonProtocol
116-
from .legacy.server import WebSocketServer, WebSocketServerProtocol
11787
from .server import ServerProtocol
11888
from .typing import (
11989
Data,
@@ -164,22 +134,6 @@
164134
"ProtocolError": ".exceptions",
165135
"SecurityError": ".exceptions",
166136
"WebSocketException": ".exceptions",
167-
"WebSocketProtocolError": ".exceptions",
168-
# .legacy.auth
169-
"BasicAuthWebSocketServerProtocol": ".legacy.auth",
170-
"basic_auth_protocol_factory": ".legacy.auth",
171-
# .legacy.client
172-
"WebSocketClientProtocol": ".legacy.client",
173-
# .legacy.exceptions
174-
"AbortHandshake": ".legacy.exceptions",
175-
"InvalidMessage": ".legacy.exceptions",
176-
"InvalidStatusCode": ".legacy.exceptions",
177-
"RedirectHandshake": ".legacy.exceptions",
178-
# .legacy.protocol
179-
"WebSocketCommonProtocol": ".legacy.protocol",
180-
# .legacy.server
181-
"WebSocketServer": ".legacy.server",
182-
"WebSocketServerProtocol": ".legacy.server",
183137
# .server
184138
"ServerProtocol": ".server",
185139
# .typing
@@ -197,5 +151,22 @@
197151
"handshake": ".legacy",
198152
"parse_uri": ".uri",
199153
"WebSocketURI": ".uri",
154+
# deprecated in 14.0
155+
# .legacy.auth
156+
"BasicAuthWebSocketServerProtocol": ".legacy.auth",
157+
"basic_auth_protocol_factory": ".legacy.auth",
158+
# .legacy.client
159+
"WebSocketClientProtocol": ".legacy.client",
160+
# .legacy.exceptions
161+
"AbortHandshake": ".legacy.exceptions",
162+
"InvalidMessage": ".legacy.exceptions",
163+
"InvalidStatusCode": ".legacy.exceptions",
164+
"RedirectHandshake": ".legacy.exceptions",
165+
"WebSocketProtocolError": ".legacy.exceptions",
166+
# .legacy.protocol
167+
"WebSocketCommonProtocol": ".legacy.protocol",
168+
# .legacy.server
169+
"WebSocketServer": ".legacy.server",
170+
"WebSocketServerProtocol": ".legacy.server",
200171
},
201172
)

src/websockets/auth.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
from __future__ import annotations
22

3-
# See #940 for why lazy_import isn't used here for backwards compatibility.
4-
# See #1400 for why listing compatibility imports in __all__ helps PyCharm.
3+
import warnings
4+
55
from .legacy.auth import *
66
from .legacy.auth import __all__ # noqa: F401
7+
8+
9+
warnings.warn( # deprecated in 14.0
10+
"websockets.auth is deprecated",
11+
DeprecationWarning,
12+
)

src/websockets/client.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
parse_upgrade,
2828
)
2929
from .http11 import Request, Response
30+
from .imports import lazy_import
3031
from .protocol import CLIENT, CONNECTING, OPEN, Protocol, State
3132
from .typing import (
3233
ConnectionOption,
@@ -40,13 +41,7 @@
4041
from .utils import accept_key, generate_key
4142

4243

43-
# See #940 for why lazy_import isn't used here for backwards compatibility.
44-
# See #1400 for why listing compatibility imports in __all__ helps PyCharm.
45-
from .legacy.client import * # isort:skip # noqa: I001
46-
from .legacy.client import __all__ as legacy__all__
47-
48-
49-
__all__ = ["ClientProtocol"] + legacy__all__
44+
__all__ = ["ClientProtocol"]
5045

5146

5247
class ClientProtocol(Protocol):
@@ -392,3 +387,14 @@ def backoff(
392387
delay *= factor
393388
while True:
394389
yield max_delay
390+
391+
392+
lazy_import(
393+
globals(),
394+
deprecated_aliases={
395+
# deprecated in 14.0
396+
"WebSocketClientProtocol": ".legacy.client",
397+
"connect": ".legacy.client",
398+
"unix_connect": ".legacy.client",
399+
},
400+
)

src/websockets/exceptions.py

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131

3232
from __future__ import annotations
3333

34-
import typing
3534
import warnings
3635

3736
from .imports import lazy_import
@@ -45,9 +44,7 @@
4544
"InvalidURI",
4645
"InvalidHandshake",
4746
"SecurityError",
48-
"InvalidMessage",
4947
"InvalidStatus",
50-
"InvalidStatusCode",
5148
"InvalidHeader",
5249
"InvalidHeaderFormat",
5350
"InvalidHeaderValue",
@@ -57,10 +54,7 @@
5754
"DuplicateParameter",
5855
"InvalidParameterName",
5956
"InvalidParameterValue",
60-
"AbortHandshake",
61-
"RedirectHandshake",
6257
"ProtocolError",
63-
"WebSocketProtocolError",
6458
"PayloadTooBig",
6559
"InvalidState",
6660
"ConcurrencyError",
@@ -366,27 +360,18 @@ class ConcurrencyError(WebSocketException, RuntimeError):
366360
"""
367361

368362

369-
# When type checking, import non-deprecated aliases eagerly. Else, import on demand.
370-
if typing.TYPE_CHECKING:
371-
from .legacy.exceptions import (
372-
AbortHandshake,
373-
InvalidMessage,
374-
InvalidStatusCode,
375-
RedirectHandshake,
376-
)
377-
378-
WebSocketProtocolError = ProtocolError
379-
else:
380-
lazy_import(
381-
globals(),
382-
aliases={
383-
"AbortHandshake": ".legacy.exceptions",
384-
"InvalidMessage": ".legacy.exceptions",
385-
"InvalidStatusCode": ".legacy.exceptions",
386-
"RedirectHandshake": ".legacy.exceptions",
387-
"WebSocketProtocolError": ".legacy.exceptions",
388-
},
389-
)
390-
391363
# At the bottom to break import cycles created by type annotations.
392364
from . import frames, http11 # noqa: E402
365+
366+
367+
lazy_import(
368+
globals(),
369+
deprecated_aliases={
370+
# deprecated in 14.0
371+
"AbortHandshake": ".legacy.exceptions",
372+
"InvalidMessage": ".legacy.exceptions",
373+
"InvalidStatusCode": ".legacy.exceptions",
374+
"RedirectHandshake": ".legacy.exceptions",
375+
"WebSocketProtocolError": ".legacy.exceptions",
376+
},
377+
)

src/websockets/server.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
parse_upgrade,
2828
)
2929
from .http11 import Request, Response
30+
from .imports import lazy_import
3031
from .protocol import CONNECTING, OPEN, SERVER, Protocol, State
3132
from .typing import (
3233
ConnectionOption,
@@ -40,13 +41,7 @@
4041
from .utils import accept_key
4142

4243

43-
# See #940 for why lazy_import isn't used here for backwards compatibility.
44-
# See #1400 for why listing compatibility imports in __all__ helps PyCharm.
45-
from .legacy.server import * # isort:skip # noqa: I001
46-
from .legacy.server import __all__ as legacy__all__
47-
48-
49-
__all__ = ["ServerProtocol"] + legacy__all__
44+
__all__ = ["ServerProtocol"]
5045

5146

5247
class ServerProtocol(Protocol):
@@ -586,3 +581,16 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
586581
DeprecationWarning,
587582
)
588583
super().__init__(*args, **kwargs)
584+
585+
586+
lazy_import(
587+
globals(),
588+
deprecated_aliases={
589+
# deprecated in 14.0
590+
"WebSocketServer": ".legacy.server",
591+
"WebSocketServerProtocol": ".legacy.server",
592+
"broadcast": ".legacy.server",
593+
"serve": ".legacy.server",
594+
"unix_serve": ".legacy.server",
595+
},
596+
)

tests/legacy/test_auth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
import unittest
33
import urllib.error
44

5-
from websockets.exceptions import InvalidStatusCode
65
from websockets.headers import build_authorization_basic
76
from websockets.legacy.auth import *
87
from websockets.legacy.auth import is_credentials
8+
from websockets.legacy.exceptions import InvalidStatusCode
99

1010
from .test_client_server import ClientServerTestsMixin, with_client, with_server
1111
from .utils import AsyncioTestCase

tests/legacy/test_client_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
ConnectionClosed,
2222
InvalidHandshake,
2323
InvalidHeader,
24-
InvalidStatusCode,
2524
NegotiationError,
2625
)
2726
from websockets.extensions.permessage_deflate import (
@@ -32,6 +31,7 @@
3231
from websockets.frames import CloseCode
3332
from websockets.http11 import USER_AGENT
3433
from websockets.legacy.client import *
34+
from websockets.legacy.exceptions import InvalidStatusCode
3535
from websockets.legacy.handshake import build_response
3636
from websockets.legacy.http import read_response
3737
from websockets.legacy.server import *

tests/test_exports.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,46 @@
11
import unittest
22

33
import websockets
4-
import websockets.auth
4+
import websockets.asyncio.client
5+
import websockets.asyncio.server
56
import websockets.client
67
import websockets.datastructures
78
import websockets.exceptions
8-
import websockets.legacy.protocol
99
import websockets.server
1010
import websockets.typing
1111
import websockets.uri
1212

1313

1414
combined_exports = (
15-
websockets.auth.__all__
15+
[]
16+
+ websockets.asyncio.client.__all__
17+
+ websockets.asyncio.server.__all__
1618
+ websockets.client.__all__
1719
+ websockets.datastructures.__all__
1820
+ websockets.exceptions.__all__
19-
+ websockets.legacy.protocol.__all__
2021
+ websockets.server.__all__
2122
+ websockets.typing.__all__
2223
)
2324

25+
# These API are intentionally not re-exported by the top-level module.
26+
missing_reexports = [
27+
# websockets.asyncio.client
28+
"ClientConnection",
29+
# websockets.asyncio.server
30+
"ServerConnection",
31+
"Server",
32+
]
33+
2434

2535
class ExportsTests(unittest.TestCase):
26-
def test_top_level_module_reexports_all_submodule_exports(self):
27-
self.assertEqual(set(combined_exports), set(websockets.__all__))
36+
def test_top_level_module_reexports_submodule_exports(self):
37+
self.assertEqual(
38+
set(combined_exports),
39+
set(websockets.__all__ + missing_reexports),
40+
)
2841

2942
def test_submodule_exports_are_globally_unique(self):
30-
self.assertEqual(len(set(combined_exports)), len(combined_exports))
43+
self.assertEqual(
44+
len(set(combined_exports)),
45+
len(combined_exports),
46+
)

0 commit comments

Comments
 (0)