mirror of
https://github.com/beetbox/beets.git
synced 2026-02-17 04:43:40 +01:00
Introduce Album.art_filepath to simplify existence checks
This commit is contained in:
parent
d017270196
commit
e40c7fd71c
6 changed files with 49 additions and 42 deletions
|
|
@ -45,6 +45,11 @@ class LibModel(dbcore.Model["Library"]):
|
|||
def writable_media_fields(cls) -> set[str]:
|
||||
return set(MediaFile.fields()) & cls._fields.keys()
|
||||
|
||||
@property
|
||||
def filepath(self) -> Path:
|
||||
"""The path to the entity as pathlib.Path."""
|
||||
return Path(os.fsdecode(self.path))
|
||||
|
||||
def _template_funcs(self):
|
||||
funcs = DefaultTemplateFunctions(self, self._db).functions()
|
||||
funcs.update(plugins.template_funcs())
|
||||
|
|
@ -207,6 +212,8 @@ class Album(LibModel):
|
|||
Reflects the library's "albums" table, including album art.
|
||||
"""
|
||||
|
||||
artpath: bytes
|
||||
|
||||
_table = "albums"
|
||||
_flex_table = "album_attributes"
|
||||
_always_dirty = True
|
||||
|
|
@ -331,6 +338,11 @@ class Album(LibModel):
|
|||
f"ON {cls._table}.id = {cls._relation._table}.album_id"
|
||||
)
|
||||
|
||||
@property
|
||||
def art_filepath(self) -> Path | None:
|
||||
"""The path to album's cover picture as pathlib.Path."""
|
||||
return Path(os.fsdecode(self.artpath)) if self.artpath else None
|
||||
|
||||
@classmethod
|
||||
def _getters(cls):
|
||||
# In addition to plugin-provided computed fields, also expose
|
||||
|
|
@ -748,11 +760,6 @@ class Item(LibModel):
|
|||
f"ON {cls._table}.album_id = {cls._relation._table}.id"
|
||||
)
|
||||
|
||||
@property
|
||||
def filepath(self) -> Path:
|
||||
"""The path to the item's file as pathlib.Path."""
|
||||
return Path(os.fsdecode(self.path))
|
||||
|
||||
@property
|
||||
def _cached_album(self):
|
||||
"""The Album object that this item belongs to, if any, or
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from __future__ import annotations
|
|||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
from unittest.mock import patch
|
||||
|
||||
|
|
@ -804,12 +805,10 @@ class ArtImporterTest(UseThePlugin):
|
|||
self.plugin.fetch_art(self.session, self.task)
|
||||
self.plugin.assign_art(self.session, self.task)
|
||||
|
||||
artpath = self.lib.albums()[0].artpath
|
||||
artpath = self.lib.albums()[0].art_filepath
|
||||
if should_exist:
|
||||
assert artpath == os.path.join(
|
||||
os.path.dirname(self.i.path), b"cover.jpg"
|
||||
)
|
||||
self.assertExists(artpath)
|
||||
assert artpath == self.i.filepath.parent / "cover.jpg"
|
||||
assert artpath.exists()
|
||||
else:
|
||||
assert artpath is None
|
||||
return artpath
|
||||
|
|
@ -861,7 +860,7 @@ class ArtImporterTest(UseThePlugin):
|
|||
self.plugin.batch_fetch_art(
|
||||
self.lib, self.lib.albums(), force=False, quiet=False
|
||||
)
|
||||
self.assertExists(self.album.artpath)
|
||||
assert self.album.art_filepath.exists()
|
||||
|
||||
|
||||
class ArtForAlbumTest(UseThePlugin):
|
||||
|
|
|
|||
|
|
@ -203,23 +203,21 @@ class EmbedartCliTest(IOMixin, PluginMixin, FetchImageHelper, BeetsTestCase):
|
|||
resource_path = os.path.join(_common.RSRC, b"image.mp3")
|
||||
album = self.add_album_fixture()
|
||||
trackpath = album.items()[0].path
|
||||
albumpath = album.path
|
||||
shutil.copy(syspath(resource_path), syspath(trackpath))
|
||||
|
||||
self.run_command("extractart", "-n", "extracted")
|
||||
|
||||
self.assertExists(os.path.join(albumpath, b"extracted.png"))
|
||||
self.assertExists(album.filepath / "extracted.png")
|
||||
|
||||
def test_extracted_extension(self):
|
||||
resource_path = os.path.join(_common.RSRC, b"image-jpeg.mp3")
|
||||
album = self.add_album_fixture()
|
||||
trackpath = album.items()[0].path
|
||||
albumpath = album.path
|
||||
shutil.copy(syspath(resource_path), syspath(trackpath))
|
||||
|
||||
self.run_command("extractart", "-n", "extracted")
|
||||
|
||||
self.assertExists(os.path.join(albumpath, b"extracted.jpg"))
|
||||
self.assertExists(album.filepath / "extracted.jpg")
|
||||
|
||||
def test_clear_art_with_yes_input(self):
|
||||
self._setup_data()
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import shutil
|
|||
import stat
|
||||
import unittest
|
||||
from os.path import join
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
@ -314,9 +315,10 @@ class ArtFileTest(BeetsTestCase):
|
|||
# Make an album.
|
||||
self.ai = self.lib.add_album((self.i,))
|
||||
# Make an art file too.
|
||||
self.art = self.lib.get_album(self.i).art_destination("something.jpg")
|
||||
touch(self.art)
|
||||
self.ai.artpath = self.art
|
||||
art_bytes = self.lib.get_album(self.i).art_destination("something.jpg")
|
||||
self.art = Path(os.fsdecode(art_bytes))
|
||||
self.art.touch()
|
||||
self.ai.artpath = art_bytes
|
||||
self.ai.store()
|
||||
# Alternate destination dir.
|
||||
self.otherdir = os.path.join(self.temp_dir, b"testotherdir")
|
||||
|
|
@ -345,10 +347,10 @@ class ArtFileTest(BeetsTestCase):
|
|||
self.i.load()
|
||||
|
||||
# Art should be in new directory.
|
||||
self.assertNotExists(self.art)
|
||||
newart = self.lib.get_album(self.i).artpath
|
||||
self.assertExists(newart)
|
||||
assert b"testotherdir" in newart
|
||||
assert not self.art.exists()
|
||||
newart = self.lib.get_album(self.i).art_filepath
|
||||
assert newart.exists()
|
||||
assert "testotherdir" in str(newart)
|
||||
|
||||
def test_setart_copies_image(self):
|
||||
util.remove(self.art)
|
||||
|
|
@ -363,7 +365,7 @@ class ArtFileTest(BeetsTestCase):
|
|||
|
||||
assert ai.artpath is None
|
||||
ai.set_art(newart)
|
||||
self.assertExists(ai.artpath)
|
||||
assert ai.art_filepath.exists()
|
||||
|
||||
def test_setart_to_existing_art_works(self):
|
||||
util.remove(self.art)
|
||||
|
|
@ -380,7 +382,7 @@ class ArtFileTest(BeetsTestCase):
|
|||
|
||||
# Set the art again.
|
||||
ai.set_art(ai.artpath)
|
||||
self.assertExists(ai.artpath)
|
||||
assert ai.art_filepath.exists()
|
||||
|
||||
def test_setart_to_existing_but_unset_art_works(self):
|
||||
newart = os.path.join(self.libdir, b"newart.jpg")
|
||||
|
|
@ -397,7 +399,7 @@ class ArtFileTest(BeetsTestCase):
|
|||
|
||||
# Set the art again.
|
||||
ai.set_art(artdest)
|
||||
self.assertExists(ai.artpath)
|
||||
assert ai.art_filepath.exists()
|
||||
|
||||
def test_setart_to_conflicting_file_gets_new_path(self):
|
||||
newart = os.path.join(self.libdir, b"newart.jpg")
|
||||
|
|
@ -442,34 +444,34 @@ class ArtFileTest(BeetsTestCase):
|
|||
os.chmod(syspath(ai.artpath), 0o777)
|
||||
|
||||
def test_move_last_file_moves_albumart(self):
|
||||
oldartpath = self.lib.albums()[0].artpath
|
||||
self.assertExists(oldartpath)
|
||||
oldartpath = self.lib.albums()[0].art_filepath
|
||||
assert oldartpath.exists()
|
||||
|
||||
self.ai.album = "different_album"
|
||||
self.ai.store()
|
||||
self.ai.items()[0].move()
|
||||
|
||||
artpath = self.lib.albums()[0].artpath
|
||||
assert b"different_album" in artpath
|
||||
self.assertExists(artpath)
|
||||
self.assertNotExists(oldartpath)
|
||||
artpath = self.lib.albums()[0].art_filepath
|
||||
assert "different_album" in str(artpath)
|
||||
assert artpath.exists()
|
||||
assert not oldartpath.exists()
|
||||
|
||||
def test_move_not_last_file_does_not_move_albumart(self):
|
||||
i2 = item()
|
||||
i2.albumid = self.ai.id
|
||||
self.lib.add(i2)
|
||||
|
||||
oldartpath = self.lib.albums()[0].artpath
|
||||
self.assertExists(oldartpath)
|
||||
oldartpath = self.lib.albums()[0].art_filepath
|
||||
assert oldartpath.exists()
|
||||
|
||||
self.i.album = "different_album"
|
||||
self.i.album_id = None # detach from album
|
||||
self.i.move()
|
||||
|
||||
artpath = self.lib.albums()[0].artpath
|
||||
assert b"different_album" not in artpath
|
||||
artpath = self.lib.albums()[0].art_filepath
|
||||
assert "different_album" not in str(artpath)
|
||||
assert artpath == oldartpath
|
||||
self.assertExists(oldartpath)
|
||||
assert oldartpath.exists()
|
||||
|
||||
|
||||
class RemoveTest(BeetsTestCase):
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import sys
|
|||
import unicodedata
|
||||
import unittest
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from tarfile import TarFile
|
||||
from tempfile import mkstemp
|
||||
from unittest.mock import Mock, patch
|
||||
|
|
@ -1566,14 +1567,14 @@ class ReimportTest(AutotagImportTestCase):
|
|||
replaced_album = self._album()
|
||||
replaced_album.set_art(art_source)
|
||||
replaced_album.store()
|
||||
old_artpath = replaced_album.artpath
|
||||
old_artpath = replaced_album.art_filepath
|
||||
self.importer.run()
|
||||
new_album = self._album()
|
||||
new_artpath = new_album.art_destination(art_source)
|
||||
assert new_album.artpath == new_artpath
|
||||
self.assertExists(new_artpath)
|
||||
assert new_album.art_filepath.exists()
|
||||
if new_artpath != old_artpath:
|
||||
self.assertNotExists(old_artpath)
|
||||
assert not old_artpath.exists()
|
||||
|
||||
def test_reimported_album_has_new_flexattr(self):
|
||||
self._setup_session()
|
||||
|
|
|
|||
|
|
@ -601,12 +601,12 @@ class UpdateTest(IOMixin, BeetsTestCase):
|
|||
assert not self.lib.albums()
|
||||
|
||||
def test_delete_removes_album_art(self):
|
||||
artpath = self.album.artpath
|
||||
self.assertExists(artpath)
|
||||
art_filepath = self.album.art_filepath
|
||||
assert art_filepath.exists()
|
||||
util.remove(self.i.path)
|
||||
util.remove(self.i2.path)
|
||||
self._update()
|
||||
self.assertNotExists(artpath)
|
||||
assert not art_filepath.exists()
|
||||
|
||||
def test_modified_metadata_detected(self):
|
||||
mf = MediaFile(syspath(self.i.path))
|
||||
|
|
|
|||
Loading…
Reference in a new issue