Skip to content

Commit

Permalink
Hatch tryout (#33)
Browse files Browse the repository at this point in the history
* Initial hatch project structure.

* Removed mypy messages

* Applied isort and black changes

* Editorial fix

* Typo in README

* Typo in README

* Updated to sphinx 7

* Doc generates (almost) OK.

* Blacked version

* Repaired documentation

* Finalized all checks

* Removed hatch matrices from github actions

* Removed mypy matrix

* Removed mypy matrix

* Removed mypy matrix
  • Loading branch information
rhjdjong authored Mar 4, 2024
1 parent fbdac05 commit a14e8d0
Show file tree
Hide file tree
Showing 30 changed files with 911 additions and 1,338 deletions.
47 changes: 47 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: test

on:
push:
pull_request:
branches: [main, master]

concurrency:
group: test-${{ github.head_ref }}
cancel-in-progress: true

env:
PYTHONUNBUFFERED: "1"
FORCE_COLOR: "1"

jobs:
run:
name: Python ${{ matrix.python-version }} on ${{ startsWith(matrix.os, 'macos-') && 'macOS' || startsWith(matrix.os, 'windows-') && 'Windows' || 'Linux' }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v3

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

- name: Install Hatch
run: pip install --upgrade hatch

- name: Run style check
run: hatch run style:check

- name: Check types
run: hatch run types:check

- name: Run static analysis
run: hatch fmt --check

- name: Run tests
run: hatch run test.py${{ matrix.python-version }}:cov
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ the functions and classes in the `sliplib` module
use a `ProtocolError` exception
to indicate protocol errors, i.e. SLIP packets with invalid byte sequences.
The `Driver` class raises the `ProtocolError` exception
as soon as a complete SLIP packet with an invalid byte sequence is received .
as soon as a complete SLIP packet with an invalid byte sequence is received.
The `SlipWrapper` class and its subclasses catch the `ProtocolError`\s
raised by the `Driver` class, and re-raise them when
an attempt is made to read the contents of a SLIP packet that contained
Expand Down
101 changes: 37 additions & 64 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -1,84 +1,57 @@
# ruff: noqa: INP001

# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
import pkg_resources

_sources = [
os.path.abspath(os.path.join('..', '..', 'src')),
os.path.abspath(os.path.join('..', '..', 'examples')),
]
sys.path[0:0] = _sources


# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = 'sliplib'
copyright = '2020, Ruud de Jong'
author = 'Ruud de Jong'

try:
# The full version, including alpha/beta/rc tags
release = pkg_resources.get_distribution(f'{project}').version
except pkg_resources.DistributionNotFound:
print(f'To build the documentation, the distribution information of {project}')
print('has to be available. Either install the package into your')
print('development environment or run "setup.py develop" or "pip install -e"')
print('to setup the metadata. A virtual environment is recommended!')
sys.exit(1)
del pkg_resources

version = '.'.join(release.split('.')[:2]) # version contains major.minor.

project = "SlipLib"
copyright = "2024, Ruud de Jong" # noqa: A001
author = "Ruud de Jong"
github_username = "rhjdjong"
github_repository = "https://github.com/rhjdjong/SlipLib/"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

# Include the example directory in sys.path\
# in order to generate the documentation for the examples
sys.path.append(os.path.abspath(os.path.join("..", "..", "examples")))

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.napoleon',
'sphinx.ext.autodoc.typehints',
"sphinx.ext.autodoc",
"sphinx.ext.autodoc.typehints",
"sphinx.ext.intersphinx",
"sphinx.ext.napoleon",
"sphinx.ext.viewcode",
"sphinx_rtd_theme",
"sphinx_tabs.tabs",
"sphinx_toolbox.more_autodoc.autoprotocol",
"sphinx_toolbox.more_autodoc.typehints",
"sphinx_toolbox.more_autodoc.typevars",
"sphinx_toolbox.more_autodoc.variables",
"sphinx_autodoc_typehints",
]

autoclass_content = 'both'
autodoc_typehints = 'description'
add_module_names = False
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None)
}

napoleon_use_rtype = True

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
templates_path = ["_templates"]
exclude_patterns = []

napoleon_google_docstring = True
# napoleon_use_rtype = False
autoclass_content = "both"
autodoc_typehints = "description"
autodoc_type_aliases = {}
add_module_names = False
intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}

# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_theme = "sphinx_rtd_theme"
html_static_path = ["_static"]
19 changes: 11 additions & 8 deletions examples/echoserver/client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# ruff: noqa: T201

# Copyright (c) 2020 Ruud de Jong
# This file is part of the SlipLib project which is released under the MIT license.
# See https://github.com/rhjdjong/SlipLib for details.
Expand All @@ -13,24 +15,25 @@
This is repeated until the user enters an empty message.
"""

# ruff: noqa: T201
import sys

import sliplib

if __name__ == '__main__':
if len(sys.argv) != 2:
if __name__ == "__main__":
if len(sys.argv) != 2: # noqa: PLR2004
print("Usage: python client.py <port>")
sys.exit(1)
port = sys.argv[1]
print("Connecting to server on port {}".format(port))
sock = sliplib.SlipSocket.create_connection(('localhost', int(port)))
print("Connected to {}".format(sock.getpeername()))
print(f"Connecting to server on port {port}")
sock = sliplib.SlipSocket.create_connection(("localhost", int(port)))
print(f"Connected to {sock.getpeername()}")

while True:
message = input('Message>')
message = input("Message>")
if not message:
break
b_message = bytes(message, 'utf-8')
b_message = bytes(message, "utf-8")
sock.send_msg(b_message)
b_reply = sock.recv_msg()
print('Response:', b_reply)
print("Response:", b_reply)
49 changes: 31 additions & 18 deletions examples/echoserver/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,61 +17,74 @@
and sends it back to the client.
"""

# ruff: noqa: T201

from __future__ import annotations

import socket
import sys
from socketserver import TCPServer
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
if sys.version_info >= (3, 12): # noqa: UP036
from collections.abc import Buffer
else:
from typing_extensions import Buffer

from _socket import dup

from _socket import dup # type: ignore
from sliplib import SlipRequestHandler


class _ChattySocket(socket.socket):
"""A socket subclass that prints the raw data that is received and sent."""

def __init__(self, sock):
def __init__(self, sock: socket.socket) -> None:
fd = dup(sock.fileno())
super().__init__(sock.family, sock.type, sock.proto, fileno=fd)
super().settimeout(sock.gettimeout())

def recv(self, chunksize):
data = super().recv(chunksize)
print('Raw data received:', data)
def recv(self, chunksize: int, *args: Any) -> bytes:
data = super().recv(chunksize, *args)
print("Raw data received:", data)
return data

def sendall(self, data):
print('Sending raw data:', data)
super().sendall(data)
def sendall(self, data: Buffer, *args: Any) -> None:
print("Sending raw data:", data)
super().sendall(data, *args)


class SlipHandler(SlipRequestHandler):
"""A SlipRequestHandler that echoes the received message with the bytes in reversed order."""

def setup(self):
def setup(self) -> None:
self.request = _ChattySocket(self.request)
print("Incoming connection from {}".format(self.request.getpeername()))
print(f"Incoming connection from {self.request.getpeername()}")
super().setup()

# Dedicated handler to show the encoded bytes.
def handle(self):
def handle(self) -> None:
while True:
message = self.request.recv_msg()
print('Decoded data:', message)
print("Decoded data:", message)
if message:
self.request.send_msg(bytes(reversed(message)))
else:
print('Closing down')
print("Closing down")
break


class TCPServerIPv6(TCPServer):
"""An IPv6 TCPServer"""

address_family = socket.AF_INET6


if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1].lower() == 'ipv6':
server = TCPServerIPv6(('localhost', 0), SlipHandler) # type: TCPServer
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1].lower() == "ipv6":
server = TCPServerIPv6(("localhost", 0), SlipHandler) # type: TCPServer
else:
server = TCPServer(('localhost', 0), SlipHandler)
print('Slip server listening on localhost, port', server.server_address[1])
server = TCPServer(("localhost", 0), SlipHandler)
print("Slip server listening on localhost, port", server.server_address[1])
server.handle_request()
4 changes: 0 additions & 4 deletions mypy.ini

This file was deleted.

Loading

0 comments on commit a14e8d0

Please sign in to comment.