Skip to content

Add support for Python 3.8 #675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Oct 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ jobs:
- checkout
- run: sudo pip install tox
- run: tox -e py37
py38:
docker:
- image: circleci/python:3.8.0rc1
steps:
# Remove IPv6 entry for localhost in Circle CI containers because it doesn't work anyway.
- run: sudo cp /etc/hosts /tmp; sudo sed -i '/::1/d' /tmp/hosts; sudo cp /tmp/hosts /etc
- checkout
- run: sudo pip install tox
- run: tox -e py38

workflows:
version: 2
Expand All @@ -41,3 +50,6 @@ workflows:
- py37:
requires:
- main
- py38:
requires:
- main
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Changelog

*In development*

* Added compatibility with Python 3.8.

8.0.2
.....

Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
],
package_dir = {'': 'src'},
package_data = {'websockets': ['py.typed']},
Expand Down
15 changes: 8 additions & 7 deletions src/websockets/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# This relies on each of the submodules having an __all__ variable.

from .auth import *
from .client import *
from .exceptions import *
from .protocol import *
from .server import *
from .typing import *
from .uri import *
from . import auth, client, exceptions, protocol, server, typing, uri
from .auth import * # noqa
from .client import * # noqa
from .exceptions import * # noqa
from .protocol import * # noqa
from .server import * # noqa
from .typing import * # noqa
from .uri import * # noqa
from .version import version as __version__ # noqa


Expand Down
8 changes: 4 additions & 4 deletions src/websockets/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import threading
from typing import Any, Set

import websockets
from websockets.exceptions import format_close
from .client import connect
from .exceptions import ConnectionClosed, format_close


if sys.platform == "win32":
Expand Down Expand Up @@ -95,7 +95,7 @@ async def run_client(
stop: "asyncio.Future[None]",
) -> None:
try:
websocket = await websockets.connect(uri)
websocket = await connect(uri)
except Exception as exc:
print_over_input(f"Failed to connect to {uri}: {exc}.")
exit_from_event_loop_thread(loop, stop)
Expand All @@ -122,7 +122,7 @@ async def run_client(
if incoming in done:
try:
message = incoming.result()
except websockets.ConnectionClosed:
except ConnectionClosed:
break
else:
if isinstance(message, str):
Expand Down
5 changes: 2 additions & 3 deletions src/websockets/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
from .extensions.permessage_deflate import ClientPerMessageDeflateFactory
from .handshake import build_request, check_response
from .headers import (
ExtensionHeader,
build_authorization_basic,
build_extension,
build_subprotocol,
Expand All @@ -33,7 +32,7 @@
)
from .http import USER_AGENT, Headers, HeadersLike, read_response
from .protocol import WebSocketCommonProtocol
from .typing import Origin, Subprotocol
from .typing import ExtensionHeader, Origin, Subprotocol
from .uri import WebSocketURI, parse_uri


Expand Down Expand Up @@ -85,7 +84,7 @@ def write_http_request(self, path: str, headers: Headers) -> None:
request = f"GET {path} HTTP/1.1\r\n"
request += str(headers)

self.writer.write(request.encode())
self.transport.write(request.encode())

async def read_http_response(self) -> Tuple[int, Headers]:
"""
Expand Down
8 changes: 4 additions & 4 deletions src/websockets/framing.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ async def read(

def write(
frame,
writer: Callable[[bytes], Any],
write: Callable[[bytes], Any],
*,
mask: bool,
extensions: Optional[Sequence["websockets.extensions.base.Extension"]] = None,
Expand All @@ -156,7 +156,7 @@ def write(
Write a WebSocket frame.

:param frame: frame to write
:param writer: function that writes bytes
:param write: function that writes bytes
:param mask: whether the frame should be masked i.e. whether the write
happens on the client side
:param extensions: list of classes with an ``encode()`` method that
Expand Down Expand Up @@ -210,10 +210,10 @@ def write(

# Send the frame.

# The frame is written in a single call to writer in order to prevent
# The frame is written in a single call to write in order to prevent
# TCP fragmentation. See #68 for details. This also makes it safe to
# send frames concurrently from multiple coroutines.
writer(output.getvalue())
write(output.getvalue())

def check(frame) -> None:
"""
Expand Down
15 changes: 10 additions & 5 deletions src/websockets/handshake.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@
import binascii
import hashlib
import random
from typing import List

from .exceptions import InvalidHeader, InvalidHeaderValue, InvalidUpgrade
from .headers import parse_connection, parse_upgrade
from .headers import ConnectionOption, UpgradeProtocol, parse_connection, parse_upgrade
from .http import Headers, MultipleValuesError


Expand Down Expand Up @@ -74,14 +75,16 @@ def check_request(headers: Headers) -> str:
is invalid; then the server must return 400 Bad Request error

"""
connection = sum(
connection: List[ConnectionOption] = sum(
[parse_connection(value) for value in headers.get_all("Connection")], []
)

if not any(value.lower() == "upgrade" for value in connection):
raise InvalidUpgrade("Connection", ", ".join(connection))

upgrade = sum([parse_upgrade(value) for value in headers.get_all("Upgrade")], [])
upgrade: List[UpgradeProtocol] = sum(
[parse_upgrade(value) for value in headers.get_all("Upgrade")], []
)

# For compatibility with non-strict implementations, ignore case when
# checking the Upgrade header. It's supposed to be 'WebSocket'.
Expand Down Expand Up @@ -148,14 +151,16 @@ def check_response(headers: Headers, key: str) -> None:
is invalid

"""
connection = sum(
connection: List[ConnectionOption] = sum(
[parse_connection(value) for value in headers.get_all("Connection")], []
)

if not any(value.lower() == "upgrade" for value in connection):
raise InvalidUpgrade("Connection", " ".join(connection))

upgrade = sum([parse_upgrade(value) for value in headers.get_all("Upgrade")], [])
upgrade: List[UpgradeProtocol] = sum(
[parse_upgrade(value) for value in headers.get_all("Upgrade")], []
)

# For compatibility with non-strict implementations, ignore case when
# checking the Upgrade header. It's supposed to be 'WebSocket'.
Expand Down
Loading