From 19ded256cd287b04125ce709addf7946e726847e Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Wed, 14 Jul 2010 13:24:11 -0700 Subject: [PATCH] albums query and modify their associated items --- beets/library.py | 34 ++++++++++++++++++++++++++++------ test/test_db.py | 14 ++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/beets/library.py b/beets/library.py index a7d39699c..d80b2c820 100644 --- a/beets/library.py +++ b/beets/library.py @@ -66,13 +66,16 @@ ITEM_KEYS_META = [f[0] for f in ITEM_FIELDS if f[3]] ITEM_KEYS = [f[0] for f in ITEM_FIELDS] # Database fields for the "albums" table. +# The third entry in each tuple indicates whether the field reflects an +# identically-named field in the items table. ALBUM_FIELDS = [ - ('id', 'integer primary key'), - ('artist', 'text'), - ('album', 'text'), - ('artpath', 'text'), + ('id', 'integer primary key', False), + ('artist', 'text', True), + ('album', 'text', True), + ('artpath', 'text', False), ] ALBUM_KEYS = [f[0] for f in ALBUM_FIELDS] +ALBUM_KEYS_ITEM = [f[0] for f in ALBUM_FIELDS if f[2]] # Default search fields for various granularities. ARTIST_DEFAULT_FIELDS = ('artist',) @@ -875,6 +878,7 @@ class Library(BaseLibrary): self._id = album_id def __getattr__(self, key): + """Get the value for an album attribute.""" if key == 'id': return self._id elif key in ALBUM_KEYS: @@ -882,15 +886,33 @@ class Library(BaseLibrary): c = self._library.conn.execute(sql, (self._id,)) return c.fetchone()[0] else: - return getattr(self, key) + object.__getattr__(self, key) def __setattr__(self, key, value): - if key in ALBUM_KEYS: + """Set the value of an album attribute.""" + if key == 'id': + raise AttributeError("can't modify album id") + elif key in ALBUM_KEYS: sql = 'UPDATE albums SET %s=? WHERE id=?' % key self._library.conn.execute(sql, (value, self._id)) + if key in ALBUM_KEYS_ITEM: + # Make modification on items as well. + for item in self.items(): + setattr(item, key, value) + self._library.store(item) else: object.__setattr__(self, key, value) + def items(self): + """Returns an iterable over the items associated with this + album. + """ + c = self._library.conn.execute( + 'SELECT * FROM items WHERE album_id=?', + (self._id,) + ) + return ResultIterator(c, self._library) + def get_album(self, item_or_id): """Given an album ID or an item associated with an album, return an _AlbumInfo object for the album. diff --git a/test/test_db.py b/test/test_db.py index ded7296e4..f15484405 100644 --- a/test/test_db.py +++ b/test/test_db.py @@ -363,6 +363,20 @@ class AlbumInfoTest(unittest.TestCase): ai = self.lib.get_album(self.i.id) self.assertNotEqual(ai, None) + def test_album_items_consistent(self): + ai = self.lib.get_album(self.i) + for item in ai.items(): + if item.id == self.i.id: + break + else: + self.fail("item not found") + + def test_albuminfo_changes_affect_items(self): + ai = self.lib.get_album(self.i) + ai.album = 'myNewAlbum' + i = self.lib.items().next() + self.assertEqual(i.album, 'myNewAlbum') + def suite(): return unittest.TestLoader().loadTestsFromName(__name__)