Skip to content
Open
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
31 changes: 31 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version:
- 3.12
job:
- mypy .
- ruff format --check .
- ruff check .
Comment on lines +13 to +14
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We'd like to maintain support for older systems. Could you check how far we could get with something more tried and tested like flake8 and pylint?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I didn't use these for quite a while, and I didn't use flake8 since migrating to ruff around a year ago. It should include majority of flake8 and some of the pylint checks though.


steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same as above.

uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Install dependencies
run: uv sync --all-extras --all-groups

- run: uv run ${{ matrix.job }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ target.cfg.d
build/
dist/
*.egg-info

# Intellij IDEs
.idea
Comment on lines +13 to +15
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Local settings folders/files shouldn't be added to the repo.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I thought intellij-based ide's are kind of common and adding that to .gitignore made sense, so contributors don't have do do that themselves. I can remove that if you want though.

51 changes: 51 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
[project]
name = "websockify"
version = "0.13.0"
description = "Websockify."
readme = "README.md"
authors = [
{ name = "Joel Martin", email = "github@martintribe.org" }
]
requires-python = ">=3.6"
dependencies = [
"jwcrypto>=1.5.1",
"numpy>=1.19.0",
"redis>=4.3.0",
"requests>=2.27.0",
Comment on lines +11 to +14
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not sure about targeting versions here, where did these come from?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

They're probably the latest compatible releases with 3.7, I don't quite remember if I pulled these manually or uv did it.

]
classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
keywords = ["noVNC", "websockify"]
license = { text = "LGPLv3" }

[project.urls]
Repository ="https://github.com/novnc/websockify"

[project.scripts]
websockify = "websockify.websocketproxy:websockify_init"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"


[tool.hatch.build.targets.wheel]
packages = [
"websockify",
]

[dependency-groups]
dev = [
"mypy>=0.971",
"ruff>=0.0.17",
]
80 changes: 40 additions & 40 deletions setup.py
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shouldn't setup.py be removed if we are converting to pyproject.toml?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, it could be removed later.

Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
from setuptools import setup, find_packages

version = '0.13.0'
name = 'websockify'
long_description = open("README.md").read() + "\n" + \
open("CHANGES.txt").read() + "\n"
version = "0.13.0"
name = "websockify"
long_description = open("README.md").read() + "\n" + open("CHANGES.txt").read() + "\n"

setup(name=name,
version=version,
description="Websockify.",
long_description=long_description,
long_description_content_type="text/markdown",
classifiers=[
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
keywords='noVNC websockify',
license='LGPLv3',
url="https://github.com/novnc/websockify",
author="Joel Martin",
author_email="github@martintribe.org",

packages=['websockify'],
include_package_data=True,
install_requires=[
'numpy', 'requests',
'jwcrypto',
'redis',
],
zip_safe=False,
entry_points={
'console_scripts': [
'websockify = websockify.websocketproxy:websockify_init',
setup(
name=name,
version=version,
description="Websockify.",
long_description=long_description,
long_description_content_type="text/markdown",
classifiers=[
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
keywords="noVNC websockify",
license="LGPLv3",
url="https://github.com/novnc/websockify",
author="Joel Martin",
author_email="github@martintribe.org",
packages=["websockify"],
include_package_data=True,
install_requires=[
"numpy",
"requests",
"jwcrypto",
"redis",
],
zip_safe=False,
entry_points={
"console_scripts": [
"websockify = websockify.websocketproxy:websockify_init",
]
},
)
},
)
45 changes: 28 additions & 17 deletions tests/echo.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
#!/usr/bin/env python

'''
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this is a bit too strict. Can the linter be configured to ignore these types of changes?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, that can be configured to preserve quotes, but the default style is using ", I personally prefer it that way.
https://docs.astral.sh/ruff/settings/#format_quote-style

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Personally I don't think it matters that much, having one quote style is better in my opinion, plus developers still can use whatever quote character they want, it would just get reformatted later, but choice is up to you on that.

"""
A WebSocket server that echos back whatever it receives from the client.
Copyright 2010 Joel Martin
Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)

You can make a cert/key with openssl using:
openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
as taken from http://docs.python.org/dev/library/ssl.html#certificates
'''
"""

import os, sys, select, optparse, logging
sys.path.insert(0,os.path.join(os.path.dirname(__file__), ".."))

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from websockify.websockifyserver import WebSockifyServer, WebSockifyRequestHandler


class WebSocketEcho(WebSockifyRequestHandler):
"""
WebSockets server that echos back whatever is received from the
client. """
client."""

buffer_size = 8096

def new_websocket_client(self):
Expand All @@ -33,9 +36,11 @@ def new_websocket_client(self):
while True:
wlist = []

if cqueue or c_pend: wlist.append(self.request)
if cqueue or c_pend:
wlist.append(self.request)
Comment on lines +39 to +40
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a nice improvement!

ins, outs, excepts = select.select(rlist, wlist, [], 1)
if excepts: raise Exception("Socket exception")
if excepts:
raise Exception("Socket exception")

if self.request in outs:
# Send queued target data to the client
Expand All @@ -50,20 +55,27 @@ def new_websocket_client(self):
if closed:
break

if __name__ == '__main__':
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In general, we want the choice of quotation characters to be up the developer.


if __name__ == "__main__":
parser = optparse.OptionParser(usage="%prog [options] listen_port")
parser.add_option("--verbose", "-v", action="store_true",
help="verbose messages and per frame traffic")
parser.add_option("--cert", default="self.pem",
help="SSL certificate file")
parser.add_option("--key", default=None,
help="SSL key file (if separate from cert)")
parser.add_option("--ssl-only", action="store_true",
help="disallow non-encrypted connections")
parser.add_option(
"--verbose",
"-v",
action="store_true",
help="verbose messages and per frame traffic",
)
parser.add_option("--cert", default="self.pem", help="SSL certificate file")
parser.add_option(
"--key", default=None, help="SSL key file (if separate from cert)"
)
parser.add_option(
"--ssl-only", action="store_true", help="disallow non-encrypted connections"
)
Comment on lines +61 to +73
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think I can guess the strategy it had when formatting here, but I think this made the code less readable.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I think generally you'd want that code to be either on one line:

parser.add_option("--verbose", "-v", action="store_true", help="verbose messages and per frame traffic")

or like this:

parser.add_option(
    "--verbose",
    "-v",
    action="store_true",
    help="verbose messages and per frame traffic",
)

To force the second style you'd need to add , to the last argument, but I think formatter could be disabled for certain code blocks: https://docs.astral.sh/ruff/formatter/#format-suppression

(opts, args) = parser.parse_args()

try:
if len(args) != 1: raise ValueError
if len(args) != 1:
raise ValueError
opts.listen_port = int(args[0])
except ValueError:
parser.error("Invalid arguments")
Expand All @@ -73,4 +85,3 @@ def new_websocket_client(self):
opts.web = "."
server = WebSockifyServer(WebSocketEcho, **opts.__dict__)
server.start_server()

31 changes: 21 additions & 10 deletions tests/echo_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
import optparse
import select

sys.path.insert(0,os.path.join(os.path.dirname(__file__), ".."))
from websockify.websocket import WebSocket, \
WebSocketWantReadError, WebSocketWantWriteError
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from websockify.websocket import (
WebSocket,
WebSocketWantReadError,
WebSocketWantWriteError,
)

parser = optparse.OptionParser(usage="%prog URL")
(opts, args) = parser.parse_args()
Expand All @@ -22,30 +25,37 @@
sock.connect(URL)
print("Connected.")


def send(msg):
while True:
try:
sock.sendmsg(msg)
break
except WebSocketWantReadError:
msg = ''
msg = ""
ins, outs, excepts = select.select([sock], [], [])
if excepts: raise Exception("Socket exception")
if excepts:
raise Exception("Socket exception")
except WebSocketWantWriteError:
msg = ''
msg = ""
ins, outs, excepts = select.select([], [sock], [])
if excepts: raise Exception("Socket exception")
if excepts:
raise Exception("Socket exception")


def read():
while True:
try:
return sock.recvmsg()
except WebSocketWantReadError:
ins, outs, excepts = select.select([sock], [], [])
if excepts: raise Exception("Socket exception")
if excepts:
raise Exception("Socket exception")
except WebSocketWantWriteError:
ins, outs, excepts = select.select([], [sock], [])
if excepts: raise Exception("Socket exception")
if excepts:
raise Exception("Socket exception")


counter = 1
while True:
Expand All @@ -56,7 +66,8 @@ def read():

while True:
ins, outs, excepts = select.select([sock], [], [], 1.0)
if excepts: raise Exception("Socket exception")
if excepts:
raise Exception("Socket exception")

if ins == []:
break
Expand Down
2 changes: 1 addition & 1 deletion tests/latency.py
Loading