add "albums" table to library database (including migrations)

This commit is contained in:
Adrian Sampson 2010-07-13 10:25:42 -07:00
parent 6394371628
commit 5d4f452393
3 changed files with 52 additions and 17 deletions

View file

@ -62,6 +62,14 @@ ITEM_KEYS_WRITABLE = [f[0] for f in ITEM_FIELDS if f[3] and f[2]]
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.
ALBUM_FIELDS = [
('id', 'integer primary key'),
('artist', 'text'),
('album', 'text'),
('artpath', 'text'),
]
# Default search fields for various granularities.
ARTIST_DEFAULT_FIELDS = ('artist',)
ALBUM_DEFAULT_FIELDS = ARTIST_DEFAULT_FIELDS + ('album', 'genre')
@ -644,7 +652,8 @@ class Library(BaseLibrary):
def __init__(self, path='library.blb',
directory='~/Music',
path_format='$artist/$album/$track $title',
fields=ITEM_FIELDS):
item_fields=ITEM_FIELDS,
album_fields=ALBUM_FIELDS):
self.path = path
self.directory = directory
self.path_format = path_format
@ -653,16 +662,17 @@ class Library(BaseLibrary):
self.conn.row_factory = sqlite3.Row
# this way we can access our SELECT results like dictionaries
self._setup(fields)
self._make_table('items', item_fields)
self._make_table('albums', album_fields)
def _setup(self, fields):
"""Set up the schema of the library file. fields is a list
of all the fields that should be present in the table. Columns
are added if necessary.
def _make_table(self, table, fields):
"""Set up the schema of the library file. fields is a list of
all the fields that should be present in the indicated table.
Columns are added if necessary.
"""
# Get current schema.
cur = self.conn.cursor()
cur.execute('PRAGMA table_info(items)')
cur.execute('PRAGMA table_info(%s)' % table)
current_fields = set([row[1] for row in cur])
field_names = set([f[0] for f in fields])
@ -672,7 +682,7 @@ class Library(BaseLibrary):
if not current_fields:
# No table exists.
setup_sql = 'CREATE TABLE items ('
setup_sql = 'CREATE TABLE %s (' % table
setup_sql += ', '.join(['%s %s' % f[:2] for f in fields])
setup_sql += ');'
@ -685,8 +695,8 @@ class Library(BaseLibrary):
break
else:
assert False
setup_sql += 'ALTER TABLE items ADD COLUMN ' \
'%s %s;\n' % field[:2]
setup_sql += 'ALTER TABLE %s ' % table
setup_sql += 'ADD COLUMN %s %s;\n' % field[:2]
self.conn.executescript(setup_sql)
self.conn.commit()

Binary file not shown.

View file

@ -15,7 +15,10 @@
"""Tests for non-query database functions of Item.
"""
import unittest, sys, os
import unittest
import sys
import os
import sqlite3
sys.path.append('..')
import beets.library
@ -257,7 +260,8 @@ class MigrationTest(unittest.TestCase):
# Set up a library with old_fields.
self.libfile = os.path.join('rsrc', 'templib.blb')
old_lib = beets.library.Library(self.libfile, fields=self.old_fields)
old_lib = beets.library.Library(self.libfile,
item_fields=self.old_fields)
# Add an item to the old library.
old_lib.conn.execute(
'insert into items (field_one, field_two) values (4, 2)'
@ -269,36 +273,57 @@ class MigrationTest(unittest.TestCase):
os.unlink(self.libfile)
def test_open_with_same_fields_leaves_untouched(self):
new_lib = beets.library.Library(self.libfile, fields=self.old_fields)
new_lib = beets.library.Library(self.libfile,
item_fields=self.old_fields)
c = new_lib.conn.cursor()
c.execute("select * from items")
row = c.fetchone()
self.assertEqual(len(row), len(self.old_fields))
def test_open_with_new_field_adds_column(self):
new_lib = beets.library.Library(self.libfile, fields=self.new_fields)
new_lib = beets.library.Library(self.libfile,
item_fields=self.new_fields)
c = new_lib.conn.cursor()
c.execute("select * from items")
row = c.fetchone()
self.assertEqual(len(row), len(self.new_fields))
def test_open_with_fewer_fields_leaves_untouched(self):
new_lib = beets.library.Library(self.libfile, fields=self.older_fields)
new_lib = beets.library.Library(self.libfile,
item_fields=self.older_fields)
c = new_lib.conn.cursor()
c.execute("select * from items")
row = c.fetchone()
self.assertEqual(len(row), len(self.old_fields))
def test_open_with_multiple_new_fields(self):
new_lib = beets.library.Library(self.libfile, fields=self.newer_fields)
new_lib = beets.library.Library(self.libfile,
item_fields=self.newer_fields)
c = new_lib.conn.cursor()
c.execute("select * from items")
row = c.fetchone()
self.assertEqual(len(row), len(self.newer_fields))
def test_open_old_db_adds_album_table(self):
conn = sqlite3.connect(self.libfile)
conn.execute('drop table albums')
conn.close()
conn = sqlite3.connect(self.libfile)
self.assertRaises(sqlite3.OperationalError, conn.execute,
'select * from albums')
conn.close()
new_lib = beets.library.Library(self.libfile,
item_fields=self.newer_fields)
try:
new_lib.conn.execute("select * from albums")
except sqlite3.OperationalError:
self.fail("select failed")
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)
if __name__ == '__main__':
unittest.main(defaultTest='suite')