diff --git a/picard/util/__init__.py b/picard/util/__init__.py index 94cf7c249..667095c30 100644 --- a/picard/util/__init__.py +++ b/picard/util/__init__.py @@ -381,11 +381,16 @@ def iter_unique(seq): _tracknum_regexps = ( # search for explicit track number (prefix "track") r"track[\s_-]*(?:(?:no|nr)\.?)?[\s_-]*(?P\d+)", - # search for 2-digit number at start of string (additional leading zeroes are allowed) - r"^(?P0*\d{2})(?:\.)[^0-9,]", # "99. ", but not "99.02" - r"^(?P0*\d{2})[^0-9,.]", - # search for 2-digit number at end of string + # search for 1- or 2-digit number at start of string (additional leading zeroes are allowed) + # An optional disc number preceeding the track number is ignored. + r"^(?:\d+[\s_-])?(?P0*\d{1,2})(?:\.)[^0-9,]", # "99. ", but not "99.02" + r"^(?:\d+[\s_-])?(?P0*\d{1,2})[^0-9,.s]", + # search for 2-digit number at end of string (additional leading zeroes are allowed) r"[^0-9,.](?P0*\d{2})$", + r"[^0-9,.]\[(?P0*\d{1,2})\]$", + r"[^0-9,.]\((?P0*\d{2})\)$", + # File names which consist of only a number + r"^(?P\d+)$", ) @@ -398,7 +403,9 @@ def tracknum_from_filename(base_filename): match = re.search(r, filename, re.I) if match: n = int(match.group('number')) - if n > 0: + # Numbers above 1900 are often years, track numbers should be much + # smaller even for extensive collections + if n > 0 and n < 1900: return n return None diff --git a/test/test_tracknum.py b/test/test_tracknum.py deleted file mode 100644 index f1c60daf1..000000000 --- a/test/test_tracknum.py +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Picard, the next-generation MusicBrainz tagger -# -# Copyright (C) 2013, 2018 Laurent Monin -# Copyright (C) 2017 Sophist-UK -# Copyright (C) 2018 Wieland Hoffmann -# Copyright (C) 2019-2020 Philipp Wolfer -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - -from test.picardtestcase import PicardTestCase - -from picard.util import tracknum_from_filename - - -class TracknumTest(PicardTestCase): - - def test_matched_tracknum_01(self): - self.assertEqual(tracknum_from_filename('1.mp3'), 1) - - def test_matched_tracknum_02(self): - self.assertEqual(tracknum_from_filename('01.mp3'), 1) - - def test_matched_tracknum_03(self): - self.assertEqual(tracknum_from_filename('001.mp3'), 1) - - def test_matched_tracknum_04(self): - self.assertEqual(tracknum_from_filename('01 song.mp3'), 1) - self.assertEqual(tracknum_from_filename('1 song.mp3'), 1) - - def test_matched_tracknum_05(self): - self.assertEqual(tracknum_from_filename('song 01.mp3'), 1) - - def test_matched_tracknum_06(self): - self.assertEqual(tracknum_from_filename('artist - song (01).mp3'), 1) - - def test_matched_tracknum_07(self): - self.assertEqual(tracknum_from_filename('artist - s 02 ong (01).mp3'), 1) - - def test_matched_tracknum_08(self): - self.assertEqual(tracknum_from_filename('artist song 2004 track01 xxxx.ogg'), 1) - - def test_matched_tracknum_09(self): - self.assertEqual(tracknum_from_filename('artist song 2004 track-no-01 xxxx.ogg'), 1) - - def test_matched_tracknum_10(self): - self.assertEqual(tracknum_from_filename('artist song 2004 track-no_01 xxxx.ogg'), 1) - - def test_matched_tracknum_11(self): - self.assertEqual(tracknum_from_filename('artist song-(666) (01) xxx.ogg'), 1) - - def test_matched_tracknum_12(self): - self.assertEqual(tracknum_from_filename('artist song [2004] [01].mp3'), 1) - - def test_matched_tracknum_13(self): - self.assertEqual(tracknum_from_filename('artist song [2004] (01).mp3'), 1) - - def test_matched_tracknum_14(self): - self.assertEqual(tracknum_from_filename('01 artist song [2004] (02).mp3'), 1) - - def test_matched_tracknum_15(self): - self.assertEqual(tracknum_from_filename('01 artist song [04].mp3'), 1) - - def test_matched_tracknum_16(self): - self.assertEqual(tracknum_from_filename('xx 01 artist song [04].mp3'), 1) - - def test_matched_tracknum_17(self): - self.assertEqual(tracknum_from_filename('song [2004] [1].mp3'), 1) - - def test_matched_tracknum_18(self): - self.assertEqual(tracknum_from_filename('song-70s 69 comment.mp3'), 69) - - def test_matched_tracknum_19(self): - self.assertEqual(tracknum_from_filename('01_foo.mp3'), 1) - - def test_matched_tracknum_20(self): - self.assertEqual(tracknum_from_filename('01ābc.mp3'), 1) - - def test_matched_tracknum_21(self): - self.assertEqual(tracknum_from_filename('01abc.mp3'), 1) - - def test_matched_tracknum_22(self): - t = u"11 Linda Jones - Things I've Been Through 08.flac" - self.assertEqual(tracknum_from_filename(t), 11) - - def test_unmatched_tracknum(self): - self.assertEqual(tracknum_from_filename('0.mp3'), None) - self.assertEqual(tracknum_from_filename('track00.mp3'), None) - self.assertEqual(tracknum_from_filename('song.mp3'), None) - self.assertEqual(tracknum_from_filename('song [2004] [1000].mp3'), None) - self.assertEqual(tracknum_from_filename('song 2015.mp3'), None) - self.assertEqual(tracknum_from_filename('2015 song.mp3'), None) diff --git a/test/test_utils.py b/test/test_utils.py index 29a5f947f..984d11084 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -437,8 +437,12 @@ class TracknumFromFilenameTest(PicardTestCase): def test_returns_expected_tracknumber(self): tests = ( + (2, '2.mp3'), + (2, '02.mp3'), + (2, '002.mp3'), (None, 'Foo.mp3'), (1, 'Foo 0001.mp3'), + (1, '1 song.mp3'), (99, '99 Foo.mp3'), (42, '42. Foo.mp3'), (None, '20000 Feet.mp3'), @@ -447,15 +451,47 @@ class TracknumFromFilenameTest(PicardTestCase): (242, 'track-242.mp3'), (242, 'track nr 242.mp3'), (242, 'track_242.mp3'), + (1, 'artist song 2004 track01 xxxx.ogg'), + (1, 'artist song 2004 track-no-01 xxxx.ogg'), + (1, 'artist song 2004 track-no_01 xxxx.ogg'), + (1, '01_foo.mp3'), + (1, '01ābc.mp3'), + (1, '01abc.mp3'), + (11, "11 Linda Jones - Things I've Been Through 08.flac"), + (1, "01 artist song [2004] (02).mp3"), + (1, "01 artist song [04].mp3"), + (7, "artist song [2004] [7].mp3"), + # (7, "artist song [2004] (7).mp3"), + (7, 'artist song [2004] [07].mp3'), + (7, 'artist song [2004] (07).mp3'), + (4, 'xx 01 artist song [04].mp3'), + (None, 'artist song-(666) (01) xxx.ogg'), + (None, 'song-70s 69 comment.mp3'), + (13, "2_13 foo.mp3"), + (13, "02-13 foo.mp3"), + (None, '1971.mp3'), + (42, '1971 Track 42.mp3'), + (None, "artist song [2004].mp3"), + (None, '0.mp3'), + (None, 'track00.mp3'), + (None, 'song [2004] [1000].mp3'), + (None, 'song 2015.mp3'), + (None, '2015 song.mp3'), (None, '30,000 Pounds of Bananas.mp3'), (None, 'Dalas 1 PM.mp3'), (None, "Don't Stop the 80's.mp3"), (None, 'Symphony no. 5 in D minor.mp3'), (None, 'Song 2.mp3'), + (None, '80s best of.mp3'), + (None, 'best of 80s.mp3'), # (None, '99 Luftballons.mp3'), (7, '99 Luftballons Track 7.mp3'), (None, 'Margin 0.001.mp3'), + (None, 'All the Small Things - blink‐182.mp3'), (None, '99.99 Foo.mp3'), + (5, '٠٥ فاصله میان دو پرده.mp3'), + (23, '23 foo.mp3'), + (None, '²³ foo.mp3'), ) for expected, filename in tests: tracknumber = tracknum_from_filename(filename)