Skip to content

Blacken #177

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

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
7a9bf5f
Blacken
njsmith May 10, 2023
35c82c3
Fix formatting on a string constant
njsmith May 10, 2023
65ef376
Work around spurious pylint error
njsmith May 10, 2023
e9e821c
Merge remote-tracking branch 'origin/HEAD' into blacken
jakkdl Oct 26, 2023
2970fb5
add black to 'make lint', and run it on all files
jakkdl Oct 26, 2023
ae69a91
Merge remote-tracking branch 'origin/master' into blacken
jakkdl Oct 26, 2023
e18e907
Merge branch 'master' into blacken
CoolCat467 Jun 13, 2024
903dfc3
Run new version of black on all files
CoolCat467 Jun 13, 2024
d64908b
Run black on docs config with manual spacing fixes
CoolCat467 Jun 13, 2024
e7dd16b
Fix broken merge commit
CoolCat467 Jun 13, 2024
8fca059
Add midding black dev dependency
CoolCat467 Jun 13, 2024
86d292f
Merge branch 'master' into blacken
CoolCat467 Aug 2, 2024
32e09cd
Ignore more pylint issues and re-run black
CoolCat467 Aug 2, 2024
6f6da21
Re-run `black tests`
CoolCat467 Aug 2, 2024
e43a087
Re-run full black again
CoolCat467 Aug 2, 2024
77e5779
fix loss of context/cause on exceptions raised inside open_websocket
jakkdl Oct 20, 2024
df0f56d
fix test on non-strict
jakkdl Oct 20, 2024
a4e0562
fix another test fail
jakkdl Oct 20, 2024
5defd03
no-copy solution that completely hides the exceptiongroup in most cases
jakkdl Oct 23, 2024
1c5bf53
fix pylint
jakkdl Oct 23, 2024
16d8d9f
remove unused _copy_exc
jakkdl Oct 25, 2024
1b0be05
small cleanups
jakkdl Oct 25, 2024
b8d1fc7
make exceptions copy- and pickleable
jakkdl Oct 29, 2024
e7706f4
Merge pull request #192 from jakkdl/exc_group_cause_context
jakkdl Nov 25, 2024
10ee47e
Merge branch 'master' into blacken
CoolCat467 Jan 13, 2025
3354a33
Re-run black again
CoolCat467 Jan 13, 2025
00fc838
Add/complete type annotations
CoolCat467 Jan 13, 2025
c49321f
Fix line-too-long errors
CoolCat467 Jan 13, 2025
45c06ad
Fix remaining CI issues
CoolCat467 Jan 13, 2025
a2d83f5
Use strings for cast values
CoolCat467 Jan 13, 2025
335dab2
Missed another type quote
CoolCat467 Jan 13, 2025
743e4cb
Fix some weird multiline string things
CoolCat467 Jan 13, 2025
8bd6a1c
Fix pylint ignore comment location
CoolCat467 Jan 13, 2025
97fae8e
Fix another pylint comment
CoolCat467 Jan 13, 2025
fd09470
Remove redundant command line flags
CoolCat467 Jan 14, 2025
b5233c8
Remove now un-needed annotation for socket listeners
CoolCat467 Jan 14, 2025
ce73cb1
Re-add type ignore because of old trio version support
CoolCat467 Jan 14, 2025
e98f233
Suggestions from code review
CoolCat467 Jan 15, 2025
96e437f
Fix lint issues
CoolCat467 Jan 15, 2025
35a6235
Avoid a few type errors with fake socket listener
CoolCat467 Jan 16, 2025
f5b2014
Add/complete type annotations
CoolCat467 Jan 30, 2025
1806fa8
Merge remote-tracking branch 'root/master' into blacken
CoolCat467 Jan 30, 2025
4ec83e3
Fix merge issue
CoolCat467 Jan 30, 2025
d9081fd
Remove un-needed string concat
CoolCat467 Jan 30, 2025
2f9c10b
Fix pylint issue
CoolCat467 Jan 30, 2025
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
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ test:
$(PYTHON) -m pytest --cov=trio_websocket --no-cov-on-fail

lint:
$(PYTHON) -m black trio_websocket/ tests/ autobahn/ examples/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @jakkdl

I was requested to add type hints to this repository

Would you share some context of that conversation? (gitter link etc.)

Please see the thread here before we discuss type annotation coverage.
#167 (comment)

Would it be reasonable to revisit if the project becomes more actively maintained?

is now relevant

To me, being off life-support maintenance would mean things like 1) there is at least another person that has some history on the project and I can trust to share the load on whatever comes up going forward, 2) there is activity like revising the API, rewriting the implementation or tests, etc. I wouldn't say that adding type annotations or auto formatting means that the project is out of the woods regarding stewardship, and there are aspects of full type annotations that make maintenance harder.

Regards,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! We'll look into possible alternative libraries that are under more active support and reconsider whether to use trio-websockets. If we don't find any great alternatives, I could go with a more minimal approach and just write separate stub files that needn't touch the existing code at all, and if you don't want the extra maintenance burden of them we can just stick them in an entirely separate repo.

$(PYTHON) -m pylint trio_websocket/ tests/ autobahn/ examples/

publish:
Expand Down
55 changes: 33 additions & 22 deletions autobahn/client.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'''
"""
This test client runs against the Autobahn test server. It is based on the
test_client.py in wsproto.
'''
"""
import argparse
import json
import logging
Expand All @@ -11,28 +11,28 @@
from trio_websocket import open_websocket_url, ConnectionClosed


AGENT = 'trio-websocket'
AGENT = "trio-websocket"
MAX_MESSAGE_SIZE = 16 * 1024 * 1024
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('client')
logger = logging.getLogger("client")


async def get_case_count(url):
url = url + '/getCaseCount'
url = url + "/getCaseCount"
async with open_websocket_url(url) as conn:
case_count = await conn.get_message()
logger.info('Case count=%s', case_count)
logger.info("Case count=%s", case_count)
return int(case_count)


async def get_case_info(url, case):
url = f'{url}/getCaseInfo?case={case}'
url = f"{url}/getCaseInfo?case={case}"
async with open_websocket_url(url) as conn:
return json.loads(await conn.get_message())


async def run_case(url, case):
url = f'{url}/runCase?case={case}&agent={AGENT}'
url = f"{url}/runCase?case={case}&agent={AGENT}"
try:
async with open_websocket_url(url, max_message_size=MAX_MESSAGE_SIZE) as conn:
while True:
Expand All @@ -43,15 +43,15 @@ async def run_case(url, case):


async def update_reports(url):
url = f'{url}/updateReports?agent={AGENT}'
url = f"{url}/updateReports?agent={AGENT}"
async with open_websocket_url(url) as conn:
# This command runs as soon as we connect to it, so we don't need to
# send any messages.
pass


async def run_tests(args):
logger = logging.getLogger('trio-websocket')
logger = logging.getLogger("trio-websocket")
if args.debug_cases:
# Don't fetch case count when debugging a subset of test cases. It adds
# noise to the debug logging.
Expand All @@ -62,7 +62,7 @@ async def run_tests(args):
test_cases = list(range(1, case_count + 1))
exception_cases = []
for case in test_cases:
case_id = (await get_case_info(args.url, case))['id']
case_id = (await get_case_info(args.url, case))["id"]
if case_count:
logger.info("Running test case %s (%d of %d)", case_id, case, case_count)
else:
Expand All @@ -71,28 +71,39 @@ async def run_tests(args):
try:
await run_case(args.url, case)
except Exception: # pylint: disable=broad-exception-caught
logger.exception(' runtime exception during test case %s (%d)', case_id, case)
logger.exception(
" runtime exception during test case %s (%d)", case_id, case
)
exception_cases.append(case_id)
logger.setLevel(logging.INFO)
logger.info('Updating report')
logger.info("Updating report")
await update_reports(args.url)
if exception_cases:
logger.error('Runtime exception in %d of %d test cases: %s',
len(exception_cases), len(test_cases), exception_cases)
logger.error(
"Runtime exception in %d of %d test cases: %s",
len(exception_cases),
len(test_cases),
exception_cases,
)
sys.exit(1)


def parse_args():
''' Parse command line arguments. '''
parser = argparse.ArgumentParser(description='Autobahn client for'
' trio-websocket')
parser.add_argument('url', help='WebSocket URL for server')
"""Parse command line arguments."""
parser = argparse.ArgumentParser(
description="Autobahn client for" " trio-websocket"
)
parser.add_argument("url", help="WebSocket URL for server")
# TODO: accept case ID's rather than indices
parser.add_argument('debug_cases', type=int, nargs='*', help='Run'
' individual test cases with debug logging (optional)')
parser.add_argument(
"debug_cases",
type=int,
nargs="*",
help="Run" " individual test cases with debug logging (optional)",
)
return parser.parse_args()


if __name__ == '__main__':
if __name__ == "__main__":
args = parse_args()
trio.run(run_tests, args)
41 changes: 23 additions & 18 deletions autobahn/server.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'''
"""
This simple WebSocket server responds to text messages by reversing each
message string and sending it back.

Expand All @@ -7,34 +7,35 @@

To use SSL/TLS: install the `trustme` package from PyPI and run the
`generate-cert.py` script in this directory.
'''
"""
import argparse
import logging

import trio
from trio_websocket import serve_websocket, ConnectionClosed, WebSocketRequest

BIND_IP = '0.0.0.0'
BIND_IP = "0.0.0.0"
BIND_PORT = 9000
MAX_MESSAGE_SIZE = 16 * 1024 * 1024
logging.basicConfig()
logger = logging.getLogger('client')
logger = logging.getLogger("client")
logger.setLevel(logging.INFO)
connection_count = 0


async def main():
''' Main entry point. '''
logger.info('Starting websocket server on ws://%s:%d', BIND_IP, BIND_PORT)
await serve_websocket(handler, BIND_IP, BIND_PORT, ssl_context=None,
max_message_size=MAX_MESSAGE_SIZE)
"""Main entry point."""
logger.info("Starting websocket server on ws://%s:%d", BIND_IP, BIND_PORT)
await serve_websocket(
handler, BIND_IP, BIND_PORT, ssl_context=None, max_message_size=MAX_MESSAGE_SIZE
)


async def handler(request: WebSocketRequest):
''' Reverse incoming websocket messages and send them back. '''
"""Reverse incoming websocket messages and send them back."""
global connection_count # pylint: disable=global-statement
connection_count += 1
logger.info('Connection #%d', connection_count)
logger.info("Connection #%d", connection_count)
ws = await request.accept()
while True:
try:
Expand All @@ -43,20 +44,24 @@ async def handler(request: WebSocketRequest):
except ConnectionClosed:
break
except Exception: # pylint: disable=broad-exception-caught
logger.exception(' runtime exception handling connection #%d', connection_count)
logger.exception(
" runtime exception handling connection #%d", connection_count
)


def parse_args():
''' Parse command line arguments. '''
parser = argparse.ArgumentParser(description='Autobahn server for'
' trio-websocket')
parser.add_argument('-d', '--debug', action='store_true',
help='WebSocket URL for server')
"""Parse command line arguments."""
parser = argparse.ArgumentParser(
description="Autobahn server for" " trio-websocket"
)
parser.add_argument(
"-d", "--debug", action="store_true", help="WebSocket URL for server"
)
return parser.parse_args()


if __name__ == '__main__':
if __name__ == "__main__":
args = parse_args()
if args.debug:
logging.getLogger('trio-websocket').setLevel(logging.DEBUG)
logging.getLogger("trio-websocket").setLevel(logging.DEBUG)
trio.run(main)
71 changes: 36 additions & 35 deletions examples/client.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'''
"""
This interactive WebSocket client allows the user to send frames to a WebSocket
server, including text message, ping, and close frames.

To use SSL/TLS: install the `trustme` package from PyPI and run the
`generate-cert.py` script in this directory.
'''
"""
import argparse
import logging
import pathlib
Expand All @@ -21,62 +21,64 @@


def commands():
''' Print the supported commands. '''
print('Commands: ')
print('send <MESSAGE> -> send message')
print('ping <PAYLOAD> -> send ping with payload')
print('close [<REASON>] -> politely close connection with optional reason')
"""Print the supported commands."""
print("Commands: ")
print("send <MESSAGE> -> send message")
print("ping <PAYLOAD> -> send ping with payload")
print("close [<REASON>] -> politely close connection with optional reason")
print()


def parse_args():
''' Parse command line arguments. '''
parser = argparse.ArgumentParser(description='Example trio-websocket client')
parser.add_argument('--heartbeat', action='store_true',
help='Create a heartbeat task')
parser.add_argument('url', help='WebSocket URL to connect to')
"""Parse command line arguments."""
parser = argparse.ArgumentParser(description="Example trio-websocket client")
parser.add_argument(
"--heartbeat", action="store_true", help="Create a heartbeat task"
)
parser.add_argument("url", help="WebSocket URL to connect to")
return parser.parse_args()


async def main(args):
''' Main entry point, returning False in the case of logged error. '''
if urllib.parse.urlsplit(args.url).scheme == 'wss':
"""Main entry point, returning False in the case of logged error."""
if urllib.parse.urlsplit(args.url).scheme == "wss":
# Configure SSL context to handle our self-signed certificate. Most
# clients won't need to do this.
try:
ssl_context = ssl.create_default_context()
ssl_context.load_verify_locations(here / 'fake.ca.pem')
ssl_context.load_verify_locations(here / "fake.ca.pem")
except FileNotFoundError:
logging.error('Did not find file "fake.ca.pem". You need to run'
' generate-cert.py')
logging.error(
'Did not find file "fake.ca.pem". You need to run generate-cert.py'
)
return False
else:
ssl_context = None
try:
logging.debug('Connecting to WebSocket…')
logging.debug("Connecting to WebSocket…")
async with open_websocket_url(args.url, ssl_context) as conn:
await handle_connection(conn, args.heartbeat)
except HandshakeError as e:
logging.error('Connection attempt failed: %s', e)
logging.error("Connection attempt failed: %s", e)
return False


async def handle_connection(ws, use_heartbeat):
''' Handle the connection. '''
logging.debug('Connected!')
"""Handle the connection."""
logging.debug("Connected!")
try:
async with trio.open_nursery() as nursery:
if use_heartbeat:
nursery.start_soon(heartbeat, ws, 1, 15)
nursery.start_soon(get_commands, ws)
nursery.start_soon(get_messages, ws)
except ConnectionClosed as cc:
reason = '<no reason>' if cc.reason.reason is None else f'"{cc.reason.reason}"'
print(f'Closed: {cc.reason.code}/{cc.reason.name} {reason}')
reason = "<no reason>" if cc.reason.reason is None else f'"{cc.reason.reason}"'
print(f"Closed: {cc.reason.code}/{cc.reason.name} {reason}")


async def heartbeat(ws, timeout, interval):
'''
"""
Send periodic pings on WebSocket ``ws``.

Wait up to ``timeout`` seconds to send a ping and receive a pong. Raises
Expand All @@ -92,28 +94,27 @@ async def heartbeat(ws, timeout, interval):
:raises: ``ConnectionClosed`` if ``ws`` is closed.
:raises: ``TooSlowError`` if the timeout expires.
:returns: This function runs until cancelled.
'''
"""
while True:
with trio.fail_after(timeout):
await ws.ping()
await trio.sleep(interval)


async def get_commands(ws):
''' In a loop: get a command from the user and execute it. '''
"""In a loop: get a command from the user and execute it."""
while True:
cmd = await trio.to_thread.run_sync(input, 'cmd> ',
cancellable=True)
if cmd.startswith('ping'):
payload = cmd[5:].encode('utf8') or None
cmd = await trio.to_thread.run_sync(input, "cmd> ", cancellable=True)
if cmd.startswith("ping"):
payload = cmd[5:].encode("utf8") or None
await ws.ping(payload)
elif cmd.startswith('send'):
elif cmd.startswith("send"):
message = cmd[5:] or None
if message is None:
logging.error('The "send" command requires a message.')
else:
await ws.send_message(message)
elif cmd.startswith('close'):
elif cmd.startswith("close"):
reason = cmd[6:] or None
await ws.aclose(code=1000, reason=reason)
break
Expand All @@ -124,13 +125,13 @@ async def get_commands(ws):


async def get_messages(ws):
''' In a loop: get a WebSocket message and print it out. '''
"""In a loop: get a WebSocket message and print it out."""
while True:
message = await ws.get_message()
print(f'message: {message}')
print(f"message: {message}")


if __name__ == '__main__':
if __name__ == "__main__":
try:
if not trio.run(main, parse_args()):
sys.exit(1)
Expand Down
Loading