diff --git a/beets/__init__.py b/beets/__init__.py index 0b64ac388..da15a1975 100644 --- a/beets/__init__.py +++ b/beets/__init__.py @@ -20,7 +20,7 @@ import os import beets.library from beets.util import confit -__version__ = '1.3.16' +__version__ = '1.3.17' __author__ = 'Adrian Sampson ' Library = beets.library.Library diff --git a/beets/library.py b/beets/library.py index f8d226dbe..74b669c03 100644 --- a/beets/library.py +++ b/beets/library.py @@ -1421,7 +1421,7 @@ class DefaultTemplateFunctions(object): # Find matching albums to disambiguate with. subqueries = [] for key in keys: - value = getattr(album, key) + value = album.get(key, '') subqueries.append(dbcore.MatchQuery(key, value)) albums = self.lib.albums(dbcore.AndQuery(subqueries)) @@ -1434,7 +1434,7 @@ class DefaultTemplateFunctions(object): # Find the first disambiguator that distinguishes the albums. for disambiguator in disam: # Get the value for each album for the current field. - disam_values = set([getattr(a, disambiguator) for a in albums]) + disam_values = set([a.get(disambiguator, '') for a in albums]) # If the set of unique values is equal to the number of # albums in the disambiguation set, we're done -- this is diff --git a/beetsplug/lyrics.py b/beetsplug/lyrics.py index 1af34df99..528d391ea 100644 --- a/beetsplug/lyrics.py +++ b/beetsplug/lyrics.py @@ -237,25 +237,45 @@ class Genius(Backend): url = u'https://api.genius.com/search?q=%s' \ % (urllib.quote(query.encode('utf8'))) - data = requests.get( - url, - headers=self.headers, - allow_redirects=True - ).content + self._log.debug('genius: requesting search {}', url) + try: + req = requests.get( + url, + headers=self.headers, + allow_redirects=True + ) + req.raise_for_status() + except requests.RequestException as exc: + self._log.debug('genius: request error: {}', exc) + return None - return json.loads(data) + try: + return req.json() + except ValueError: + self._log.debug('genius: invalid response: {}', req.text) + return None def get_lyrics(self, link): url = u'http://genius-api.com/api/lyricsInfo' - data = requests.post( - url, - data={'link': link}, - headers=self.headers, - allow_redirects=True - ).content + self._log.debug('genius: requesting lyrics for link {}', link) + try: + req = requests.post( + url, + data={'link': link}, + headers=self.headers, + allow_redirects=True + ) + req.raise_for_status() + except requests.RequestException as exc: + self._log.debug('genius: request error: {}', exc) + return None - return json.loads(data) + try: + return req.json() + except ValueError: + self._log.debug('genius: invalid response: {}', req.text) + return None def build_lyric_string(self, lyrics): if 'lyrics' not in lyrics: @@ -274,6 +294,8 @@ class Genius(Backend): def fetch(self, artist, title): search_data = self.search_genius(artist, title) + if not search_data: + return if not search_data['meta']['status'] == 200: return @@ -284,6 +306,8 @@ class Genius(Backend): record_url = records[0]['result']['url'] lyric_data = self.get_lyrics(record_url) + if not lyric_data: + return lyrics = self.build_lyric_string(lyric_data) return lyrics @@ -513,7 +537,7 @@ class Google(Backend): class LyricsPlugin(plugins.BeetsPlugin): - SOURCES = ['google', 'lyricwiki', 'lyrics.com', 'musixmatch', 'genius'] + SOURCES = ['google', 'lyricwiki', 'lyrics.com', 'musixmatch'] SOURCE_BACKENDS = { 'google': Google, 'lyricwiki': LyricsWiki, diff --git a/docs/changelog.rst b/docs/changelog.rst index 534a7d100..f950e6149 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,13 +1,43 @@ Changelog ========= -1.3.16 (in development) +1.3.17 (in development) ----------------------- -New: +Changelog goes here! + + +1.3.16 (December 28, 2015) +-------------------------- + +The big news in this release is a new :doc:`interactive editor plugin +`. It's really nifty: you can now change your music's metadata +by making changes in a visual text editor, which can sometimes be far more +efficient than the built-in :ref:`modify-cmd` command. No more carefully +retyping the same artist name with slight capitalization changes. + +This version also adds an oft-requested "not" operator to beets' queries, so +you can exclude music from any operation. It also brings friendlier formatting +(and querying!) of song durations. + +The big new stuff: * A new :doc:`/plugins/edit` lets you manually edit your music's metadata using your favorite text editor. :bug:`164` :bug:`1706` +* Queries can now use "not" logic. Type a ``^`` before part of a query to + *exclude* matching music from the results. For example, ``beet list -a + beatles ^album:1`` will find all your albums by the Beatles except for their + singles compilation, "1." See :ref:`not_query`. :bug:`819` :bug:`1728` +* A new :doc:`/plugins/embyupdate` can trigger a library refresh on an `Emby`_ + server when your beets database changes. +* Track length is now displayed as "M:SS" rather than a raw number of seconds. + Queries on track length also accept this format: for example, ``beet list + length:5:30..`` will find all your tracks that have a duration over 5 + minutes and 30 seconds. You can turn off this new behavior using the + ``format_raw_length`` configuration option. :bug:`1749` + +Smaller changes: + * Three commands, ``modify``, ``update``, and ``mbsync``, would previously move files by default after changing their metadata. Now, these commands will only move files if you have the :ref:`config-import-copy` or @@ -20,21 +50,11 @@ New: various-artists albums. The setting defaults to "Various Artists," the MusicBrainz standard. In order to match MusicBrainz, the :doc:`/plugins/discogs` also adopts the same setting. -* :doc:`/plugins/embyupdate`: A plugin to trigger a library refresh on a - `Emby Server`_ if database changed. -* Queries can now use "not" logic. Type a ``^`` before part of a query to - *exclude* matching music from the results. For example, ``beet list -a - beatles ^album:1`` will find all your albums by the Beatles except for their - singles compilation, "1." See :ref:`not_query`. :bug:`819` :bug:`1728` -* :doc:`/plugins/info`: The plugin now accepts the ``-f/--format`` option for - customizing how items are displayed. :bug:`1737` -* Track length is now displayed as ``M:SS`` by default, instead of displaying - the raw number of seconds. Queries on track length also accept this format: - for example, ``beet list length:5:30..`` will find all your tracks that have - a duration over 5 minutes and 30 seconds. You can turn off this new behavior - using the ``format_raw_length`` configuration option. :bug:`1749` +* :doc:`/plugins/info`: The ``info`` command now accepts a ``-f/--format`` + option for customizing how items are displayed, just like the built-in + ``list`` command. :bug:`1737` -For developers: +Some changes for developers: * Two new :ref:`plugin hooks `, ``albuminfo_received`` and ``trackinfo_received``, let plugins intercept metadata as soon as it is @@ -52,12 +72,13 @@ Fixes: and name in quick succession. The importer would fail to detect them as duplicates, claiming that there were "empty albums" in the database even when there were not. :bug:`1652` -* :doc:`plugins/lastgenre`: Clean up the reggae related genres somewhat. +* :doc:`plugins/lastgenre`: Clean up the reggae-related genres somewhat. Thanks to :user:`Freso`. :bug:`1661` * The importer now correctly moves album art files when re-importing. :bug:`314` -* :doc:`/plugins/fetchart`: In auto mode, skips albums that already have - art attached to them so as not to interfere with re-imports. :bug:`314` +* :doc:`/plugins/fetchart`: In auto mode, the plugin now skips albums that + already have art attached to them so as not to interfere with re-imports. + :bug:`314` * :doc:`plugins/fetchart`: The plugin now only resizes album art if necessary, rather than always by default. :bug:`1264` * :doc:`plugins/fetchart`: Fix a bug where a database reference to a @@ -88,12 +109,17 @@ Fixes: bands with regular-expression characters in their names, like Sunn O))). :bug:`1673` * :doc:`/plugins/scrub`: In ``auto`` mode, the plugin now *actually* only - scrubs files on import---not every time files were written, as it previously - did. :bug:`1657` + scrubs files on import, as the documentation always claimed it did---not + every time files were written, as it previously did. :bug:`1657` * :doc:`/plugins/scrub`: Also in ``auto`` mode, album art is now correctly restored. :bug:`1657` +* Possibly allow flexible attributes to be used with the ``%aunique`` template + function. :bug:`1775` +* :doc:`/plugins/lyrics`: The Genius backend is now more robust to + communication errors. The backend has also been disabled by default, since + the API it depends on is currently down. :bug:`1770` -.. _Emby Server: http://emby.media +.. _Emby: http://emby.media 1.3.15 (October 17, 2015) diff --git a/docs/conf.py b/docs/conf.py index d952b410e..a63622079 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,7 +14,7 @@ project = u'beets' copyright = u'2012, Adrian Sampson' version = '1.3' -release = '1.3.16' +release = '1.3.17' pygments_style = 'sphinx' diff --git a/docs/plugins/lyrics.rst b/docs/plugins/lyrics.rst index 1b3ca0c2f..0d504733f 100644 --- a/docs/plugins/lyrics.rst +++ b/docs/plugins/lyrics.rst @@ -52,9 +52,9 @@ configuration file. The available options are: sources known to be scrapeable. - **sources**: List of sources to search for lyrics. An asterisk ``*`` expands to all available sources. - Default: ``google lyricwiki lyrics.com musixmatch genius``, i.e., all - sources. The *google* source will be automatically deactivated if no - ``google_API_key`` is setup. + Default: ``google lyricwiki lyrics.com musixmatch``, i.e., all the + sources except for `genius`. The `google` source will be automatically + deactivated if no ``google_API_key`` is setup. Here's an example of ``config.yaml``:: diff --git a/setup.py b/setup.py index c7e4af3a0..3b53afd5f 100755 --- a/setup.py +++ b/setup.py @@ -56,7 +56,7 @@ if 'sdist' in sys.argv: setup( name='beets', - version='1.3.16', + version='1.3.17', description='music tagger and library organizer', author='Adrian Sampson', author_email='adrian@radbox.org',