From ad660afae3d79132e53b01a9184bccbba57efc11 Mon Sep 17 00:00:00 2001 From: zebra Date: Mon, 8 Jun 2026 19:49:18 -0700 Subject: [PATCH] feat(server): load musicfetch binary as importable module Co-Authored-By: Claude Sonnet 4.6 --- server/__init__.py | 0 server/mf.py | 24 ++++++++++++++++++++++++ tests/__init__.py | 0 tests/test_mf_loader.py | 15 +++++++++++++++ 4 files changed, 39 insertions(+) create mode 100644 server/__init__.py create mode 100644 server/mf.py create mode 100644 tests/__init__.py create mode 100644 tests/test_mf_loader.py diff --git a/server/__init__.py b/server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/server/mf.py b/server/mf.py new file mode 100644 index 0000000..8c60b77 --- /dev/null +++ b/server/mf.py @@ -0,0 +1,24 @@ +"""Loads the sibling standalone `musicfetch` script (no .py extension) as a +module and re-exports the symbols the API reuses. This is the single seam +between the REST API and the CLI; musicfetch itself is unchanged.""" +import importlib.machinery +import importlib.util +import os + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_MF_PATH = os.environ.get("MUSICFETCH_BIN", os.path.join(_HERE, "..", "musicfetch")) + +# spec_from_file_location returns None for extension-less files, so use +# SourceFileLoader directly to handle the bare `musicfetch` binary. +_loader = importlib.machinery.SourceFileLoader("musicfetch_core", _MF_PATH) +_spec = importlib.util.spec_from_loader("musicfetch_core", _loader) +_mod = importlib.util.module_from_spec(_spec) +_spec.loader.exec_module(_mod) # safe: musicfetch guards main() behind __main__ + +Hit = _mod.Hit +build_combined_hits = _mod.build_combined_hits +pick = _mod.pick +act_youtube = _mod.act_youtube +act_lidarr_album = _mod.act_lidarr_album +act_lidarr_artist = _mod.act_lidarr_artist +QUALITY_CHOICES = _mod.QUALITY_CHOICES diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_mf_loader.py b/tests/test_mf_loader.py new file mode 100644 index 0000000..21d3e4e --- /dev/null +++ b/tests/test_mf_loader.py @@ -0,0 +1,15 @@ +def test_mf_reexports_musicfetch_symbols(): + from server import mf + assert hasattr(mf, "Hit") + assert callable(mf.build_combined_hits) + assert callable(mf.pick) + assert callable(mf.act_youtube) + assert callable(mf.act_lidarr_album) + assert callable(mf.act_lidarr_artist) + + +def test_mf_hit_constructs(): + from server import mf + h = mf.Hit(source="youtube", kind="track", title="x", artist="y") + assert h.source == "youtube" + assert h.artist == "y"