discogs: revise position regexp, add tests, tox

Revise the regular expression used for extracting information from a
discogs position, making the subtrack_index only be matched if one of
the other groups is matched as well. Split the definition into several
lines in order to try to document it a bit more clearly.
Add unit tests for position parsing and non standard positions.
Fix the underscore on tox dependency.
This commit is contained in:
Diego Moreda 2016-10-10 17:42:27 +02:00
parent e7f2a111e4
commit 1148acaaf1
3 changed files with 47 additions and 6 deletions

View file

@ -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):

View file

@ -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'])

View file

@ -23,7 +23,7 @@ deps =
jellyfish
python-mpd2
coverage
discogs_client
discogs-client
[_flake8]
deps =