Files
musicmouse/python-backend/pyproject.toml
Martin Bauer a0ac48ccbf Remove bloat: the design bundle zip, duplicate images, course notebooks
- claude-design/Dolphin Beats Music Player.zip (32 MB): the design tool's export of
  the mockups already unpacked next to it. Still in history (30065bb) if needed.
- claude-design/pasted-*.png: byte-identical copies of dolphin-mascot.png and
  dolphin-remote.png that nothing references.
- python-backend/notebooks: the chord-recognition course material with stale paths.
  effect_debug.ipynb stays.

The hardware models are untouched, and the history keeps its size: removing files
from the tree does not shrink the pack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:51:27 +02:00

89 lines
3.3 KiB
TOML

[project]
name = "musicmouse"
version = "2.0.0"
description = "Host backend for the MusicMouse RFID music player"
# Raspberry Pi OS (Bookworm) ships Python 3.11, and its system interpreter is what the
# device runs. Staying on it means apt and piwheels supply prebuilt armhf wheels for
# the native dependencies (pydantic-core, Pillow), instead of needing a separate
# toolchain to fetch a newer interpreter and compile them on the Pi.
requires-python = ">=3.11"
dependencies = [
"aiomqtt>=2.0",
"fastapi>=0.115",
# Podcast RSS feeds in the wild are full of small quirks (odd dates, missing
# namespaces); parsing them by hand invites silently dropping episodes.
"feedparser>=6.0",
# 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"]
# Off by default: the reactive background is nice, not required, and librosa/numpy are
# a real install cost on a Pi. Missing this group means `build_analyzer()` falls back
# to `NullAnalyzer` and the background stays at its static baseline - never a crash.
analysis = ["librosa>=1.0", "numpy>=2.0"]
[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 = "py311"
# 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.11"
strict = true
files = ["musicmouse"]
warn_unreachable = true
[[tool.mypy.overrides]]
# numpy ships its own types, but only when the `analysis` extra is installed - a plain
# checkout must still type-check clean, so it needs the same treatment as librosa.
module = ["vlc", "serial_asyncio", "ruamel.*", "librosa.*", "numpy", "feedparser"]
ignore_missing_imports = true
[[tool.mypy.overrides]]
# Recent numpy ships stubs written in 3.12+ syntax (`type X = ...`). Checking against
# the device's 3.11 makes mypy refuse to parse them and abort before checking anything
# at all - which is what happened in a dev venv that has the analysis extra. Treat the
# analysis stack as untyped instead: it is only touched by librosa_analyzer.py.
module = ["numpy", "numpy.*", "librosa", "librosa.*"]
follow_imports = "skip"
follow_imports_for_stubs = true