Repository: beetbox/beets

Issue:
Fetch MusicBrainz track disambiguation field
I download a lot of singletons, and I use the track disambiguation notes frequently. I saw that Beets has a way to note the **album** disambig, but not the **track** disambig. Can this be inserted into a future release? This way, my beets.yaml config could look something like this:

`paths:
    default: $albumartist_sort/[$year] $album/$track. $artist- $title
    comp: Various Artists/[$year] $album/$track. $artist- $title
    singleton: $artist_sort/$artist- $title [$trackdisambig]
`


Discussion:

Patch:
diff --git a/beets/autotag/mb.py b/beets/autotag/mb.py
index 03ea5b382..3ca5463c2 100644
--- a/beets/autotag/mb.py
+++ b/beets/autotag/mb.py
@@ -223,6 +223,8 @@ def track_info(recording, index=None, medium=None, medium_index=None,
     if recording.get('length'):
         info.length = int(recording['length']) / (1000.0)
 
+    info.trackdisambig = recording.get('disambiguation')
+
     lyricist = []
     composer = []
     composer_sort = []
diff --git a/beets/library.py b/beets/library.py
index a060e93d6..78552bb61 100644
--- a/beets/library.py
+++ b/beets/library.py
@@ -477,6 +477,7 @@ class Item(LibModel):
         'mb_artistid':          types.STRING,
         'mb_albumartistid':     types.STRING,
         'mb_releasetrackid':    types.STRING,
+        'trackdisambig':        types.STRING,
         'albumtype':            types.STRING,
         'label':                types.STRING,
         'acoustid_fingerprint': types.STRING,
diff --git a/beetsplug/discogs.py b/beetsplug/discogs.py
index 05abb80c2..b1b1593cd 100644
--- a/beetsplug/discogs.py
+++ b/beetsplug/discogs.py
@@ -14,7 +14,7 @@
 # included in all copies or substantial portions of the Software.
 
 """Adds Discogs album search support to the autotagger. Requires the
-python3-discogs-client library.
+discogs-client library.
 """
 from __future__ import division, absolute_import, print_function
 
diff --git a/beetsplug/mpdstats.py b/beetsplug/mpdstats.py
index 5c8402329..599aa7631 100644
--- a/beetsplug/mpdstats.py
+++ b/beetsplug/mpdstats.py
@@ -50,15 +50,8 @@ class MPDClientWrapper(object):
     def __init__(self, log):
         self._log = log
 
-        self.music_directory = mpd_config['music_directory'].as_str()
-        self.strip_path = mpd_config['strip_path'].as_str()
-
-        # Ensure strip_path end with '/'
-        if not self.strip_path.endswith('/'):
-            self.strip_path += '/'
-
-        self._log.debug('music_directory: {0}', self.music_directory)
-        self._log.debug('strip_path: {0}', self.strip_path)
+        self.music_directory = (
+            mpd_config['music_directory'].as_str())
 
         if sys.version_info < (3, 0):
             # On Python 2, use_unicode will enable the utf-8 mode for
@@ -125,21 +118,14 @@ class MPDClientWrapper(object):
         """Return the path to the currently playing song, along with its
         songid.  Prefixes paths with the music_directory, to get the absolute
         path.
-        In some cases, we need to remove the local path from MPD server,
-        we replace 'strip_path' with ''.
-        `strip_path` defaults to ''.
         """
         result = None
         entry = self.get('currentsong')
         if 'file' in entry:
             if not is_url(entry['file']):
-                file = entry['file']
-                if file.startswith(self.strip_path):
-                    file = file[len(self.strip_path):]
-                result = os.path.join(self.music_directory, file)
+                result = os.path.join(self.music_directory, entry['file'])
             else:
                 result = entry['file']
-        self._log.debug('returning: {0}', result)
         return result, entry.get('id')
 
     def status(self):
@@ -348,7 +334,6 @@ class MPDStatsPlugin(plugins.BeetsPlugin):
         super(MPDStatsPlugin, self).__init__()
         mpd_config.add({
             'music_directory': config['directory'].as_filename(),
-            'strip_path':      u'',
             'rating':          True,
             'rating_mix':      0.75,
             'host':            os.environ.get('MPD_HOST', u'localhost'),
diff --git a/docs/changelog.rst b/docs/changelog.rst
index f8debb3da..69f64456c 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -6,8 +6,6 @@ Changelog
 
 New features:
 
-* :doc:`/plugins/mpdstats`: Add strip_path option to help build the right local path
-  from MPD information
 * Submitting acoustID information on tracks which already have a fingerprint
   :bug:`3834`
 * conversion uses par_map to parallelize conversion jobs in python3
@@ -180,6 +178,9 @@ New features:
   :bug:`3478`
 * Removes usage of the bs1770gain replaygain backend.
   Thanks to :user:`SamuelCook`.
+* Added ``trackdisambig`` which stores the recording disambiguation from
+  MusicBrainz for each track.
+  :bug:`1904`
 
 Fixes:
 
@@ -302,8 +303,6 @@ Fixes:
   :bug:`3798`
 * Fix :bug:`3308` by using browsing for big releases to retrieve additional
   information. Thanks to :user:`dosoe`.
-* :doc:`/plugins/discogs`: Replace deprecated discogs-client library with community
-  supported python3-discogs-client library. :bug:`3608`
 
 For plugin developers:
 
diff --git a/docs/plugins/discogs.rst b/docs/plugins/discogs.rst
index 40875b022..c199ccf49 100644
--- a/docs/plugins/discogs.rst
+++ b/docs/plugins/discogs.rst
@@ -10,9 +10,9 @@ Installation
 ------------
 
 To use the ``discogs`` plugin, first enable it in your configuration (see
-:ref:`using-plugins`). Then, install the `python3-discogs-client`_ library by typing::
+:ref:`using-plugins`). Then, install the `discogs-client`_ library by typing::
 
-    pip install python3-discogs-client
+    pip install discogs-client
 
 You will also need to register for a `Discogs`_ account, and provide
 authentication credentials via a personal access token or an OAuth2
@@ -36,7 +36,7 @@ Authentication via Personal Access Token
 
 As an alternative to OAuth, you can get a token from Discogs and add it to
 your configuration.
-To get a personal access token (called a "user token" in the `python3-discogs-client`_
+To get a personal access token (called a "user token" in the `discogs-client`_
 documentation), login to `Discogs`_, and visit the
 `Developer settings page
 <https://www.discogs.com/settings/developers>`_. Press the ``Generate new
@@ -89,4 +89,4 @@ Here are two things you can try:
 * Make sure that your system clock is accurate. The Discogs servers can reject
   your request if your clock is too out of sync.
 
-.. _python3-discogs-client: https://github.com/joalla/discogs_client
+.. _discogs-client: https://github.com/discogs/discogs_client
diff --git a/docs/plugins/mpdstats.rst b/docs/plugins/mpdstats.rst
index c5adbc64b..de9b2ca59 100644
--- a/docs/plugins/mpdstats.rst
+++ b/docs/plugins/mpdstats.rst
@@ -53,9 +53,6 @@ configuration file. The available options are:
 - **music_directory**: If your MPD library is at a different location from the
   beets library (e.g., because one is mounted on a NFS share), specify the path
   here.
-- **strip_path**: If your MPD library contains local path, specify the part to remove
-  here. Combining this with **music_directory** you can mangle MPD path to match the 
-  beets library one.
   Default: The beets library directory.
 - **rating**: Enable rating updates.
   Default: ``yes``.
diff --git a/setup.py b/setup.py
index ec1d2c819..a6cfc9310 100755
--- a/setup.py
+++ b/setup.py
@@ -113,6 +113,7 @@ setup(
         'test': [
             'beautifulsoup4',
             'coverage',
+            'discogs-client',
             'flask',
             'mock',
             'pylast',
@@ -127,9 +128,6 @@ setup(
             ['pathlib'] if (sys.version_info < (3, 4, 0)) else []
         ) + [
             'rarfile<4' if sys.version_info < (3, 6, 0) else 'rarfile',
-        ] + [
-            'discogs-client' if (sys.version_info < (3, 0, 0))
-            else 'python3-discogs-client'
         ],
         'lint': [
             'flake8',
@@ -146,10 +144,7 @@ setup(
         'embyupdate': ['requests'],
         'chroma': ['pyacoustid'],
         'gmusic': ['gmusicapi'],
-        'discogs': (
-            ['discogs-client' if (sys.version_info < (3, 0, 0))
-                else 'python3-discogs-client']
-        ),
+        'discogs': ['discogs-client>=2.2.1'],
         'beatport': ['requests-oauthlib>=0.6.1'],
         'kodiupdate': ['requests'],
         'lastgenre': ['pylast'],


Test patch:
diff --git a/test/test_mb.py b/test/test_mb.py
index de1ffd9a7..9eca57c80 100644
--- a/test/test_mb.py
+++ b/test/test_mb.py
@@ -111,7 +111,8 @@ class MBAlbumInfoTest(_common.TestCase):
         })
         return release
 
-    def _make_track(self, title, tr_id, duration, artist=False, video=False):
+    def _make_track(self, title, tr_id, duration, artist=False, video=False,
+                    disambiguation=None):
         track = {
             'title': title,
             'id': tr_id,
@@ -131,6 +132,8 @@ class MBAlbumInfoTest(_common.TestCase):
             ]
         if video:
             track['video'] = 'true'
+        if disambiguation:
+            track['disambiguation'] = disambiguation
         return track
 
     def test_parse_release_with_year(self):
@@ -445,6 +448,18 @@ class MBAlbumInfoTest(_common.TestCase):
         self.assertEqual(d.tracks[1].title, 'TITLE TWO')
         self.assertEqual(d.tracks[2].title, 'TITLE VIDEO')
 
+    def test_track_disambiguation(self):
+        tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
+                  self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0,
+                                   disambiguation="SECOND TRACK")]
+        release = self._make_release(tracks=tracks)
+
+        d = mb.album_info(release)
+        t = d.tracks
+        self.assertEqual(len(t), 2)
+        self.assertEqual(t[0].trackdisambig, None)
+        self.assertEqual(t[1].trackdisambig, "SECOND TRACK")
+
 
 class ParseIDTest(_common.TestCase):
     def test_parse_id_correct(self):