feat(server): load musicfetch binary as importable module

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 19:49:18 -07:00
parent 11a57bfa67
commit ad660afae3
4 changed files with 39 additions and 0 deletions

0
server/__init__.py Normal file
View File

24
server/mf.py Normal file
View File

@@ -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

0
tests/__init__.py Normal file
View File

15
tests/test_mf_loader.py Normal file
View File

@@ -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"