mirror of
https://github.com/beetbox/beets.git
synced 2026-01-06 16:02:53 +01:00
moved per-library settings to config file
This commit is contained in:
parent
85b4d9a129
commit
a348e19112
5 changed files with 33 additions and 82 deletions
|
|
@ -59,12 +59,6 @@ metadata_rw_keys = map(operator.itemgetter(0), metadata_rw_fields)
|
|||
metadata_keys = map(operator.itemgetter(0), metadata_fields)
|
||||
item_keys = map(operator.itemgetter(0), item_fields)
|
||||
|
||||
# Entries in the "options" table along with their default values.
|
||||
library_options = {
|
||||
'directory': u'~/Music',
|
||||
'path_format': u'$artist/$album/$track $title.$extension',
|
||||
}
|
||||
|
||||
# Logger.
|
||||
log = logging.getLogger('beets')
|
||||
log.setLevel(logging.DEBUG)
|
||||
|
|
@ -285,8 +279,8 @@ class Item(object):
|
|||
"""Returns the path within the library directory designated for this
|
||||
item (i.e., where the file ought to be).
|
||||
"""
|
||||
libpath = self.library.options['directory']
|
||||
subpath_tmpl = Template(self.library.options['path_format'])
|
||||
libpath = self.library.directory
|
||||
subpath_tmpl = Template(self.library.path_format)
|
||||
|
||||
# build the mapping for substitution in the path template, beginning
|
||||
# with the values from the database
|
||||
|
|
@ -570,71 +564,29 @@ class ResultIterator(object):
|
|||
|
||||
|
||||
class Library(object):
|
||||
def __init__(self, path='library.blb'):
|
||||
def __init__(self, path='library.blb',
|
||||
directory='~/Music',
|
||||
path_format='$artist/$album/$track $title.$extension'):
|
||||
self.path = path
|
||||
self.directory = directory
|
||||
self.path_format = path_format
|
||||
|
||||
self.conn = sqlite3.connect(self.path)
|
||||
self.conn.row_factory = sqlite3.Row
|
||||
# this way we can access our SELECT results like dictionaries
|
||||
self.options = Library._LibraryOptionsAccessor(self)
|
||||
|
||||
self._setup()
|
||||
|
||||
def _setup(self):
|
||||
"""Set up the schema of the library file."""
|
||||
|
||||
# options (library data) table
|
||||
setup_sql = """
|
||||
PRAGMA synchronous = OFF;
|
||||
CREATE TABLE IF NOT EXISTS options (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT
|
||||
);"""
|
||||
|
||||
# items (things in the library) table
|
||||
setup_sql += 'CREATE TABLE IF NOT EXISTS items ('
|
||||
setup_sql = 'CREATE TABLE IF NOT EXISTS items ('
|
||||
setup_sql += ', '.join([' '.join(f) for f in item_fields])
|
||||
setup_sql += ');'
|
||||
|
||||
self.conn.executescript(setup_sql)
|
||||
self.conn.commit()
|
||||
|
||||
|
||||
#### library options ####
|
||||
|
||||
class _LibraryOptionsAccessor(object):
|
||||
"""Provides access to the library's configuration variables."""
|
||||
def __init__(self, library):
|
||||
self.library = library
|
||||
|
||||
def _validate_key(self, key):
|
||||
if key not in self:
|
||||
raise ValueError(key + " is not a valid option name")
|
||||
|
||||
def __iter__(self):
|
||||
return iter(library_options)
|
||||
def __contains__(self, key):
|
||||
return key in library_options
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Return the current value of option "key"."""
|
||||
self._validate_key(key)
|
||||
result = (self.library.conn.
|
||||
execute('SELECT value FROM options WHERE key=?', (key,)).
|
||||
fetchone())
|
||||
if result is None: # no value stored
|
||||
return library_options[key] # return default value
|
||||
else:
|
||||
return result[0]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""Set the value of option "key" to "value"."""
|
||||
self._validate_key(key)
|
||||
self.library.conn.execute(
|
||||
'INSERT OR REPLACE INTO options VALUES (?,?)',
|
||||
(key, value) )
|
||||
|
||||
options = None
|
||||
# will be set to a _LibraryOptionsAccessor when the library is initialized
|
||||
|
||||
|
||||
### helpers ###
|
||||
|
||||
|
|
|
|||
|
|
@ -1085,9 +1085,3 @@ class Server(BaseServer):
|
|||
pos = cast_arg(int, pos)
|
||||
super(Server, self).cmd_seek(conn, index, pos)
|
||||
self.player.seek(pos)
|
||||
|
||||
|
||||
# When run as a script, just start the server.
|
||||
|
||||
if __name__ == '__main__':
|
||||
Server(beets.Library('library.blb')).run()
|
||||
|
|
|
|||
13
bts
13
bts
|
|
@ -29,6 +29,8 @@ from beets.mediafile import FileTypeError
|
|||
CONFIG_DEFAULTS = {
|
||||
# beets
|
||||
'library': 'library.blb',
|
||||
'directory': '~/Music',
|
||||
'path_format': '$artist/$album/$track $title.$extension',
|
||||
|
||||
# bpd
|
||||
'host': '',
|
||||
|
|
@ -118,10 +120,13 @@ class BeetsApp(cmdln.Cmdln):
|
|||
self.config.add_section(sec)
|
||||
|
||||
# Open library file.
|
||||
libpath = self.options.libpath
|
||||
if not libpath:
|
||||
libpath = self.config.get('beets', 'library')
|
||||
self.lib = Library(os.path.expanduser(libpath))
|
||||
libpath = self.options.libpath or self.config.get('beets', 'library')
|
||||
directory = self.config.get('beets', 'directory')
|
||||
path_format = self.config.get('beets', 'path_format')
|
||||
|
||||
self.lib = Library(os.path.expanduser(libpath),
|
||||
directory,
|
||||
path_format)
|
||||
|
||||
@cmdln.alias("imp", "im")
|
||||
def do_import(self, subcmd, opts, *paths):
|
||||
|
|
|
|||
|
|
@ -152,32 +152,32 @@ class DestinationTest(unittest.TestCase):
|
|||
self.lib.conn.close()
|
||||
|
||||
def test_directory_works_with_trailing_slash(self):
|
||||
self.lib.options['directory'] = 'one/'
|
||||
self.lib.options['path_format'] = 'two'
|
||||
self.lib.directory = 'one/'
|
||||
self.lib.path_format = 'two'
|
||||
self.assertEqual(self.i.destination(), np('one/two'))
|
||||
|
||||
def test_directory_works_without_trailing_slash(self):
|
||||
self.lib.options['directory'] = 'one'
|
||||
self.lib.options['path_format'] = 'two'
|
||||
self.lib.directory = 'one'
|
||||
self.lib.path_format = 'two'
|
||||
self.assertEqual(self.i.destination(), np('one/two'))
|
||||
|
||||
def test_destination_substitues_metadata_values(self):
|
||||
self.lib.options['directory'] = 'base'
|
||||
self.lib.options['path_format'] = '$album/$artist $title'
|
||||
self.lib.directory = 'base'
|
||||
self.lib.path_format = '$album/$artist $title'
|
||||
self.i.title = 'three'
|
||||
self.i.artist = 'two'
|
||||
self.i.album = 'one'
|
||||
self.assertEqual(self.i.destination(), np('base/one/two three'))
|
||||
|
||||
def test_destination_substitutes_extension(self):
|
||||
self.lib.options['directory'] = 'base'
|
||||
self.lib.options['path_format'] = '$extension'
|
||||
self.lib.directory = 'base'
|
||||
self.lib.path_format = '$extension'
|
||||
self.i.path = 'hey.audioFormat'
|
||||
self.assertEqual(self.i.destination(), np('base/audioFormat'))
|
||||
|
||||
def test_destination_pads_some_indices(self):
|
||||
self.lib.options['directory'] = 'base'
|
||||
self.lib.options['path_format'] = '$track $tracktotal ' \
|
||||
self.lib.directory = 'base'
|
||||
self.lib.path_format = '$track $tracktotal ' \
|
||||
'$disc $disctotal $bpm $year'
|
||||
self.i.track = 1
|
||||
self.i.tracktotal = 2
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ class MoveTest(unittest.TestCase):
|
|||
|
||||
# set up the destination
|
||||
self.libdir = join('rsrc', 'testlibdir')
|
||||
self.lib.options['directory'] = self.libdir
|
||||
self.lib.options['path_format'] = join('$artist',
|
||||
self.lib.directory = self.libdir
|
||||
self.lib.path_format = join('$artist',
|
||||
'$album', '$title')
|
||||
self.i.artist = 'one'
|
||||
self.i.album = 'two'
|
||||
|
|
@ -141,8 +141,8 @@ class AddTest(unittest.TestCase):
|
|||
def setUp(self):
|
||||
self.dir = os.path.join('rsrc', 'test_lib')
|
||||
self.lib = beets.library.Library(':memory:')
|
||||
self.lib.options['directory'] = self.dir
|
||||
self.lib.options['path_format'] = 'item'
|
||||
self.lib.directory = self.dir
|
||||
self.lib.path_format = 'item'
|
||||
def tearDown(self):
|
||||
if os.path.exists(self.dir):
|
||||
shutil.rmtree(self.dir)
|
||||
|
|
|
|||
Loading…
Reference in a new issue