Replace command now writes metadata to the file

This commit is contained in:
Will Burden 2025-12-12 22:37:15 +00:00
parent 8a97fba2ab
commit eaec52bd79
2 changed files with 65 additions and 23 deletions

View file

@ -123,7 +123,14 @@ class ReplacePlugin(BeetsPlugin):
except Exception as e:
raise ui.UserError(f"Could not delete original file: {e}")
# Store the new path in the database.
song.path = str(dest).encode()
song.store()
# Write the metadata in the database to the song file's tags.
try:
song.write()
except Exception as e:
raise ui.UserError(f"Error writing metadata to file: {e}")
ui.print_("Replacement successful.")

View file

@ -5,46 +5,54 @@ import pytest
from mediafile import MediaFile
from beets import ui
from beets.library import Item, Library
from beets.test import _common
from beets.test.helper import TestHelper
from beetsplug.replace import ReplacePlugin
replace = ReplacePlugin()
class TestReplace:
@pytest.fixture(autouse=True)
def _fake_dir(self, tmp_path):
self.fake_dir = tmp_path
@pytest.fixture
def mp3_file(self, tmp_path) -> Path:
dest = tmp_path / "full.mp3"
src = Path(_common.RSRC.decode()) / "full.mp3"
shutil.copyfile(src, dest)
@pytest.fixture(autouse=True)
def _fake_file(self, tmp_path):
self.fake_file = tmp_path
return dest
def test_path_is_dir(self):
fake_directory = self.fake_dir / "fakeDir"
@pytest.fixture
def opus_file(self, tmp_path) -> Path:
dest = tmp_path / "full.opus"
src = Path(_common.RSRC.decode()) / "full.opus"
shutil.copyfile(src, dest)
return dest
@pytest.fixture
def library(self) -> Library:
helper = TestHelper()
helper.setup_beets()
yield helper.lib
helper.teardown_beets()
def test_path_is_dir(self, tmp_path):
fake_directory = tmp_path / "fakeDir"
fake_directory.mkdir()
with pytest.raises(ui.UserError):
replace.file_check(fake_directory)
def test_path_is_unsupported_file(self):
fake_file = self.fake_file / "fakefile.txt"
def test_path_is_unsupported_file(self, tmp_path):
fake_file = tmp_path / "fakefile.txt"
fake_file.write_text("test", encoding="utf-8")
with pytest.raises(ui.UserError):
replace.file_check(fake_file)
def test_path_is_supported_file(self):
dest = self.fake_file / "full.mp3"
src = Path(_common.RSRC.decode()) / "full.mp3"
shutil.copyfile(src, dest)
mediafile = MediaFile(dest)
mediafile.albumartist = "AAA"
mediafile.disctitle = "DDD"
mediafile.genres = ["a", "b", "c"]
mediafile.composer = None
mediafile.save()
replace.file_check(Path(str(dest)))
def test_path_is_supported_file(self, mp3_file):
replace.file_check(mp3_file)
def test_select_song_valid_choice(self, monkeypatch, capfd):
songs = ["Song A", "Song B", "Song C"]
@ -113,3 +121,30 @@ class TestReplace:
song = Song()
assert replace.confirm_replacement("test", song) is False
def test_replace_file(
self, mp3_file: Path, opus_file: Path, library: Library
):
old_mediafile = MediaFile(mp3_file)
old_mediafile.albumartist = "ABC"
old_mediafile.disctitle = "DEF"
old_mediafile.genre = "GHI"
old_mediafile.save()
item = Item.from_path(mp3_file)
library.add(item)
replace.replace_file(opus_file, item)
# Check that the file has been replaced.
assert opus_file.exists()
assert not mp3_file.exists()
# Check that the database path has been updated.
assert item.path == bytes(opus_file)
# Check that the new file has the old file's metadata.
new_mediafile = MediaFile(opus_file)
assert new_mediafile.albumartist == old_mediafile.albumartist
assert new_mediafile.disctitle == old_mediafile.disctitle
assert new_mediafile.genre == old_mediafile.genre