mirror of
https://github.com/OMGeeky/flucto-heisskleber.git
synced 2025-12-26 16:07:50 +01:00
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:
@@ -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"]
|
||||
|
||||
56
Makefile
56
Makefile
@@ -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
|
||||
@@ -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():
|
||||
|
||||
102
pyproject.toml
102
pyproject.toml
@@ -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"]
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user