diff --git a/beetsplug/replace.py b/beetsplug/replace.py index d6557fc0c..e63e4e0e6 100644 --- a/beetsplug/replace.py +++ b/beetsplug/replace.py @@ -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.") diff --git a/test/plugins/test_replace.py b/test/plugins/test_replace.py index a247e317a..7ae9b332c 100644 --- a/test/plugins/test_replace.py +++ b/test/plugins/test_replace.py @@ -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