diff --git a/beetsplug/discogs.py b/beetsplug/discogs.py index 65cebbb2f..216540f34 100644 --- a/beetsplug/discogs.py +++ b/beetsplug/discogs.py @@ -416,17 +416,30 @@ class DiscogsPlugin(BeetsPlugin): """Returns the medium, medium index and subtrack index for a discogs track position. """ - # TODO: revise comment - # medium_index is a number at the end of position. medium is everything - # else. E.g. (A)(1), (Side A, Track )(1), (A)(), ()(1), etc. - match = re.match(r'^(.*?)(\d*?)(\.[\w]+|[A-Z]+)?$', position.upper()) + # Match the standard Discogs positions (12.2.9), which can have several + # forms (1, 1-1, A1, A1.1, A1a, ...). + match = re.match( + r'^(.*?)' # medium: everything before medium_index. + r'(\d*?)' # medium_index: a number at the end of + # `position`, except if followed by a subtrack + # index. + # subtrack_index: can only be matched if medium + # or medium_index have been matched, and can be + r'((?<=\w)\.[\w]+' # - a dot followed by a string (A.1, 2.A) + r'|(?<=\d)[A-Z]+' # - a string that follows a number (1A, B2a) + r')?' + r'$', + position.upper() + ) + if match: medium, index, subindex = match.groups() + if subindex and subindex.startswith('.'): subindex = subindex[1:] else: self._log.debug(u'Invalid position: {0}', position) - medium = index, subindex = None + medium = index = subindex = None return medium or None, index or None, subindex or None def get_track_length(self, duration): diff --git a/test/test_discogs.py b/test/test_discogs.py index b5356ccf4..c0cde0c92 100644 --- a/test/test_discogs.py +++ b/test/test_discogs.py @@ -92,6 +92,26 @@ class DGAlbumInfoTest(_common.TestCase): self.assertEqual(t[0].media, d.media) self.assertEqual(t[1].media, d.media) + def test_parse_position(self): + """Test the conversion of discogs `position` to medium, medium_index + and subtrack_index.""" + # List of tuples (discogs_position, (medium, medium_index, subindex) + positions = [('1', (None, '1', None)), + ('A12', ('A', '12', None)), + ('12-34', ('12-', '34', None)), + ('CD1-1', ('CD1-', '1', None)), + ('1.12', (None, '1', '12')), + ('12.a', (None, '12', 'A')), + ('12.34', (None, '12', '34')), + ('1ab', (None, '1', 'AB')), + # Non-standard + ('IV', ('IV', None, None)), + ] + + d = DiscogsPlugin() + for position, expected in positions: + self.assertEqual(d.get_track_index(position), expected) + def test_parse_tracklist_without_sides(self): """Test standard Discogs position 12.2.9#1: "without sides".""" release = self._make_release_from_positions(['1', '2', '3']) @@ -125,6 +145,14 @@ class DGAlbumInfoTest(_common.TestCase): self.assertEqual(d.mediums, 3) self.assertEqual(len(d.tracks), 4) + def test_parse_tracklist_non_standard(self): + """Test non standard Discogs position.""" + release = self._make_release_from_positions(['I', 'II', 'III', 'IV']) + d = DiscogsPlugin().get_album_info(release) + + self.assertEqual(d.mediums, 1) + self.assertEqual(len(d.tracks), 4) + def test_parse_tracklist_subtracks_dot(self): """Test standard Discogs position 12.2.9#5: "sub tracks, dots".""" release = self._make_release_from_positions(['1', '2.1', '2.2', '3']) diff --git a/tox.ini b/tox.ini index cb1db2aa1..28fd3636e 100644 --- a/tox.ini +++ b/tox.ini @@ -23,7 +23,7 @@ deps = jellyfish python-mpd2 coverage - discogs_client + discogs-client [_flake8] deps =