Compare commits
3
Commits
43d04bf311
...
v0.7.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
494ac950d7 | ||
|
|
61761c7fac | ||
|
|
8644184caa |
+19
-1
@@ -75,6 +75,11 @@ PLAYLIST_DIRECTORY = "_playlists"
|
|||||||
# library holds Mötley Crüe, Beyoncé and Sigur Rós.
|
# library holds Mötley Crüe, Beyoncé and Sigur Rós.
|
||||||
PLAYLIST_SUFFIX = ".m3u8"
|
PLAYLIST_SUFFIX = ".m3u8"
|
||||||
|
|
||||||
|
# Extensions this tool has written in the past. A playlist of the same name
|
||||||
|
# under one of these is a leftover of its own, and is cleaned up even though no
|
||||||
|
# record of writing it survives.
|
||||||
|
SUPERSEDED_SUFFIXES = (".m3u",)
|
||||||
|
|
||||||
# Tags are re-fetched this often. They move slowly, and the first pass over a
|
# Tags are re-fetched this often. They move slowly, and the first pass over a
|
||||||
# library already costs one request per artist.
|
# library already costs one request per artist.
|
||||||
TAG_REFRESH_SECONDS = 90 * 86400
|
TAG_REFRESH_SECONDS = 90 * 86400
|
||||||
@@ -1674,9 +1679,22 @@ def prune_playlists(directory, produced, store):
|
|||||||
Driven by a record of what was written last time rather than by "every M3U
|
Driven by a record of what was written last time rather than by "every M3U
|
||||||
that is not one of ours", so a playlist put there by hand is left alone. A
|
that is not one of ours", so a playlist put there by hand is left alone. A
|
||||||
renamed mood otherwise leaves its old file on the device for ever.
|
renamed mood otherwise leaves its old file on the device for ever.
|
||||||
|
|
||||||
|
That record cannot reach back before it existed, which is how the switch
|
||||||
|
from .m3u to .m3u8 left every playlist on the device twice: the old files
|
||||||
|
were written by a version that kept no record, so there was nothing to
|
||||||
|
prune them by. A file with the same name as one being written now, under a
|
||||||
|
superseded extension, is therefore removed as well -- narrow enough that
|
||||||
|
only this tool's own leavings match it.
|
||||||
"""
|
"""
|
||||||
previous = set(json.loads(store.get_state("playlist_files") or "[]"))
|
previous = set(json.loads(store.get_state("playlist_files") or "[]"))
|
||||||
for name in sorted(previous - set(produced)):
|
stale_names = previous - set(produced)
|
||||||
|
for name in produced:
|
||||||
|
for superseded in SUPERSEDED_SUFFIXES:
|
||||||
|
stale_names.add(Path(name).with_suffix(superseded).name)
|
||||||
|
stale_names -= set(produced)
|
||||||
|
|
||||||
|
for name in sorted(stale_names):
|
||||||
stale = directory / name
|
stale = directory / name
|
||||||
if stale.is_file():
|
if stale.is_file():
|
||||||
logger.info("removing playlist %s, no longer produced", name)
|
logger.info("removing playlist %s, no longer produced", name)
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "music-curator"
|
name = "music-curator"
|
||||||
version = "0.7.0"
|
version = "0.7.1"
|
||||||
description = "Ingest a Last.fm listening history and curate a music library from it"
|
description = "Ingest a Last.fm listening history and curate a music library from it"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
|
|||||||
@@ -1504,3 +1504,35 @@ def test_the_old_m3u_playlists_are_pruned_after_the_rename(tmp_path):
|
|||||||
music_curator.prune_playlists(directory, ["screamo.m3u8"], store)
|
music_curator.prune_playlists(directory, ["screamo.m3u8"], store)
|
||||||
|
|
||||||
assert not (directory / "screamo.m3u").exists()
|
assert not (directory / "screamo.m3u").exists()
|
||||||
|
|
||||||
|
|
||||||
|
def test_a_playlist_under_a_superseded_extension_is_removed(tmp_path):
|
||||||
|
"""Switching from .m3u to .m3u8 left every playlist on the device twice.
|
||||||
|
The old files predated the record of what had been written, so there was
|
||||||
|
nothing to prune them by."""
|
||||||
|
api, source, mirror = playlist_library(tmp_path)
|
||||||
|
store = store_at(tmp_path)
|
||||||
|
directory = mirror / "_playlists"
|
||||||
|
directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
(directory / "screamo.m3u").write_text("#EXTM3U\n")
|
||||||
|
(directory / "screamo.m3u8").write_text("#EXTM3U\n")
|
||||||
|
|
||||||
|
# No record at all, as on the first run after the rename.
|
||||||
|
music_curator.prune_playlists(directory, ["screamo.m3u8"], store)
|
||||||
|
|
||||||
|
assert not (directory / "screamo.m3u").exists()
|
||||||
|
assert (directory / "screamo.m3u8").is_file()
|
||||||
|
|
||||||
|
|
||||||
|
def test_an_unrelated_m3u_is_still_left_alone(tmp_path):
|
||||||
|
"""Only a name this run is writing anyway is matched, so a playlist made by
|
||||||
|
hand survives whatever its extension."""
|
||||||
|
api, source, mirror = playlist_library(tmp_path)
|
||||||
|
store = store_at(tmp_path)
|
||||||
|
directory = mirror / "_playlists"
|
||||||
|
directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
(directory / "lyras-own-mix.m3u").write_text("#EXTM3U\n")
|
||||||
|
|
||||||
|
music_curator.prune_playlists(directory, ["screamo.m3u8"], store)
|
||||||
|
|
||||||
|
assert (directory / "lyras-own-mix.m3u").is_file()
|
||||||
|
|||||||
Reference in New Issue
Block a user