Files
musicmouse/python-backend/pyproject.toml
Martin Bauer a8ed350aec Add "Mein Zimmer" room-control page (Home Assistant, proxied through the backend)
Implements the room-control page from the design mockup: a scenes row above cards
for shutters, color lamps, and brightness-only lamps, all driven by a new
`general.ha` config section (server URL, token, ordered device/scene lists).

The backend proxies every Home Assistant call server-side (GET/POST /api/ha/...)
rather than the browser calling Home Assistant directly, so the long-lived token
never leaves the LAN device and Home Assistant's own CORS settings don't need to
know about musicmouse at all. Card kind (shutter/color/brightness-only) is
inferred at runtime from what Home Assistant reports about each entity, not
configured explicitly.

Also stops tracking python-backend/config.yml, which had drifted into the repo
despite its own header saying it shouldn't be - it now carries real credentials
locally and needs to stay untracked.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 23:45:29 +02:00

67 lines
1.9 KiB
TOML

[project]
name = "musicmouse"
version = "2.0.0"
description = "Host backend for the MusicMouse RFID music player"
requires-python = ">=3.13"
dependencies = [
"aiomqtt>=2.0",
"fastapi>=0.115",
# Also what tests drive the ASGI app with - plain httpx is deprecated in favour of
# this for exactly that. Runtime uses it to proxy the room page's Home Assistant
# calls, so the long-lived token never has to leave the backend.
"httpx2>=2.12",
"mutagen>=1.47",
"pillow>=10.4",
"pydantic>=2.7",
"pyserial-asyncio>=0.6",
"python-vlc>=3.0",
"ruamel.yaml>=0.18",
"uvicorn>=0.30",
# uvicorn ships no websocket implementation of its own; without this the
# state-push upgrade is answered with a 404 and the UI never updates.
"websockets>=13",
]
[project.optional-dependencies]
dev = ["mypy>=1.10", "pytest-asyncio>=0.23", "pytest>=8.0", "ruff>=0.5"]
[project.scripts]
musicmouse = "musicmouse.__main__:main"
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find]
include = ["musicmouse*"]
[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
filterwarnings = ["error"]
[tool.ruff]
line-length = 100
target-version = "py313"
# Course material and scratch work, not part of the backend. See notebooks/README.md.
extend-exclude = ["notebooks"]
[tool.ruff.lint]
select = ["ARG", "B", "C4", "E", "F", "I", "N", "PTH", "RUF", "SIM", "UP", "W"]
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["ARG001"]
# Entity is an ABC with optional hooks: empty bodies and unused args are the point.
"musicmouse/services/mqtt/entity.py" = ["ARG002", "B027"]
[tool.mypy]
python_version = "3.13"
strict = true
files = ["musicmouse"]
warn_unreachable = true
[[tool.mypy.overrides]]
module = ["vlc", "serial_asyncio", "ruamel.*"]
ignore_missing_imports = true