Cache an item's album with a property

Use Album.load() whenever the album is requested, which causes it to be
reloaded from the database.

Drawback: This adds a slowdown of 100% (6.2s to 12.6s) to `beet list`
on my setup.
This commit is contained in:
FichteFoll 2019-06-05 02:39:22 +02:00
parent a112358f76
commit e17c478f74
3 changed files with 35 additions and 14 deletions

View file

@ -772,7 +772,7 @@ class ImportTask(BaseImportTask):
if (not dup_item.album_id or
dup_item.album_id in replaced_album_ids):
continue
replaced_album = dup_item.get_album()
replaced_album = dup_item._cached_album
if replaced_album:
replaced_album_ids.add(dup_item.album_id)
self.replaced_albums[replaced_album.path] = replaced_album

View file

@ -395,9 +395,9 @@ class FormattedItemMapping(dbcore.db.FormattedMapping):
album_keys.append(key)
return album_keys
@lazy_property
@property
def album(self):
return self.item.get_album()
return self.item._cached_album
def _get(self, key):
"""Get the value for a key, either from the album or the item.
@ -542,6 +542,29 @@ class Item(LibModel):
_format_config_key = 'format_item'
__album = None
"""Cached album object. Read-only."""
@property
def _cached_album(self):
"""The Album object that this item belongs to, if any, or
None if the item is a singleton or is not associated with a
library.
The instance is cached and refreshed on access.
DO NOT MODIFY!
If you want a copy to modify, use :meth:`get_album`.
"""
if not self.__album and self._db:
self.__album = self._db.get_album(self)
elif self.__album:
self.__album.load()
return self.__album
@_cached_album.setter
def _cached_album(self, album):
self.__album = album
@classmethod
def _getters(cls):
getters = plugins.item_field_getters()
@ -568,6 +591,8 @@ class Item(LibModel):
value = bytestring_path(value)
elif isinstance(value, BLOB_TYPE):
value = bytes(value)
elif key == 'album_id':
self._cached_album = None
changed = super(Item, self)._setitem(key, value)
@ -581,9 +606,8 @@ class Item(LibModel):
try:
return super(Item, self).__getitem__(key)
except KeyError:
album = self.get_album()
if album:
return album[key]
if self._cached_album:
return self._cached_album[key]
raise
def keys(self, computed=False, with_album=True):
@ -591,10 +615,8 @@ class Item(LibModel):
controls whether the album's fields are included.
"""
keys = super(Item, self).keys(computed=computed)
if with_album:
album = self.get_album()
if album:
keys += album.keys(computed=computed)
if with_album and self._cached_album:
keys += self._cached_album.keys(computed=computed)
return keys
def get(self, key, default=None, with_album=True):
@ -604,9 +626,8 @@ class Item(LibModel):
try:
return self._get(key, default, raise_=with_album)
except KeyError:
album = self.get_album()
if album:
return album.get(key, default)
if self._cached_album:
return self._cached_album.get(key, default)
return default
def update(self, values):

View file

@ -332,7 +332,7 @@ class ConvertPlugin(BeetsPlugin):
item.store() # Store new path and audio data.
if self.config['embed']:
album = item.get_album()
album = item._cached_album
if album and album.artpath:
self._log.debug(u'embedding album art from {}',
util.displayable_path(album.artpath))