From 2f88190d68ea8e64f2b267bb38538d82e7dae17f Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Mon, 6 Jan 2020 23:11:51 +0100 Subject: [PATCH] Implement Popularimeter #23 --- mediafile.py | 34 ++++++++++++++++++++++++++++++++++ test/test_mediafile.py | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/mediafile.py b/mediafile.py index 51f352a..b87bbde 100644 --- a/mediafile.py +++ b/mediafile.py @@ -1222,6 +1222,8 @@ def _none_value(self): return False elif self.out_type == six.text_type: return u'' + elif self.out_type == dict: + return {} class ListMediaField(MediaField): @@ -1414,6 +1416,34 @@ def __delete__(self, mediafile): delattr(mediafile, 'images') +class PopmMediaField(MediaField): + """ Access Popularimeter as dictionary.""" + + +class MP3PopmStorageStyle(StorageStyle): + formats = ['MP3'] + + def get(self, mutagen_file): + """Returns POPM dictionary: {EMAIL: {'rating': RATING, 'count': COUNT}} + """ + return { + popm.email: {'rating': popm.rating, 'count': popm.count} + for popm in mutagen_file.tags.getall('POPM') + } + + def set(self, mutagen_file, value): + """Set POPM. 'count' will be set to 0 by default.""" + popm_list = [ + mutagen.id3.POPM( + email=email, + rating=value[email]['rating'], + count=value[email].get('count', 0) + ) + for email in value.keys() + ] + mutagen_file.tags.setall('POPM', popm_list) + + class QNumberField(MediaField): """Access integer-represented Q number fields. @@ -1849,6 +1879,10 @@ def update(self, dict): StorageStyle('MUSICBRAINZ_ALBUMCOMMENT'), ASFStorageStyle('MusicBrainz/Album Comment'), ) + popm = PopmMediaField( + MP3PopmStorageStyle(key='POPM', as_type=list), + out_type=dict + ) # Release date. date = DateField( diff --git a/test/test_mediafile.py b/test/test_mediafile.py index e9e1850..3f83226 100644 --- a/test/test_mediafile.py +++ b/test/test_mediafile.py @@ -755,6 +755,37 @@ def test_unknown_apic_type(self): mediafile = self._mediafile_fixture('image_unknown_type') self.assertEqual(mediafile.images[0].type, ImageType.other) + def test_write_single_popm(self): + mediafile = self._mediafile_fixture('empty') + test_email = 'test1@foobar.de' + mediafile.popm = { + test_email: {'rating': 1, 'count': 1} + } + mediafile.save() + self.assertEqual(mediafile.popm, { + test_email: {'rating': 1, 'count': 1} + }) + + def test_write_popm_without_count(self): + mediafile = self._mediafile_fixture('empty') + test_email = 'test1@foobar.de' + mediafile.popm = {test_email: {'rating': 1}} + mediafile.save() + self.assertEqual(mediafile.popm, { + test_email: {'rating': 1, 'count': 0} + }) + + def test_write_multiple_popm(self): + mediafile = self._mediafile_fixture('full') + mediafile.popm = {'test1@foobar.de': {'rating': 1, 'count': 1}, + 'test2@foobar.de': {'rating': 2, 'count': 2}} + mediafile.save() + + self.assertEqual(mediafile.popm, { + 'test1@foobar.de': {'rating': 1, 'count': 1}, + 'test2@foobar.de': {'rating': 2, 'count': 2}, + }) + class MP4Test(ReadWriteTestBase, PartialTestMixin, ImageStructureTestMixin, unittest.TestCase): @@ -975,7 +1006,7 @@ def test_properties_from_readable_fields(self): def test_known_fields(self): fields = list(ReadWriteTestBase.tag_fields) - fields.extend(('encoder', 'images', 'genres', 'albumtype')) + fields.extend(('encoder', 'images', 'genres', 'albumtype', 'popm')) assertCountEqual(self, MediaFile.fields(), fields) def test_fields_in_readable_fields(self):