From 65e9439d45623d609e7157a5425840d745ce9148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katharina=20Dr=C3=B6ge?= Date: Wed, 24 Sep 2025 23:14:36 +0200 Subject: [PATCH] Support releases with multiple catalog numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Katharina Dröge --- whipper/command/mblookup.py | 16 +++++------ whipper/common/mbngs.py | 17 ++++++++---- whipper/common/program.py | 26 +++++++++--------- whipper/test/test_common_mbngs.py | 2 +- ...discid.xu338_M8WukSRi0J.KTlDoflB8Y-.pickle | Bin 7307 -> 6692 bytes 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/whipper/command/mblookup.py b/whipper/command/mblookup.py index 75ebf9f..db8b886 100644 --- a/whipper/command/mblookup.py +++ b/whipper/command/mblookup.py @@ -26,15 +26,15 @@ Example Disc ID: KnpGsLhvH.lPrNc1PBL21lb9Bg4-""" :param md: MusicBrainz's metadata about the disc :type md: `DiscMetadata` """ - print(' Artist: %s' % md.artist.encode('utf-8')) - print(' Title: %s' % md.releaseTitle.encode('utf-8')) - print(' Type: %s' % str(md.releaseType).encode('utf-8')) - print(' URL: %s' % md.url) - print(' Tracks: %d' % len(md.tracks)) - if md.catalogNumber: - print(' Cat no: %s' % md.catalogNumber) + print(' Artist: %s' % md.artist.encode('utf-8')) + print(' Title: %s' % md.releaseTitle.encode('utf-8')) + print(' Type: %s' % str(md.releaseType).encode('utf-8')) + print(' URL: %s' % md.url) + print(' Tracks: %d' % len(md.tracks)) + if md.catalogNumbers: + print(' Cat no(s): %s' % ', '.join(md.catalogNumbers)) if md.barcode: - print(' Barcode: %s' % md.barcode) + print(' Barcode: %s' % md.barcode) for j, track in enumerate(md.tracks): print(' Track %2d: %s - %s' % ( diff --git a/whipper/common/mbngs.py b/whipper/common/mbngs.py index c6a2aaa..f56ae49 100644 --- a/whipper/common/mbngs.py +++ b/whipper/common/mbngs.py @@ -81,8 +81,8 @@ class DiscMetadata: :vartype discNumber: int or None :cvar discTotal: total number of discs in the chosen release :vartype discTotal: int or None - :cvar catalogNumber: release catalog number - :vartype catalogNumber: str or None + :cvar catalogNumbers: release catalog number + :vartype catalogNumbers: list[str] :cvar barcode: release barcode :vartype barcode: str or None """ @@ -103,7 +103,7 @@ class DiscMetadata: mbidArtist = None url = None - catalogNumber = None + catalogNumbers: list[str] barcode = None countries = None discNumber = None @@ -112,6 +112,7 @@ class DiscMetadata: def __init__(self): self.tracks = [] + self.catalogNumbers = [] def _record(record, which, name, what): @@ -289,9 +290,13 @@ def _getMetadata(release, discid=None, country=None): discMD.countries = list(filter(None, countries)) else: discMD.countries = list(filter(None, [release.get('country', None)])) - lil = release.get('label-info-list', [{}]) - if lil: - discMD.catalogNumber = lil[0].get('catalog-number') + lil = release.get('label-info-list', []) + catalog_numbers = [] + for li in lil: + cn = li.get('catalog-number') + if cn and cn not in catalog_numbers: + catalog_numbers.append(cn) + discMD.catalogNumbers = catalog_numbers tainted = False duration = 0 diff --git a/whipper/common/program.py b/whipper/common/program.py index 0659b56..690a2d2 100644 --- a/whipper/common/program.py +++ b/whipper/common/program.py @@ -150,8 +150,8 @@ class Program: @staticmethod def addDisambiguation(template_part, metadata): """Add disambiguation to template path part string.""" - if metadata.catalogNumber: - template_part += ' (%s)' % metadata.catalogNumber + if metadata.catalogNumbers: + template_part += ' (%s)' % ', '.join(metadata.catalogNumbers) elif metadata.barcode: template_part += ' (%s)' % metadata.barcode return template_part @@ -220,7 +220,7 @@ class Program: v['d'] = metadata.releaseTitle v['D'] = metadata.title v['B'] = metadata.barcode - v['C'] = metadata.catalogNumber + v['C'] = ', '.join(metadata.catalogNumbers) v['c'] = metadata.releaseDisambCmt v['M'] = metadata.discTotal v['N'] = metadata.discNumber @@ -331,20 +331,20 @@ class Program: print('\nMatching releases:') for metadata in metadatas: - print('\nArtist : %s' % metadata.artist) - print('Title : %s' % metadata.releaseTitle) - print('Duration: %s' % common.formatTime( + print('\nArtist : %s' % metadata.artist) + print('Title : %s' % metadata.releaseTitle) + print('Duration : %s' % common.formatTime( metadata.duration / 1000.0)) - print('URL : %s' % metadata.url) - print('Release : %s' % metadata.mbid) - print('Type : %s' % metadata.releaseType) + print('URL : %s' % metadata.url) + print('Release : %s' % metadata.mbid) + print('Type : %s' % metadata.releaseType) if metadata.barcode: - print("Barcode : %s" % metadata.barcode) + print("Barcode : %s" % metadata.barcode) if metadata.countries: - print("Country : %s" % ', '.join(metadata.countries)) + print("Country : %s" % ', '.join(metadata.countries)) # TODO: Add test for non ASCII catalog numbers: see issue #215 - if metadata.catalogNumber: - print("Cat no : %s" % metadata.catalogNumber) + if metadata.catalogNumbers: + print("Cat no(s): %s" % ', '.join(metadata.catalogNumbers)) delta = abs(metadata.duration - ittoc.duration()) if delta not in deltas: diff --git a/whipper/test/test_common_mbngs.py b/whipper/test/test_common_mbngs.py index 0d306d6..819ee66 100644 --- a/whipper/test/test_common_mbngs.py +++ b/whipper/test/test_common_mbngs.py @@ -287,7 +287,7 @@ class MetadataTestCase(unittest.TestCase): self.assertEqual(metadata.url, 'https://musicbrainz.org/release' '/6109ceed-7e21-490b-b5ad-3a66b4e4cfbb') - self.assertEqual(metadata.catalogNumber, '[none]') + self.assertEqual(metadata.catalogNumbers, ['[none]']) self.assertEqual(metadata.barcode, '700261430249') self.assertEqual(len(metadata.tracks), 16) diff --git a/whipper/test/whipper.discid.xu338_M8WukSRi0J.KTlDoflB8Y-.pickle b/whipper/test/whipper.discid.xu338_M8WukSRi0J.KTlDoflB8Y-.pickle index acf79b77e5717e40bc751813f298cac872cd42d0..bf8040122b78d5160958c1bc087efb608d7fc5d8 100644 GIT binary patch literal 6692 zcmeI1UCSJ28OK`_lO{B25Bg%7R;L=;1advk{r)0|RI9~^r6egi3V7Xb&#vz7Jj~1{ zC@9ebL7B6Tf(L#HLBBx1fG2{-1;HafgV*eALi41^nu0yq2L_&DcXns)-+f)z|Nq|y zr+yYn{wD0i5!!{MXh+OLLR3|IRz zU4!wb?QnOvI(xRiaC`vWmnD^&slN{G=ZpIzZpQmk8>Snn;eJ-sV z?B?}qxbeH2&pxvbvvbp~nLYo%KmP3EQ}Lg@_=Q2Az5EnU`RZrmwbzE(rT$7*+3&61-;xgcS;{Qkq)lh7^;^TQ3-)pA?@+6&;mFEy406X+Bx%X(mPB%$1lVYN4p7QS(CoL{ z#bN^|+Dt)%q^PGDDhA{QyrPMZN_y{@M7}k!IYi1V4Y{T`ia75m+A~6s+M{ewX@<@} zA>#fe_RVZZIOl)xNWE>ikWk}vAYc&GpHNT=OTrBdPgnxePAjT~QCv$?Wbp}1D2BRO z3gD#+V3ed}$Xb!`3A_61x5uK%{l!RW{GvX3f4!vad=tW+G1hCa1NLX{VKcAS?eN?G zW8m7KZSo>xOF{K%@(^V7D7PfnU^vB&AR+}^$}vUq)ko zy*{Q;+Ths7qX8q`n0TrLD5(?K9BJJGB?6Mh!50_u_NUg(V(8zUb=`6M&BMdxx}C?+ z;C%J-gSt67+%Cr9ZYyv$U=!;^Yj?q0=Q)+M= literal 7307 zcmbW6%Z?kz6^8fy6rD{*22@hrFWCgn&2WGShR2pS0ff3zOgJRbBqcZxnn%ex|EVS^ z0U8->3K&U4Hk;k&tMgZV)h{-CKIFXH|N3sKs{w!I-S%*tPWiZ-hP@bGr;_cyrwA;m5rh zUX;BZ9v=?7>G&o-)rVp4hPU6H4#(IIhu!w&`1k)!tBQaBdpOo9)oJx|{OgA}{(k)P z?&GGu9KYR`Ux&RP4v!CUI<5~#oFWWw=Z}q_pNT$pJqu1ipPbKv`{8tg)3m{-g}?>9 zKOXmoKfHeZbULhan&NuNOP} zMHPXnD*3RwtCUjE)jXwj`4P;gvfi$6QBvZft!HXn_Fl$Rxg+P6S zW|_Qbbg=0M2Vp|Uk$Dq5)0#WxWAwQ8>S8S=6shT8JH$hZG*VXAQJ@?~f$}s8RJd~# zXw+lXp(~+r{G zs)Y}>Xl7yxsC?4QTY++MDU{>hn@odG)9@mcLIuz1o@RQQLgz+$+AW}`{Q`PAJVVcL z3Pu1edn50pXL`w~Wxa^T$z)l}5`(TGtddokwWeh@NyccXWlb-v9^O(rq2tHRy46dg z`hT9#_9}#LaNvFYYS2b!hQ?hOM&omkEikWZV>(E5PensSsl9B?B%Y~_4SITJ=!6V( zXEQ@X?R_Id%NH=TVgW-dpJ8Yf7+T$DH*+ULN}jm`xzfP}#hJCp7VRPhM~W=?#C0^n zqFShv?S-YZ{Q(hH>vR~`+wri+)Osc2z`%; zK0}(ULo|vxQ50r%hk&;wGc03TE-D(SDd0UtL`SF$;`4&go7)k3%vLwggMN*C&6pq0fp3_T!-V5!a3=q=-}P!nd(0@ggtSgD-T9&PFAD=8rQ zWGL~^JRw~Rl zEObh?Sbg)>T%d6#NLl87#KPv&%0_g3xiM1({A2-6BsU#>TT2RP%`-S*H^2$IA)K^i zy-QLAOy@j1W~F!wHL+$D*5FMP%#Ox0r?Lt{HiJ>v>(whvIDbCWcG_Ta{7|>F+P@eH zMpx$vb-IfunbWy91(weEKk<|~BquTiBzTx&g)M}FD=neMiXT^cZV0lbxjTgju!~E; ziXJAn0)nNBiH-I|aLG-0rR$2mKf->K!N{aaWXZv@=T2TXwk!3^j}Fr~!5) zd0{R#p{>OJfa@qBYBNe{5W$~?EoAL>l#sdwC?S6fP{R10K?$t`N;n&#goE9Qa#ps! z2(pONm}y5sV{-Bh+MSevd#9+13o$5C5z(Ekqx_-n_M1A!VOc+MhKx`cOsmPts@kvghWeNG#ug;D<7|vW+}SVG#8eqK3{fa>j)o7A^XlG zeC;lDaJMTusM#4^#lkt(T3F^9;vqC=sWicamnmXOk4ca_3i#O>U69z_p(KtJl0L$-G;E;#jp#*Y#st`c4nAe#SRYk!CkXRg(w;e8mq6U zv0vo5ilX~J1mw&Rp=$f);+Y{N?RJKcxdjX%eG3@E^qye|odZM28Zm@?-N|rvwa!r4 zrdlY>re+bNC9$AW(gq@4iKWvw&({<==>uTvrKNKc5{r3EpCUGQN^D)19o zOcHq>C3eTLL}gZ#*b+D1=)R*5H9NPU#?t$fI!f5t&G;lF?sk08=>_;C{EqNlg2LJ` zZ+3J)zU^U+B;$L0_zAHV)As87c