From 873b3aa65b9b4e05d1c217d9e821e12e1577aaa2 Mon Sep 17 00:00:00 2001 From: Jamie Gravendeel Date: Tue, 12 Aug 2025 14:09:53 +0200 Subject: [PATCH] Split up data and cache with XDG directories (#2304) --- music_assistant/__main__.py | 40 +++++++++++++++++++++++++++---------- music_assistant/mass.py | 4 ++-- tests/conftest.py | 6 ++++-- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/music_assistant/__main__.py b/music_assistant/__main__.py index a2b2e3e7..50feb951 100644 --- a/music_assistant/__main__.py +++ b/music_assistant/__main__.py @@ -35,17 +35,32 @@ def get_arguments() -> argparse.Namespace: """Arguments handling.""" parser = argparse.ArgumentParser(description="MusicAssistant") - default_data_dir = os.getenv("APPDATA") if os.name == "nt" else os.path.expanduser("~") - if not default_data_dir: - parser.error("Unable to find default data dir") - default_data_dir = os.path.join(default_data_dir, ".musicassistant") + if os.path.isdir(old_data_dir := os.path.join(os.path.expanduser("~"), ".musicassistant")): + data_dir = old_data_dir + cache_dir = os.path.join(data_dir, ".cache") + else: + data_dir = os.path.join( + os.getenv("XDG_DATA_HOME", os.path.join(os.path.expanduser("~"), ".local", "share")), + "music-assistant", + ) + cache_dir = os.path.join( + os.getenv("XDG_CACHE_HOME", os.path.join(os.path.expanduser("~"), ".cache")), + "music-assistant", + ) parser.add_argument( + "--data-dir", "-c", "--config", - metavar="path_to_config_dir", - default=default_data_dir, - help="Directory that contains the MusicAssistant configuration", + metavar="path_to_data_dir", + default=data_dir, + help="Directory that contains MusicAssistant persistent data", + ) + parser.add_argument( + "--cache-dir", + metavar="path_to_cache_dir", + default=cache_dir, + help="Directory that contains MusicAssistant cache data", ) parser.add_argument( "--log-level", @@ -59,6 +74,7 @@ def get_arguments() -> argparse.Namespace: action=argparse.BooleanOptionalAction, help="Start in safe mode (core controllers only, no providers)", ) + return parser.parse_args() @@ -174,9 +190,11 @@ def main() -> None: """Start MusicAssistant.""" # parse arguments args = get_arguments() - data_dir = args.config - if not os.path.isdir(data_dir): - os.makedirs(data_dir) + + data_dir = args.data_dir + cache_dir = args.cache_dir + + os.makedirs(data_dir, exist_ok=True) # TEMP: override options though hass config file hass_options_file = os.path.join(data_dir, "options.json") @@ -195,7 +213,7 @@ def main() -> None: # setup logger logger = setup_logger(data_dir, log_level) - mass = MusicAssistant(data_dir, safe_mode) + mass = MusicAssistant(data_dir, cache_dir, safe_mode) # enable alpine subprocess workaround _enable_posix_spawn() diff --git a/music_assistant/mass.py b/music_assistant/mass.py index 53a36ab2..049d222a 100644 --- a/music_assistant/mass.py +++ b/music_assistant/mass.py @@ -112,10 +112,10 @@ class MusicAssistant: streams: StreamsController _aiobrowser: AsyncServiceBrowser - def __init__(self, storage_path: str, safe_mode: bool = False) -> None: + def __init__(self, storage_path: str, cache_path: str, safe_mode: bool = False) -> None: """Initialize the MusicAssistant Server.""" self.storage_path = storage_path - self.cache_path = os.path.join(storage_path, ".cache") + self.cache_path = cache_path self.safe_mode = safe_mode # we dynamically register command handlers which can be consumed by the apis self.command_handlers: dict[str, APICommandHandler] = {} diff --git a/tests/conftest.py b/tests/conftest.py index 2dc3e1f6..ff92acfb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -19,12 +19,14 @@ def caplog_fixture(caplog: pytest.LogCaptureFixture) -> pytest.LogCaptureFixture @pytest.fixture async def mass(tmp_path: pathlib.Path) -> AsyncGenerator[MusicAssistant, None]: """Start a Music Assistant in test mode.""" - storage_path = tmp_path / "root" + storage_path = tmp_path / "data" + cache_path = tmp_path / "cache" storage_path.mkdir(parents=True) + cache_path.mkdir(parents=True) logging.getLogger("aiosqlite").level = logging.INFO - mass = MusicAssistant(str(storage_path)) + mass = MusicAssistant(str(storage_path), str(cache_path)) await mass.start() -- 2.34.1