Apple Music: Fix syncing shared playlists (#3095)
authorMizterB <5458030+MizterB@users.noreply.github.com>
Mon, 9 Feb 2026 08:28:13 +0000 (03:28 -0500)
committerGitHub <noreply@github.com>
Mon, 9 Feb 2026 08:28:13 +0000 (09:28 +0100)
* Catch MediaNotFoundError in get_library_playlists

* Undo try/except, fix is_library_id

* Tests for is_library_id

---------

Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
music_assistant/providers/apple_music/__init__.py
tests/providers/apple_music/__init__.py [new file with mode: 0644]
tests/providers/apple_music/test_ids.py [new file with mode: 0644]

index c3de16461b2a623399544d79148ebf2c2c4a5ecd..11d5ed9defa4cfdf50ec3883403872126aea5dfe 100644 (file)
@@ -1128,7 +1128,7 @@ class AppleMusicProvider(MusicProvider):
         """Check a library ID matches known format."""
         if not isinstance(library_id, str):
             return False
-        valid = re.findall(r"^(?:[a|i|l|p]{1}\.|pl\.u\-)[a-zA-Z0-9]+$", library_id)
+        valid = re.findall(r"^(?:[ailp]\.)[a-zA-Z0-9]+$", library_id)
         return bool(valid)
 
     def _is_catalog_id(self, catalog_id: str) -> bool:
diff --git a/tests/providers/apple_music/__init__.py b/tests/providers/apple_music/__init__.py
new file mode 100644 (file)
index 0000000..ada2278
--- /dev/null
@@ -0,0 +1 @@
+"""Tests for the Apple Music provider."""
diff --git a/tests/providers/apple_music/test_ids.py b/tests/providers/apple_music/test_ids.py
new file mode 100644 (file)
index 0000000..9fafc82
--- /dev/null
@@ -0,0 +1,35 @@
+"""Unit tests for Apple Music ID helpers."""
+
+from typing import Any
+
+import pytest
+
+from music_assistant.providers.apple_music import AppleMusicProvider
+
+
+@pytest.fixture
+def provider() -> AppleMusicProvider:
+    """Return a minimal AppleMusicProvider instance for helper testing."""
+    # Avoid Provider __init__ complexity; is_library_id does not use instance state.
+    return AppleMusicProvider.__new__(AppleMusicProvider)
+
+
+def test_is_library_id_accepts_library_prefixes(provider: AppleMusicProvider) -> None:
+    """Confirm expected library prefixes are accepted."""
+    for prefix in ("a.", "i.", "l.", "p."):
+        assert provider.is_library_id(f"{prefix}ABC123")
+
+
+def test_is_library_id_rejects_pl_u_prefix(provider: AppleMusicProvider) -> None:
+    """Reject the invalid pl.u- prefix."""
+    assert not provider.is_library_id("pl.u-ABC123")
+    assert not provider.is_library_id("pl.u-1")
+
+
+def test_is_library_id_rejects_invalid_values(provider: AppleMusicProvider) -> None:
+    """Reject malformed values and non-string inputs."""
+    for value in ("", "a.", "x.123", "pl.123", "p.123-456"):
+        assert not provider.is_library_id(value)
+    invalid_non_str: list[Any] = [None, 123, 12.3]
+    for value in invalid_non_str:
+        assert not provider.is_library_id(value)