Skip to content

Commit

Permalink
Merge pull request #30 from tarasko/feature/fix_lint_errors
Browse files Browse the repository at this point in the history
Feature/fix lint errors
  • Loading branch information
tarasko authored Dec 10, 2024
2 parents f1a6d38 + 1827779 commit 07c9321
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 110 deletions.
4 changes: 4 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[flake8]
exclude = .git,__pycache__,docs/source/conf.py,old,build,dist
max-complexity = 10
max-line-length = 127
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
flake8 . --count --statistics
mypy-checks:
strategy:
Expand Down
4 changes: 0 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ Connects to an echo server, sends a message and disconnect upon reply.
.. code-block:: python
import asyncio
import uvloop
from picows import ws_connect, WSFrame, WSTransport, WSListener, WSMsgType, WSCloseCode
class ClientListener(WSListener):
Expand All @@ -97,7 +96,6 @@ Connects to an echo server, sends a message and disconnect upon reply.
if __name__ == '__main__':
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
asyncio.run(main("ws://127.0.0.1:9001"))
This prints:
Expand All @@ -112,7 +110,6 @@ Echo server
.. code-block:: python
import asyncio
import uvloop
from picows import ws_create_server, WSFrame, WSTransport, WSListener, WSMsgType, WSUpgradeRequest
class ServerClientListener(WSListener):
Expand All @@ -138,7 +135,6 @@ Echo server
await server.serve_forever()
if __name__ == '__main__':
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
asyncio.run(main())
Expand Down
187 changes: 113 additions & 74 deletions examples/echo_client_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@
from picows import WSFrame, WSTransport, WSListener, ws_connect, WSMsgType
from time import time

_logger = getLogger(__name__)

try:
from examples.echo_client_cython import picows_main_cython
except ImportError:
picows_main_cython = None


RPS: Dict[str, List[float]] = {"ssl": [], "plain": []}
NAMES: List[str] = []
_logger = getLogger(__name__)


def create_client_ssl_context():
Expand Down Expand Up @@ -116,7 +121,101 @@ async def aiohttp_main(url: str, data: bytes, duration: int, ssl_context):
break


if __name__ == '__main__':
def run_for_websockets_library(plain_url, ssl_url, ssl_context, msg, duration):
global NAMES, RPS
_, rps = asyncio.run(websockets_main(plain_url, msg, duration, None))
RPS["plain"].append(rps)
name, rps = asyncio.run(websockets_main(ssl_url, msg, duration, ssl_context))
RPS["ssl"].append(rps)
NAMES.append(name)


def run_for_aiohttp_library(plain_url, ssl_url, ssl_context, msg, duration):
global NAMES, RPS
_, rps = asyncio.run(aiohttp_main(plain_url, msg, duration, None))
RPS["plain"].append(rps)
name, rps = asyncio.run(aiohttp_main(ssl_url, msg, duration, ssl_context))
RPS["ssl"].append(rps)
NAMES.append(name)


def run_picows_client(plain_url, ssl_url, ssl_context, msg, duration):
global NAMES, RPS
_, rps = asyncio.run(picows_main(plain_url, msg, duration, None))
RPS["plain"].append(rps)
name, rps = asyncio.run(picows_main(ssl_url, msg, duration, ssl_context))
RPS["ssl"].append(rps)
NAMES.append(name)


def run_picows_cython_plain_client(plain_url, ssl_url, ssl_context, msg, duration):
global NAMES, RPS
print("Run picows cython plain client")
rps = asyncio.run(picows_main_cython(plain_url, msg, duration, None))
RPS["plain"].append(rps)


def run_picows_cython_ssl_client(plain_url, ssl_url, ssl_context, msg, duration):
global NAMES, RPS
print("Run picows cython ssl client")
rps = asyncio.run(picows_main_cython(ssl_url, msg, duration, ssl_context))
RPS["ssl"].append(rps)


def run_boost_beast_client(args):
global NAMES, RPS

print("Run boost.beast plain client")
pr = subprocess.run([args.boost_client, b"0",
args.host.encode(),
args.plain_port.encode(),
args.msg_size, args.duration],
shell=False, check=True, capture_output=True)
_, rps = pr.stdout.split(b":", 2)
RPS["plain"].append(int(rps.decode()))

print("Run boost.beast ssl client")
pr = subprocess.run([args.boost_client, b"1",
args.host.encode(),
args.ssl_port.encode(),
args.msg_size, args.duration],
shell=False, check=True, capture_output=True)
name, rps = pr.stdout.split(b":", 2)
RPS["ssl"].append(int(rps.decode()))
NAMES.append("c++ boost.beast")


def print_result_and_plot(loop_name, msg_size):
for k, v in RPS.items():
print(k.replace("\n", " "), v)

print("names:", " | ".join(n.replace("\n", " ") for n in NAMES))

try:
import matplotlib.pyplot as plt

fig, ax = plt.subplots(layout='constrained')

x = np.arange(len(NAMES))
width = 0.25 # the width of the bars
multiplier = 0

for cl_type, measurement in RPS.items():
offset = width * multiplier
ax.bar(x + offset, measurement, width, label=cl_type)
multiplier += 1

ax.set_ylabel('request/second')
ax.set_title(f'Echo round-trip performance \n({loop_name}, msg_size={msg_size})')
ax.set_xticks(x + width, NAMES)
ax.legend(loc='upper left', ncols=3)

plt.show()
except ImportError:
pass


def main():
parser = argparse.ArgumentParser(description="Benchmark for the various websocket clients",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--host", default="127.0.0.1", help="Server host")
Expand Down Expand Up @@ -146,87 +245,27 @@ async def aiohttp_main(url: str, data: bytes, duration: int, ssl_context):
ssl_url = f"wss://{args.host}:{args.ssl_port}/"

if not args.picows_plain_only and not args.picows_ssl_only:
_, rps = asyncio.run(websockets_main(plain_url, msg, duration, None))
RPS["plain"].append(rps)
name, rps = asyncio.run(websockets_main(ssl_url, msg, duration, ssl_context))
RPS["ssl"].append(rps)
NAMES.append(name)

_, rps = asyncio.run(aiohttp_main(plain_url, msg, duration, None))
RPS["plain"].append(rps)
name, rps = asyncio.run(aiohttp_main(ssl_url, msg, duration, ssl_context))
RPS["ssl"].append(rps)
NAMES.append(name)

_, rps = asyncio.run(picows_main(plain_url, msg, duration, None))
RPS["plain"].append(rps)
name, rps = asyncio.run(picows_main(ssl_url, msg, duration, ssl_context))
RPS["ssl"].append(rps)
NAMES.append(name)
run_for_websockets_library(plain_url, ssl_url, ssl_context, msg, duration)
run_for_aiohttp_library(plain_url, ssl_url, ssl_context, msg, duration)
run_picows_client(plain_url, ssl_url, ssl_context, msg, duration)

if picows_main_cython is not None:
NAMES.append("picows\ncython client")

try:
from examples.echo_client_cython import picows_main_cython
if not args.picows_ssl_only:
print("Run picows cython plain client")
rps = asyncio.run(picows_main_cython(plain_url, msg, duration, None))
RPS["plain"].append(rps)
run_picows_cython_plain_client(plain_url, ssl_url, ssl_context, msg, duration)

if not args.picows_plain_only:
print("Run picows cython ssl client")
rps = asyncio.run(picows_main_cython(ssl_url, msg, duration, ssl_context))
RPS["ssl"].append(rps)

NAMES.append("picows\ncython client")
except ImportError:
pass
run_picows_cython_ssl_client(plain_url, ssl_url, ssl_context, msg, duration)

if not args.picows_plain_only and not args.picows_ssl_only and args.boost_client is not None:
print("Run boost.beast plain client")
pr = subprocess.run([args.boost_client, b"0",
args.host.encode(),
args.plain_port.encode(),
args.msg_size, args.duration],
shell=False, check=True, capture_output=True)
_, rps = pr.stdout.split(b":", 2)
RPS["plain"].append(int(rps.decode()))

print("Run boost.beast ssl client")
pr = subprocess.run([args.boost_client, b"1",
args.host.encode(),
args.ssl_port.encode(),
args.msg_size, args.duration],
shell=False, check=True, capture_output=True)
name, rps = pr.stdout.split(b":", 2)
RPS["ssl"].append(int(rps.decode()))
NAMES.append("c++ boost.beast")
run_boost_beast_client(args)

if args.picows_plain_only or args.picows_ssl_only:
exit()

for k, v in RPS.items():
print(k.replace("\n", " "), v)

print("names:", " | ".join(n.replace("\n", " ") for n in NAMES))
print_result_and_plot(loop_name, msg_size)

try:
import matplotlib.pyplot as plt

fig, ax = plt.subplots(layout='constrained')

x = np.arange(len(NAMES))
width = 0.25 # the width of the bars
multiplier = 0

for cl_type, measurement in RPS.items():
offset = width * multiplier
rects = ax.bar(x + offset, measurement, width, label=cl_type)
multiplier += 1

ax.set_ylabel('request/second')
ax.set_title(f'Echo round-trip performance \n({loop_name}, msg_size={msg_size})')
ax.set_xticks(x + width, NAMES)
ax.legend(loc='upper left', ncols=3)

plt.show()
except ImportError:
pass
if __name__ == '__main__':
main()
3 changes: 2 additions & 1 deletion examples/okx_roundtrip_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import logging

import picows
from picows import ws_connect, WSFrame, WSTransport, WSListener, WSMsgType, WSCloseCode
from picows import ws_connect, WSTransport, WSListener

EXPECTED_OKX_ROUNDTRIP_TIME = 0.1


class ClientListener(WSListener):
async def check_okx_roundtrip_time(self, transport: picows.WSTransport):
rtts = await transport.measure_roundtrip_time(5)
Expand Down
2 changes: 0 additions & 2 deletions examples/readme_client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import asyncio
import uvloop
from picows import ws_connect, WSFrame, WSTransport, WSListener, WSMsgType, WSCloseCode


Expand All @@ -19,5 +18,4 @@ async def main(url):


if __name__ == '__main__':
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
asyncio.run(main("ws://127.0.0.1:9001"))
2 changes: 0 additions & 2 deletions examples/readme_server.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import asyncio
import uvloop
from picows import ws_create_server, WSFrame, WSTransport, WSListener, \
WSMsgType, WSUpgradeRequest

Expand Down Expand Up @@ -30,5 +29,4 @@ def listener_factory(r: WSUpgradeRequest):


if __name__ == '__main__':
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
asyncio.run(main())
18 changes: 15 additions & 3 deletions examples/subprotocol_negotiation.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
ws_create_server, WSUpgradeResponse, WSUpgradeResponseWithListener, \
WSUpgradeRequest


class OCPPServerClientListener(WSListener):
def on_ws_connected(self, transport: WSTransport):
print("New client connected, negotiated protocol: ", transport.response.headers["Sec-WebSocket-Protocol"])
Expand All @@ -19,15 +20,26 @@ def on_ws_connected(self, transport: WSTransport):
async def main():
def server_client_factory(request: WSUpgradeRequest):
if "ocpp2.1" in request.headers["Sec-WebSocket-Protocol"]:
return WSUpgradeResponseWithListener(WSUpgradeResponse.create_101_response(extra_headers={"Sec-WebSocket-Protocol": "ocpp2.1"}), OCPPServerClientListener())
return WSUpgradeResponseWithListener(
WSUpgradeResponse.create_101_response(extra_headers={"Sec-WebSocket-Protocol": "ocpp2.1"}),
OCPPServerClientListener())
else:
return WSUpgradeResponseWithListener(WSUpgradeResponse.create_error_response(HTTPStatus.BAD_REQUEST, b"requested websocket subprotocol is not supported"), None)
return WSUpgradeResponseWithListener(
WSUpgradeResponse.create_error_response(
HTTPStatus.BAD_REQUEST,
b"requested websocket subprotocol is not supported"
),
None)

server = await ws_create_server(server_client_factory, "127.0.0.1", 27001)
asyncio.create_task(server.serve_forever())

# Client request support for either ocpp1.6 or ocpp2.1 protocol
(transport, client) = await ws_connect(OCPPClientListener, "ws://127.0.0.1:27001/", extra_headers={"Sec-WebSocket-Protocol": "ocpp1.6,ocpp2.1"})
(transport, client) = await ws_connect(
OCPPClientListener,
"ws://127.0.0.1:27001/",
extra_headers={"Sec-WebSocket-Protocol": "ocpp1.6,ocpp2.1"}
)

transport.disconnect()
await transport.wait_disconnected()
Expand Down
Loading

0 comments on commit 07c9321

Please sign in to comment.