Merge branch 'master' of git://github.com/sampsyo/beets

This commit is contained in:
Michael Schuerig 2013-05-01 14:07:05 +02:00
commit ae807bccfc
10 changed files with 69 additions and 34 deletions

View file

@ -18,3 +18,4 @@ f3cd4c138c6f40dc324a23bf01c4c7d97766477e 1.0rc2
6f29c0f4dc7025e8d8216ea960000c353886c4f4 v1.1.0-beta.1
f28ea9e2ef8d39913d79dbba73db280ff0740c50 v1.1.0-beta.2
8f070ce28a7b33d8509b29a8dbe937109bbdbd21 v1.1.0-beta.3
97f04ce252332dbda013cbc478d702d54a8fc1bd v1.1.0

View file

@ -104,7 +104,7 @@ def im_resize(maxwidth, path_in, path_out=None):
# "-resize widthxheight>" shrinks images with dimension(s) larger
# than the corresponding width and/or height dimension(s). The >
# "only shrink" flag is prefixed by ^ escape char for Windows
# compatability.
# compatibility.
call([
'convert', util.syspath(path_in),
'-resize', '{0}x^>'.format(maxwidth), path_out

View file

@ -51,7 +51,7 @@ class WaitableEvent(Event):
return (), (), ()
def fire(self):
"""Called when an assoicated file descriptor becomes ready
"""Called when an associated file descriptor becomes ready
(i.e., is returned from a select() call).
"""
pass

View file

@ -667,7 +667,7 @@ class Configuration(RootView):
"""
dirs = list(self._search_dirs())
# First, look for an existant configuration file.
# First, look for an existent configuration file.
for appdir in dirs:
if os.path.isfile(os.path.join(appdir, CONFIG_FILENAME)):
return appdir

View file

@ -189,7 +189,7 @@ class ConvertPlugin(BeetsPlugin):
help='choose albums instead of tracks')
cmd.parser.add_option('-t', '--threads', action='store', type='int',
help='change the number of threads, \
defaults to maximum availble processors ')
defaults to maximum available processors')
cmd.parser.add_option('-k', '--keep-new', action='store_true',
dest='keep_new', help='keep only the converted \
and move the old files')

View file

@ -28,7 +28,6 @@ from beets import util
from beets import config
IMAGE_EXTENSIONS = ['png', 'jpg', 'jpeg']
COVER_NAMES = ['cover', 'front', 'art', 'album', 'folder']
CONTENT_TYPES = ('image/jpeg',)
DOWNLOAD_EXTENSION = '.jpg'
@ -111,7 +110,7 @@ def aao_art(asin):
# Art from the filesystem.
def art_in_path(path):
def art_in_path(path, cover_names, cautious):
"""Look for album art files in a specified directory."""
if not os.path.isdir(path):
return
@ -124,16 +123,16 @@ def art_in_path(path):
images.append(fn)
# Look for "preferred" filenames.
cover_pat = r"(\b|_)({0})(\b|_)".format('|'.join(cover_names))
for fn in images:
for name in COVER_NAMES:
if fn.lower().startswith(name):
log.debug(u'fetchart: using well-named art file {0}'.format(
util.displayable_path(fn)
))
return os.path.join(path, fn)
if re.search(cover_pat, os.path.splitext(fn)[0], re.I):
log.debug(u'fetchart: using well-named art file {0}'.format(
util.displayable_path(fn)
))
return os.path.join(path, fn)
# Fall back to any image in the folder.
if images:
if images and not cautious:
log.debug(u'fetchart: using fallback art file {0}'.format(
util.displayable_path(images[0])
))
@ -172,9 +171,11 @@ def art_for_album(album, paths, maxwidth=None, local_only=False):
out = None
# Local art.
cover_names = config['fetchart']['cover_names'].as_str_seq()
cautious = config['fetchart']['cautious'].get(bool)
if paths:
for path in paths:
out = art_in_path(path)
out = art_in_path(path, cover_names, cautious)
if out:
break
@ -221,6 +222,8 @@ class FetchArtPlugin(BeetsPlugin):
'auto': True,
'maxwidth': 0,
'remote_priority': False,
'cautious': False,
'cover_names': ['cover', 'front', 'art', 'album', 'folder'],
})
# Holds paths to downloaded images between fetching them and

View file

@ -1,8 +1,16 @@
Changelog
=========
1.1.0 (in development)
----------------------
1.1.0 (April 29, 203)
---------------------
This final release of 1.1 brings a little polish to the betas that introduced
the new configuration system. The album art and lyrics plugins also got a
little love.
If you're upgrading from 1.0.0 or earlier, this release (like the 1.1 betas)
will automatically migrate your configuration to the new system. See
:doc:`/guides/migration`.
* :doc:`/plugins/embedart`: The ``embedart`` command now embeds each album's
associated art by default. The ``--file`` option invokes the old behavior,
@ -14,6 +22,10 @@ Changelog
guess more than 200 characters. This prevents errors on systems where the
maximum length was misreported. You can, of course, override this default
with the :ref:`max_filename_length` option.
* :doc:`/plugins/fetchart`: Two new configuration options were added:
``cover_names``, the list of keywords used to identify preferred images, and
``cautious``, which lets you avoid falling back to images that don't contain
those keywords. Thanks to Fabrice Laporte.
* Avoid some error cases in the ``update`` command and the ``embedart`` and
``mbsync`` plugins. Invalid or missing files now cause error logs instead of
crashing beets. Thanks to Lucas Duailibe.

View file

@ -67,17 +67,27 @@ Currently, this plugin searches for art in the local filesystem as well as on
the Cover Art Archive, Amazon, and AlbumArt.org (in that order).
When looking for local album art, beets checks for image files located in the
same folder as the music files you're importing. If you have an image file
called "cover," "front," "art," "album," for "folder" alongside your music,
beets will treat it as album art and skip searching any online databases.
same folder as the music files you're importing. Beets prefers to use an image
file whose name contains "cover", "front", "art", "album" or "folder", but in
the absence of well-known names, it will use any image file in the same folder
as your music files.
When you choose to apply changes during an import, beets searches all sources
for album art. For "as-is" imports (and non-autotagged imports using the ``-A``
flag), beets only looks for art on the local filesystem.
You can change the list of filename keywords using the ``cover_names`` config
option. Or, to use *only* filenames containing the keywords and not fall back
to any image, set ``cautious`` to true. For example::
fetchart:
cautious: true
cover_names: front back
By default, remote (Web) art sources are only queried if no local art is found
in the filesystem. To query remote sources every time, set the
``remote_priority`` configuration option to false.
``remote_priority`` configuration option to true, which will cause beets to
prefer remote cover art over any local image files.
When you choose to apply changes during an import, beets will search for art as
described above. For "as-is" imports (and non-autotagged imports using the
``-A`` flag), beets only looks for art on the local filesystem.
Embedding Album Art
-------------------

View file

@ -195,7 +195,7 @@ Ordinary metadata:
* encoder
.. _artist credit: http://wiki.musicbrainz.org/Artist_Credit
.. _list of type names: http://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Release_Type_and_Status
.. _list of type names: http://musicbrainz.org/doc/Release_Group/Type
Audio information:

View file

@ -58,18 +58,27 @@ class FSArtTest(_common.TestCase):
def test_finds_jpg_in_directory(self):
_common.touch(os.path.join(self.dpath, 'a.jpg'))
fn = fetchart.art_in_path(self.dpath)
fn = fetchart.art_in_path(self.dpath, ('art',), False)
self.assertEqual(fn, os.path.join(self.dpath, 'a.jpg'))
def test_appropriately_named_file_takes_precedence(self):
_common.touch(os.path.join(self.dpath, 'a.jpg'))
_common.touch(os.path.join(self.dpath, 'cover.jpg'))
fn = fetchart.art_in_path(self.dpath)
self.assertEqual(fn, os.path.join(self.dpath, 'cover.jpg'))
_common.touch(os.path.join(self.dpath, 'art.jpg'))
fn = fetchart.art_in_path(self.dpath, ('art',), False)
self.assertEqual(fn, os.path.join(self.dpath, 'art.jpg'))
def test_non_image_file_not_identified(self):
_common.touch(os.path.join(self.dpath, 'a.txt'))
fn = fetchart.art_in_path(self.dpath)
fn = fetchart.art_in_path(self.dpath, ('art',), False)
self.assertEqual(fn, None)
def test_cautious_skips_fallback(self):
_common.touch(os.path.join(self.dpath, 'a.jpg'))
fn = fetchart.art_in_path(self.dpath, ('art',), True)
self.assertEqual(fn, None)
def test_empty_dir(self):
fn = fetchart.art_in_path(self.dpath, ('art',), True)
self.assertEqual(fn, None)
class CombinedTest(_common.TestCase):
@ -107,11 +116,11 @@ class CombinedTest(_common.TestCase):
self.assertEqual(artpath, None)
def test_main_interface_gives_precedence_to_fs_art(self):
_common.touch(os.path.join(self.dpath, 'a.jpg'))
_common.touch(os.path.join(self.dpath, 'art.jpg'))
fetchart.urllib.urlretrieve = MockUrlRetrieve('image/jpeg')
album = _common.Bag(asin='xxxx')
artpath = fetchart.art_for_album(album, [self.dpath])
self.assertEqual(artpath, os.path.join(self.dpath, 'a.jpg'))
self.assertEqual(artpath, os.path.join(self.dpath, 'art.jpg'))
def test_main_interface_falls_back_to_amazon(self):
fetchart.urllib.urlretrieve = MockUrlRetrieve('image/jpeg')
@ -150,12 +159,12 @@ class CombinedTest(_common.TestCase):
self.assertFalse(mock_retrieve.fetched)
def test_local_only_gets_fs_image(self):
_common.touch(os.path.join(self.dpath, 'a.jpg'))
_common.touch(os.path.join(self.dpath, 'art.jpg'))
mock_retrieve = MockUrlRetrieve('image/jpeg')
fetchart.urllib.urlretrieve = mock_retrieve
album = _common.Bag(mb_albumid='releaseid', asin='xxxx')
artpath = fetchart.art_for_album(album, [self.dpath], local_only=True)
self.assertEqual(artpath, os.path.join(self.dpath, 'a.jpg'))
artpath = fetchart.art_for_album(album, [self.dpath], None, local_only=True)
self.assertEqual(artpath, os.path.join(self.dpath, 'art.jpg'))
self.assertFalse(self.urlopen_called)
self.assertFalse(mock_retrieve.fetched)