From 3ae6706b053f8abdd11e6f509a50df92c2efa209 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Sun, 30 Jan 2022 11:39:28 +0100 Subject: [PATCH] Moved calculate_mb_toc_numbers to picard.disc.utils --- picard/disc/eaclog.py | 25 ++-------------- picard/disc/utils.py | 54 +++++++++++++++++++++++++++++++++ test/test_disc_eaclog.py | 17 ----------- test/test_disc_utils.py | 64 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 40 deletions(-) create mode 100644 picard/disc/utils.py create mode 100644 test/test_disc_utils.py diff --git a/picard/disc/eaclog.py b/picard/disc/eaclog.py index 5de3b3d72..ce5b72e55 100644 --- a/picard/disc/eaclog.py +++ b/picard/disc/eaclog.py @@ -25,6 +25,8 @@ import re +from picard.disc.utils import calculate_mb_toc_numbers + RE_TOC_TABLE_HEADER = re.compile(r""" \s* \s*.+\s+ \| # track @@ -51,10 +53,6 @@ RE_TOC_TABLE_LINE = re.compile(r""" PREGAP_LENGTH = 150 -class NotSupportedTOCError(Exception): - pass - - def filter_toc_entries(lines): """ Take iterator of lines, return iterator of toc entries @@ -76,25 +74,6 @@ def filter_toc_entries(lines): yield m.groupdict() -def calculate_mb_toc_numbers(eac_entries): - """ - Take iterator of toc entries, return a tuple of numbers for musicbrainz disc id - """ - eac = tuple(eac_entries) - num_tracks = len(eac) - if not num_tracks: - raise NotSupportedTOCError("Empty track list: %s", eac) - - expected_tracknums = tuple(range(1, num_tracks+1)) - tracknums = tuple(int(e['num']) for e in eac) - if expected_tracknums != tracknums: - raise NotSupportedTOCError("Non-standard track number sequence: %s", tracknums) - - leadout_offset = int(eac[-1]['end_sector']) + PREGAP_LENGTH + 1 - offsets = tuple((int(x['start_sector']) + PREGAP_LENGTH) for x in eac) - return (1, num_tracks, leadout_offset) + offsets - - def toc_from_file(path): """Reads EAC / XLD log files, generates musicbrainz disc TOC listing for use as discid. diff --git a/picard/disc/utils.py b/picard/disc/utils.py new file mode 100644 index 000000000..634f07942 --- /dev/null +++ b/picard/disc/utils.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# +# MIT License +# +# Copyright(c) 2018 Konstantin Mochalov +# Copyright(c) 2022 Philipp Wolfer +# +# Original code from https://gist.github.com/kolen/765526 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files(the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +PREGAP_LENGTH = 150 + + +class NotSupportedTOCError(Exception): + pass + + +def calculate_mb_toc_numbers(toc_entries): + """ + Take iterator of toc entries, return a tuple of numbers for musicbrainz disc id + + Each toc entry is a dict with the following keys: + - num: track number + - start_sector: start sector of the track + - end_sector: end sector of the track + """ + eac = tuple(toc_entries) + num_tracks = len(eac) + if not num_tracks: + raise NotSupportedTOCError("Empty track list: %s", eac) + + expected_tracknums = tuple(range(1, num_tracks+1)) + tracknums = tuple(int(e['num']) for e in eac) + if expected_tracknums != tracknums: + raise NotSupportedTOCError("Non-standard track number sequence: %s", tracknums) + + leadout_offset = int(eac[-1]['end_sector']) + PREGAP_LENGTH + 1 + offsets = tuple((int(x['start_sector']) + PREGAP_LENGTH) for x in eac) + return (1, num_tracks, leadout_offset) + offsets diff --git a/test/test_disc_eaclog.py b/test/test_disc_eaclog.py index 652ad6727..5c63c4d52 100644 --- a/test/test_disc_eaclog.py +++ b/test/test_disc_eaclog.py @@ -26,8 +26,6 @@ from test.picardtestcase import ( ) from picard.disc.eaclog import ( - NotSupportedTOCError, - calculate_mb_toc_numbers, filter_toc_entries, toc_from_file, ) @@ -76,21 +74,6 @@ class TestFilterTocEntries(PicardTestCase): self.assertEqual(test_entries, entries) -class TestCalculateMbTocNumbers(PicardTestCase): - - def test_calculate_mb_toc_numbers(self): - self.assertEqual((1, 3, 60890, 150, 25064, 43611), calculate_mb_toc_numbers(test_entries)) - - def test_calculate_mb_toc_numbers_invalid_track_numbers(self): - entries = [{'num': '1'}, {'num': '3'}, {'num': '4'}] - with self.assertRaises(NotSupportedTOCError): - calculate_mb_toc_numbers(entries) - - def test_calculate_mb_toc_numbers_empty_entries(self): - with self.assertRaises(NotSupportedTOCError): - calculate_mb_toc_numbers([]) - - class TestTocFromFile(PicardTestCase): def _test_toc_from_file(self, logfile): diff --git a/test/test_disc_utils.py b/test/test_disc_utils.py new file mode 100644 index 000000000..0e5ef3b44 --- /dev/null +++ b/test/test_disc_utils.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# +# Picard, the next-generation MusicBrainz tagger +# +# Copyright (C) 2022 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.disc.utils import ( + NotSupportedTOCError, + calculate_mb_toc_numbers, +) + + +test_entries = [ + { + 'num': '1', + 'start_time': '0:00.00', + 'length_time': '5:32.14', + 'start_sector': '0', + 'end_sector': '24913' + }, { + 'num': '2', + 'start_time': '5:32.14', + 'length_time': '4:07.22', + 'start_sector': '24914', + 'end_sector': '43460' + }, { + 'num': '3', + 'start_time': '9:39.36', + 'length_time': '3:50.29', + 'start_sector': '43461', + 'end_sector': '60739' + } +] + + +class TestCalculateMbTocNumbers(PicardTestCase): + + def test_calculate_mb_toc_numbers(self): + self.assertEqual((1, 3, 60890, 150, 25064, 43611), calculate_mb_toc_numbers(test_entries)) + + def test_calculate_mb_toc_numbers_invalid_track_numbers(self): + entries = [{'num': '1'}, {'num': '3'}, {'num': '4'}] + with self.assertRaises(NotSupportedTOCError): + calculate_mb_toc_numbers(entries) + + def test_calculate_mb_toc_numbers_empty_entries(self): + with self.assertRaises(NotSupportedTOCError): + calculate_mb_toc_numbers([])