diff --git a/beets/dbcore/db.py b/beets/dbcore/db.py index 79645c599..a2d7b3513 100644 --- a/beets/dbcore/db.py +++ b/beets/dbcore/db.py @@ -95,7 +95,7 @@ class Model(object): # Basic operation. - def __init__(self, db=None, fixed=None, flexattr=None, **values): + def __init__(self, db=None, **values): """Create a new object with an optional Database association and initial field values. """ @@ -105,10 +105,24 @@ class Model(object): self._values_flex = {} # Initial contents. - self._bulk_update(fixed, flexattr) self.update(values) self.clear_dirty() + @classmethod + def _awaken(cls, db=None, fixed_values=None, flex_values=None): + """Create an object with values drawn from the database. + + This is a performance optimization: the checks involved with + ordinary construction are bypassed. + """ + obj = cls(db) + if fixed_values: + for key, value in fixed_values.items(): + obj._values_fixed[key] = cls._fields[key].normalize(value) + if flex_values: + obj._values_flex.update(flex_values) + return obj + def __repr__(self): return '{0}({1})'.format( type(self).__name__, @@ -196,24 +210,6 @@ class Model(object): for key, value in values.items(): self[key] = value - def _bulk_update(self, fixed, flexattr): - """Assign all values in the fixed and flex dicts. - Using _bulk_update() bypasses many tests made by update() and - should only be used when loading data from the db. - """ - if fixed: - for (key, value) in fixed.items(): - self._set_fixed_attr(key, value) - if flexattr: - for (key, value) in flexattr.items(): - self._set_flex_attr(key, value) - - def _set_fixed_attr(self, key, value): - self._values_fixed[key] = self._fields[key].normalize(value) - - def _set_flex_attr(self, key, value): - self._values_flex[key] = value - def items(self): """Iterate over (key, value) pairs that this object contains. Computed fields are not included. @@ -515,7 +511,7 @@ class Results(object): # Construct the Python object and yield it if it passes the # predicate. - obj = self.model_class(self.db, values, flex_values) + obj = self.model_class._awaken(self.db, values, flex_values) if not self.query or self.query.match(obj): yield obj diff --git a/beets/library.py b/beets/library.py index bf4df16a4..7c1bd5075 100644 --- a/beets/library.py +++ b/beets/library.py @@ -94,6 +94,19 @@ class PathType(types.Type): def parse(self, string): return normpath(bytestring_path(string)) + def normalize(self, value): + if isinstance(value, unicode): + # Paths stored internally as encoded bytes. + return bytestring_path(value) + + elif isinstance(value, buffer): + # SQLite must store bytestings as buffers to avoid decoding. + # We unwrap buffers to bytes. + return bytes(value) + + else: + return value + # Special path format key. PF_KEY_DEFAULT = 'default' @@ -295,14 +308,6 @@ class Item(LibModel): if self.mtime == 0 and 'mtime' in values: self.mtime = values['mtime'] - def _set_fixed_attr(self, key, value): - if key == 'path': - if isinstance(value, unicode): - value = bytestring_path(value) - elif isinstance(value, buffer): - value = str(value) - super(Item, self)._set_fixed_attr(key, value) - def get_album(self): """Get the Album object that this item belongs to, if any, or None if the item is a singleton or is not associated with a @@ -695,23 +700,6 @@ class Album(LibModel): getters['path'] = Album.item_dir return getters - def _set_fixed_attr(self, key, value): - if key == 'artpath': - if isinstance(value, unicode): - value = bytestring_path(value) - elif isinstance(value, buffer): - value = bytes(value) - super(Album, self)._set_fixed_attr(key, value) - - def __setitem__(self, key, value): - """Set the value of an album attribute.""" - if key == 'artpath': - if isinstance(value, unicode): - value = bytestring_path(value) - elif isinstance(value, buffer): - value = bytes(value) - super(Album, self).__setitem__(key, value) - def items(self): """Returns an iterable over the items associated with this album.