Repo houskeeping (#220)

* Remove deprecated Makefile

* Fix zmq test warning

* Fix type hints in config class.

* Update linting rules

* Remove filter group

* Update pre-commit hook

* Update file test to stop creating files in current dir

* Add yaml-types.

* Update README
This commit is contained in:
Felix Weiler
2025-05-06 13:35:16 +02:00
committed by GitHub
parent 6feec59b81
commit 317a09972f
8 changed files with 652 additions and 780 deletions

View File

@@ -10,7 +10,7 @@ repos:
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.7.4"
rev: "v0.11.8"
hooks:
- id: ruff
args: ["--fix", "--show-fixes"]

View File

@@ -1,56 +0,0 @@
.PHONY: install
install: ## Install the poetry environment and install the pre-commit hooks
@echo "Creating virtual environment using pyenv and poetry"
@poetry install
@poetry run pre-commit install
@poetry shell
.PHONY: check
check: ## Run code quality tools.
@echo "Checking Poetry lock file consistency with 'pyproject.toml': Running poetry lock --check"
@poetry check --lock
@echo "Linting code: Running pre-commit"
@poetry run pre-commit run -a
@echo "Static type checking: Running mypy"
@poetry run mypy .
@echo "Checking for obsolete dependencies: Running deptry"
@poetry run deptry .
.PHONY: test
test: ## Test the code with pytest
@echo "Testing code: Running pytest"
@poetry run pytest --cov --cov-config=pyproject.toml --cov-report=xml
.PHONY: build
build: clean-build ## Build wheel file using poetry
@echo "Creating wheel file"
@poetry build
.PHONY: clean-build
clean-build: ## clean build artifacts
@rm -rf dist
.PHONY: publish
publish: ## publish a release to pypi.
@echo "Publishing: Dry run."
@poetry config pypi-token.pypi $(PYPI_TOKEN)
@poetry publish --dry-run
@echo "Publishing."
@poetry publish
.PHONY: build-and-publish
build-and-publish: build publish ## Build and publish.
.PHONY: docs-test
docs-test: ## Test if documentation can be built without warnings or errors
@poetry run python3 -m sphinx docs/ docs/_build -W
.PHONY: docs
docs: ## Build and serve the documentation
@poetry run python3 -m sphinx docs docs/_build -b html
.PHONY: help
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
.DEFAULT_GOAL := help

View File

@@ -37,7 +37,7 @@ $ pip install heisskleber
## Quick Start
Here's a simple example to demonstrate how Heisskleber can be used to connect a zmq source to an mqtt sink:
Here's a simple example to demonstrate how Heisskleber can be used to connect a serial input to an mqtt output:
```python
"""
@@ -45,8 +45,8 @@ A simple forwarder that takes messages from a serial device and publishes them v
"""
import asyncio
from heisskleber.serial import SerialSubscriber, SerialConf
from heisskleber.mqtt import MqttPublisher, MqttConf
from heisskleber.serial import SerialReceiver, SerialConf
from heisskleber.mqtt import MqttSender, MqttConf
async def main():

View File

@@ -1,18 +1,12 @@
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
[project]
name = "heisskleber"
description = "Heisskleber"
authors = [
{ name = "Felix Weiler-Detjen", email = "felix@flucto.tech" },
]
license = {file = "LICENSE"}
authors = [{ name = "Felix Weiler-Detjen", email = "felix@flucto.tech" }]
license = { file = "LICENSE" }
readme = "README.md"
requires-python = ">=3.10"
dynamic = ["version"]
dependencies= [
dependencies = [
"aiomqtt>=2.3.0",
"pyserial>=3.5",
"pyyaml>=6.0.2",
@@ -26,7 +20,6 @@ Repository = "https://github.com/flucto-gmbh/heisskleber"
Documentation = "https://heisskleber.readthedocs.io"
[project.optional-dependencies]
test = [
"pytest>=8.3.3",
@@ -45,10 +38,6 @@ docs = [
"sphinx_copybutton",
"sphinx_autodoc_typehints",
]
filter = [
"numpy>=2.1.1",
"scipy>=1.14.1",
]
[tool.uv]
dev-dependencies = [
@@ -64,6 +53,7 @@ dev-dependencies = [
"pre-commit>=4.0.1",
"types-aiofiles>=24.1.0.20241221",
"freezegun>=1.5.1",
"types-pyyaml>=6.0.12.20250402",
]
package = true
@@ -94,29 +84,56 @@ line-length = 120
fix = true
[tool.ruff.lint]
select = ["ALL"]
select = [
"I", # isort
"B", # bugbear
"A", # builtins
"ASYNC", # async
"ANN", # annotations
"S", # bandit
"BLE", # blind-exception
"COM", # commas
"C4", # comprehensions
"INT", # gettext
"G", # logging-format
"T20", # print
"PYI", # pyi
"PT", # pytest-style
"Q", # quotes
"SIM", # simplify
"TC", # type-checking
"ARG", # unsued-arguments
"PTH", # use-pathlib
"C90", # complexity
"N", # pep8-naming
"PERF", # perf-lint
"E", # pycodestyle - error
"W", # pycodestyle - warning
"D", # pydocstyle
"F", # pyflakes
"UP", # pyupgrade
"RUF", # ruff
"FURB", # refurb
"TRY", # tryceratops
"PLR", # refactor
]
ignore = [
"E501", # LineTooLong
"E731", # DoNotAssignLambda
"A001", #
"D100", # Missing module docstring
"D104", # Missing package docstring
"D107", # Missing __init__ docstring
"ANN101", # Deprecated and stupid self annotation
"ANN401", # Dynamically typed annotation
"FA102", # Missing from __future__ import annotations
"FBT001", # boolean style argument in function definition
"FBT002", # boolean style argument in function definition
"ARG002", # Unused kwargs
"TD002",
"TD003",
"FIX002",
"COM812",
"ISC001",
"ARG001",
"INP001",
"TRY003", # Avoid specifying long messages in Exceptions
"EM101", # Exceptions must not use string literal
"E501", # LineTooLong
"E731", # DoNotAssignLambda
"A001", #
"D100", # Missing module docstring
"D104", # Missing package docstring
"D107", # Missing __init__ docstring
"ANN401", # Dynamically typed annotation
"FA102", # Missing from __future__ import annotations
"FBT001", # boolean style argument in function definition
"ARG002", # Unused kwargs
"COM812",
"ARG001",
"INP001",
"TRY003", # Avoid specifying long messages in Exceptions
"EM101", # Exceptions must not use string literal
]
[tool.ruff.lint.pydocstyle]
@@ -124,15 +141,20 @@ convention = "google"
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["S101", "D", "T201", "PLR2", "SLF001", "ANN"]
"bin/*" = [
"ERA001", # Found commented-out code
]
[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope = "session"
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
[tool.hatch]
version.source = "vcs"
version.path = "src/heisskleber/__init__.py"
version.raw-options = { local_scheme = "no-local-version" }
[tool.hatch.version.raw_options]
local_scheme = "no-local-version"
[tool.hatch.envs.default]
features = ["test"]

View File

@@ -3,9 +3,9 @@
import logging
from dataclasses import dataclass, fields
from pathlib import Path
from typing import Any, Literal, TextIO, TypeVar, Union, get_args, get_origin
from typing import Any, Literal, Self, TextIO, TypeVar, Union, get_args, get_origin
import yaml # type: ignore[import-untyped]
import yaml
logger = logging.getLogger("heisskleber")
@@ -76,7 +76,7 @@ class BaseConf:
raise TypeError
@classmethod
def from_dict(cls: type[ConfigType], config_dict: dict[str, Any]) -> ConfigType:
def from_dict(cls, config_dict: dict[str, Any]) -> Self:
"""Create a config instance from a dictionary, including only fields defined in the dataclass.
Arguments:
@@ -125,7 +125,7 @@ class BaseConf:
return cls(**filtered_dict)
@classmethod
def from_file(cls: type[ConfigType], file_path: str | Path) -> ConfigType:
def from_file(cls, file_path: str | Path) -> Self:
"""Create a config instance from a file - accepts yaml or json."""
path = Path(file_path)
if not path.exists():

View File

@@ -10,10 +10,11 @@ from heisskleber.file import FileConf, FileWriter
@pytest.fixture
def config() -> FileConf:
def config(tmp_path: Path) -> FileConf:
return FileConf(
rollover=3600, # 1 hour rollover
name_fmt="%Y%m%d_%H.txt",
directory=str(tmp_path),
)

View File

@@ -9,6 +9,7 @@ from heisskleber.zmq import ZmqConf, ZmqSender
@pytest.mark.asyncio
async def test_zmq_sink_send() -> None:
mock_socket = AsyncMock()
mock_socket.connect = Mock(return_value=None)
mock_context = Mock()
mock_context.socket.return_value = mock_socket

1254
uv.lock generated

File diff suppressed because it is too large Load Diff