use better default paths on Windows (#241)

This commit is contained in:
Adrian Sampson 2011-11-27 23:33:11 -08:00
parent d805401b23
commit 1ba4d74a75
5 changed files with 86 additions and 11 deletions

View file

@ -33,9 +33,12 @@ from beets import util
# Constants.
CONFIG_PATH_VAR = 'BEETSCONFIG'
DEFAULT_CONFIG_FILE = os.path.expanduser('~/.beetsconfig')
DEFAULT_LIBRARY = '~/.beetsmusic.blb'
DEFAULT_DIRECTORY = '~/Music'
DEFAULT_CONFIG_FILENAME_UNIX = '.beetsconfig'
DEFAULT_CONFIG_FILENAME_WINDOWS = 'beetsconfig.ini'
DEFAULT_LIBRARY_FILENAME_UNIX = '.beetsmusic.blb'
DEFAULT_LIBRARY_FILENAME_WINDOWS = 'beetsmusic.blb'
DEFAULT_DIRECTORY_NAME = 'Music'
WINDOWS_BASEDIR = os.environ.get('APPDATA') or '~'
DEFAULT_PATH_FORMATS = {
'default': '$albumartist/$album/$track $title',
'comp': 'Compilations/$album/$track $title',
@ -373,6 +376,33 @@ def colordiff(a, b, highlight='red'):
return u''.join(a_out), u''.join(b_out)
def default_paths(pathmod=None):
"""Produces the appropriate default config, library, and directory
paths for the current system. On Unix, this is always in ~. On
Windows, tries ~ first and then $APPDATA for the config and library
files (for backwards compatibility).
"""
pathmod = pathmod or os.path
windows = pathmod.__name__ == 'ntpath'
if windows:
windata = os.environ.get('APPDATA') or '~'
# Shorthand for joining paths.
def exp(*vals):
return pathmod.expanduser(pathmod.join(*vals))
config = exp('~', DEFAULT_CONFIG_FILENAME_UNIX)
if windows and not pathmod.exists(config):
config = exp(windata, DEFAULT_CONFIG_FILENAME_WINDOWS)
libpath = exp('~', DEFAULT_LIBRARY_FILENAME_UNIX)
if windows and not pathmod.exists(libpath):
libpath = exp(windata, DEFAULT_LIBRARY_FILENAME_WINDOWS)
libdir = exp('~', DEFAULT_DIRECTORY_NAME)
return config, libpath, libdir
# Subcommand parsing infrastructure.
@ -542,6 +572,9 @@ def main(args=None, configfh=None):
# Get the default subcommands.
from beets.ui.commands import default_commands
# Get default file paths.
default_config, default_libpath, default_dir = default_paths()
# Read defaults from config file.
config = ConfigParser.SafeConfigParser()
if configfh:
@ -549,7 +582,7 @@ def main(args=None, configfh=None):
elif CONFIG_PATH_VAR in os.environ:
configpath = os.path.expanduser(os.environ[CONFIG_PATH_VAR])
else:
configpath = DEFAULT_CONFIG_FILE
configpath = default_config
if configpath:
configpath = util.syspath(configpath)
if os.path.exists(util.syspath(configpath)):
@ -588,9 +621,9 @@ def main(args=None, configfh=None):
# Open library file.
libpath = options.libpath or \
config_val(config, 'beets', 'library', DEFAULT_LIBRARY)
config_val(config, 'beets', 'library', default_libpath)
directory = options.directory or \
config_val(config, 'beets', 'directory', DEFAULT_DIRECTORY)
config_val(config, 'beets', 'directory', default_dir)
legacy_path_format = config_val(config, 'beets', 'path_format', None)
if options.path_format:
# If given, -p overrides all path format settings
@ -621,6 +654,9 @@ def main(args=None, configfh=None):
log.setLevel(logging.DEBUG)
else:
log.setLevel(logging.INFO)
log.debug(u'config file: %s' % configpath)
log.debug(u'library database: %s' % lib.path)
log.debug(u'library directory: %s' % lib.directory)
# Invoke the subcommand.
try:

View file

@ -25,6 +25,11 @@ Changelog
levels in ReplayGain-aware music players.
* Albums are now tagged with their *original* release date rather than the date
of any reissue, remaster, "special edition", or the like.
* The config file and library databases are now given better names and locations
on Windows. Namely, both files now reside in ``%APPDATA%``; the config file is
named ``beetsconfig.ini`` and the database is called ``beetslibrary.blb``
(neither has a leading dot as on Unix). For backwards compatibility, beets
will check the old locations first.
* When entering an ID manually during tagging, beets now searches for anything
that looks like an MBID in the entered string. This means that full
MusicBrainz URLs now work as IDs at the prompt. (Thanks to derwin.)

View file

@ -85,9 +85,11 @@ trouble or you have more detail to contribute here, please `let me know`_.
Configuring
-----------
You'll want to set a few basic options before you start using beets. To do this,
create and edit the file ``~/.beetsconfig`` with your favorite text editor. This
file will start out empty, but here's good place to start::
You'll want to set a few basic options before you start using beets. The
configuration is stored in a text file: on Unix-like OSes, the config file is at
``~/.beetsconfig``; on Windows, it's at ``%APPDATA%\beetsconfig.ini``. Create
and edit the appropriate file with your favorite text editor. This file will
start out empty, but here's good place to start::
[beets]
directory: ~/music

View file

@ -1,7 +1,8 @@
.beetsconfig
============
The ``beet`` command reads configuration information from ``~/.beetsconfig``.
The ``beet`` command reads configuration information from ``~/.beetsconfig`` on
Unix-like OSes (inluding Mac OS X) and ``%APPDATA%\beetsconfig.ini`` on Windows.
The file is in INI format.
Options
@ -11,7 +12,8 @@ These options are available, all of which must appear under the ``[beets]``
section header:
``library``
Path to the beets library file. Defaults to ``~/.beetsmusic.blb``.
Path to the beets library file. Defaults to ``~/.beetsmusic.blb`` on Unix
and ``%APPDATA\beetsmusic.blb`` on Windows.
``directory``
The directory to which files will be copied/moved when adding them to the

View file

@ -668,6 +668,36 @@ class ShowChangeTest(unittest.TestCase):
msg = self.io.getoutput().lower()
self.assertTrue(u'caf\xe9.mp3 -> the title' in msg.decode('utf8'))
class DefaultPathTest(unittest.TestCase):
def setUp(self):
self.old_home = os.environ.get('HOME')
self.old_appdata = os.environ.get('APPDATA')
os.environ['HOME'] = 'xhome'
os.environ['APPDATA'] = 'xappdata'
def tearDown(self):
if self.old_home is None:
del os.environ['HOME']
else:
os.environ['HOME'] = self.old_home
if self.old_appdata is None:
del os.environ['APPDATA']
else:
os.environ['APPDATA'] = self.old_appdata
def test_unix_paths_in_home(self):
import posixpath
config, lib, libdir = ui.default_paths(posixpath)
self.assertEqual(config, 'xhome/.beetsconfig')
self.assertEqual(lib, 'xhome/.beetsmusic.blb')
self.assertEqual(libdir, 'xhome/Music')
def test_windows_paths_in_home_and_appdata(self):
import ntpath
config, lib, libdir = ui.default_paths(ntpath)
self.assertEqual(config, 'xappdata\\beetsconfig.ini')
self.assertEqual(lib, 'xappdata\\beetsmusic.blb')
self.assertEqual(libdir, 'xhome\\Music')
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)