From 439d4c1061567280f4be1ebe61ab57d7df50b521 Mon Sep 17 00:00:00 2001 From: Heinz Wiesinger Date: Wed, 28 Nov 2018 14:06:27 +0100 Subject: [PATCH] Performance improvement: Type cast properties on demand --- beets/dbcore/db.py | 32 ++++++++++++++++++++++++++++---- beets/importer.py | 8 ++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/beets/dbcore/db.py b/beets/dbcore/db.py index 24c20ef1aa..112b8ee93d 100755 --- a/beets/dbcore/db.py +++ b/beets/dbcore/db.py @@ -177,6 +177,8 @@ def __init__(self, db=None, **values): """ self._db = db self._dirty = set() + self._raw_values_fixed = {} + self._raw_values_flex = {} self._values_fixed = {} self._values_flex = {} @@ -193,9 +195,9 @@ def _awaken(cls, db=None, fixed_values={}, flex_values={}): """ obj = cls(db) for key, value in fixed_values.items(): - obj._values_fixed[key] = cls._type(key).from_sql(value) + obj._raw_values_fixed[key] = value for key, value in flex_values.items(): - obj._values_flex[key] = cls._type(key).from_sql(value) + obj._raw_values_flex[key] = value return obj def __repr__(self): @@ -232,7 +234,9 @@ def copy(self): """ new = self.__class__() new._db = self._db + new._raw_values_fixed = self._raw_values_fixed.copy() new._values_fixed = self._values_fixed.copy() + new._raw_values_flex = self._raw_values_flex.copy() new._values_flex = self._values_flex.copy() new._dirty = self._dirty.copy() return new @@ -256,9 +260,18 @@ def __getitem__(self, key): if key in getters: # Computed. return getters[key](self) elif key in self._fields: # Fixed. - return self._values_fixed.get(key, self._type(key).null) + if key in self._values_fixed: + return self._values_fixed[key] + elif key in self._raw_values_fixed: + self._values_fixed[key] = self._type(key).from_sql(self._raw_values_fixed[key]) + return self._values_fixed[key] + else: + return self._type(key).null elif key in self._values_flex: # Flexible. return self._values_flex[key] + elif key in self._raw_values_flex: # Flexible. + self._values_flex[key] = self._type(key).from_sql(self._raw_values_flex[key]) + return self._values_flex[key] else: raise KeyError(key) @@ -268,8 +281,12 @@ def _setitem(self, key, value): """ # Choose where to place the value. if key in self._fields: + if not key in self._values_fixed and key in self._raw_values_fixed: + self._values_fixed[key] = self._type(key).from_sql(self._raw_values_fixed[key]) source = self._values_fixed else: + if not key in self._values_flex and key in self._raw_values_flex: + self._values_flex[key] = self._type(key).from_sql(self._raw_values_flex[key]) source = self._values_flex # If the field has a type, filter the value. @@ -294,6 +311,11 @@ def __delitem__(self, key): """ if key in self._values_flex: # Flexible. del self._values_flex[key] + if key in self._raw_values_flex: + del self._raw_values_flex[key] + self._dirty.add(key) # Mark for dropping on store. + elif key in self._raw_values_flex: # Flexible + del self._raw_values_flex[key] self._dirty.add(key) # Mark for dropping on store. elif key in self._fields: # Fixed setattr(self, key, self._type(key).null) @@ -307,7 +329,7 @@ def keys(self, computed=False): `computed` parameter controls whether computed (plugin-provided) fields are included in the key list. """ - base_keys = list(self._fields) + list(self._values_flex.keys()) + base_keys = list(self._fields) + list(self._values_flex.keys()) + list(self._raw_values_flex.keys()) if computed: return base_keys + list(self._getters().keys()) else: @@ -436,7 +458,9 @@ def load(self): self._check_db() stored_obj = self._db._get(type(self), self.id) assert stored_obj is not None, u"object {0} not in DB".format(self.id) + self._raw_values_fixed = {} self._values_fixed = {} + self._raw_values_flex = {} self._values_flex = {} self.update(dict(stored_obj)) self.clear_dirty() diff --git a/beets/importer.py b/beets/importer.py index 889f1297e9..50e4545c54 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -785,14 +785,14 @@ def reimport_metadata(self, lib): replaced_album = self.replaced_albums.get(self.album.path) if replaced_album: self.album.added = replaced_album.added - self.album.update(replaced_album._values_flex) + self.album.update(replaced_album._raw_values_flex) self.album.artpath = replaced_album.artpath self.album.store() log.debug( u'Reimported album: added {0}, flexible ' u'attributes {1} from album {2} for {3}', self.album.added, - replaced_album._values_flex.keys(), + replaced_album._raw_values_flex.keys(), replaced_album.id, displayable_path(self.album.path) ) @@ -809,11 +809,11 @@ def reimport_metadata(self, lib): dup_item.id, displayable_path(item.path) ) - item.update(dup_item._values_flex) + item.update(dup_item._raw_values_flex) log.debug( u'Reimported item flexible attributes {0} ' u'from item {1} for {2}', - dup_item._values_flex.keys(), + dup_item._raw_values_flex.keys(), dup_item.id, displayable_path(item.path) )