"""plex/paths — the Plex-side path → local mount translation (E32 S2: 23% covered, and a wrong answer here reads as "media file not found" for a whole library at once, with nothing else failing). Pure logic: the admin map is read through sysconfig, stubbed per test. """ from pathlib import Path import pytest from app.plex import paths @pytest.fixture def path_map(monkeypatch): def use(raw: str) -> None: monkeypatch.setattr(paths.sysconfig, "get_str", lambda db, key: raw) return use def test_the_map_parses_both_separators_drops_junk_and_puts_the_longest_prefix_first(): raw = " /data=/mnt/a ,\n/data/movies = /mnt/m\nnot-a-pair,=/x,/y=, /data/tv=/mnt/tv " assert paths.parse_map(raw) == [ ("/data/movies", "/mnt/m"), ("/data/tv", "/mnt/tv"), ("/data", "/mnt/a"), ] assert paths.parse_map("") == [] def test_the_longest_matching_prefix_wins(path_map): path_map("/data=/mnt/a,/data/movies=/mnt/m") assert paths.map_path(None, "/data/movies/Foo.mkv") == str(Path("/mnt/m") / "Foo.mkv") assert paths.map_path(None, "/data/tv/Bar.mkv") == str(Path("/mnt/a") / "tv/Bar.mkv") def test_a_prefix_matches_only_at_a_path_boundary(path_map): # "/data/movies2" shares the characters of "/data/movies" but is another folder. path_map("/data/movies=/mnt/m") assert paths.map_path(None, "/data/movies2/Foo.mkv") == "/data/movies2/Foo.mkv" def test_the_prefix_itself_and_a_trailing_slash_in_the_map(path_map): path_map("/data/movies/=/mnt/m") assert paths.map_path(None, "/data/movies/Foo.mkv") == str(Path("/mnt/m") / "Foo.mkv") path_map("/data/movies=/mnt/m") assert paths.map_path(None, "/data/movies") == "/mnt/m" def test_no_map_leaves_the_path_as_plex_sees_it(path_map): path_map("") assert paths.map_path(None, "/data/movies/Foo.mkv") == "/data/movies/Foo.mkv" def test_the_local_file_must_exist(path_map, tmp_path): (tmp_path / "movies").mkdir() (tmp_path / "movies" / "Foo.mkv").write_bytes(b"x") path_map(f"/data={tmp_path}") assert ( paths.local_media_path(None, "/data/movies/Foo.mkv") == (tmp_path / "movies" / "Foo.mkv").resolve() ) assert paths.local_media_path(None, "/data/movies/Missing.mkv") is None assert paths.local_media_path(None, "/data/movies") is None # a folder is not a file assert paths.local_media_path(None, None) is None assert paths.local_media_path(None, "") is None def test_a_path_that_cannot_be_resolved_is_logged_and_answered_none(path_map, monkeypatch, caplog): path_map("") def broken(self, strict=False): raise OSError("dead mount") monkeypatch.setattr(paths.Path, "resolve", broken) assert paths.local_media_path(None, "/data/movies/Foo.mkv") is None rec = next( r for r in caplog.records if getattr(r, "event", None) == "plex.paths.resolve_failed" ) # The title stays out of the log line: the path carries it. assert "Foo" not in rec.getMessage() and rec.attrs == {"reason": "OSError"}