Пример #1
0
    def test_cmd_inmulti(self):
        context = Metadata()

        # Test with single-value string
        context["foo"] = "First:A; Second:B; Third:C"
        # Tests with $in for comparison purposes
        self.assertScriptResultEquals("$in(%foo%,Second:B)", "1", context)
        self.assertScriptResultEquals("$in(%foo%,irst:A; Second:B; Thi)", "1",
                                      context)
        self.assertScriptResultEquals("$in(%foo%,First:A; Second:B; Third:C)",
                                      "1", context)
        # Base $inmulti tests
        self.assertScriptResultEquals("$inmulti(%foo%,Second:B)", "", context)
        self.assertScriptResultEquals("$inmulti(%foo%,irst:A; Second:B; Thi)",
                                      "", context)
        self.assertScriptResultEquals(
            "$inmulti(%foo%,First:A; Second:B; Third:C)", "1", context)
        # Test separator override but with existing separator - results should be same as base
        self.assertScriptResultEquals("$inmulti(%foo%,Second:B,; )", "",
                                      context)
        self.assertScriptResultEquals(
            "$inmulti(%foo%,irst:A; Second:B; Thi,; )", "", context)
        self.assertScriptResultEquals(
            "$inmulti(%foo%,First:A; Second:B; Third:C,; )", "1", context)
        # Test separator override
        self.assertScriptResultEquals("$inmulti(%foo%,First:A,:)", "", context)
        self.assertScriptResultEquals("$inmulti(%foo%,Second:B,:)", "",
                                      context)
        self.assertScriptResultEquals("$inmulti(%foo%,Third:C,:)", "", context)
        self.assertScriptResultEquals("$inmulti(%foo%,First,:)", "1", context)
        self.assertScriptResultEquals("$inmulti(%foo%,A; Second,:)", "1",
                                      context)
        self.assertScriptResultEquals("$inmulti(%foo%,B; Third,:)", "1",
                                      context)
        self.assertScriptResultEquals("$inmulti(%foo%,C,:)", "1", context)

        # Test with multi-values
        context["foo"] = ["First:A", "Second:B", "Third:C"]
        # Tests with $in for comparison purposes
        self.assertScriptResultEquals("$in(%foo%,Second:B)", "1", context)
        self.assertScriptResultEquals("$in(%foo%,irst:A; Second:B; Thi)", "1",
                                      context)
        self.assertScriptResultEquals("$in(%foo%,First:A; Second:B; Third:C)",
                                      "1", context)
        # Base $inmulti tests
        self.assertScriptResultEquals("$inmulti(%foo%,Second:B)", "1", context)
        self.assertScriptResultEquals("$inmulti(%foo%,irst:A; Second:B; Thi)",
                                      "", context)
        self.assertScriptResultEquals(
            "$inmulti(%foo%,First:A; Second:B; Third:C)", "", context)
        # Test separator override but with existing separator - results should be same as base
        self.assertScriptResultEquals("$inmulti(%foo%,Second:B,; )", "1",
                                      context)
        self.assertScriptResultEquals(
            "$inmulti(%foo%,irst:A; Second:B; Thi,; )", "", context)
        self.assertScriptResultEquals(
            "$inmulti(%foo%,First:A; Second:B; Third:C,; )", "", context)
        # Test separator override
        self.assertScriptResultEquals("$inmulti(%foo%,First:A,:)", "", context)
        self.assertScriptResultEquals("$inmulti(%foo%,Second:B,:)", "",
                                      context)
        self.assertScriptResultEquals("$inmulti(%foo%,Third:C,:)", "", context)
        self.assertScriptResultEquals("$inmulti(%foo%,First,:)", "1", context)
        self.assertScriptResultEquals("$inmulti(%foo%,A; Second,:)", "1",
                                      context)
        self.assertScriptResultEquals("$inmulti(%foo%,B; Third,:)", "1",
                                      context)
        self.assertScriptResultEquals("$inmulti(%foo%,C,:)", "1", context)
Пример #2
0
 def test_artist(self):
     m = Metadata()
     artist_to_metadata(self.json_doc, m)
     self.assertEqual(m, {})
Пример #3
0
 def test_can_open_and_save(self):
     metadata = save_and_load_metadata(self.filename, Metadata())
     self.assertTrue(metadata['~format'])
Пример #4
0
 def test_recording(self):
     m = Metadata()
     t = Track("1")
     recording_to_metadata(self.json_doc, m, t)
     self.assertEqual(m, {})
Пример #5
0
 def test_track(self):
     m = Metadata()
     medium_to_metadata(self.json_doc, m)
     self.assertEqual(m['discnumber'], '1')
     self.assertEqual(m['media'], '12" Vinyl')
     self.assertEqual(m['totaltracks'], '10')
Пример #6
0
    def _load(self, filename):
        log.debug("Loading file %r", filename)
        config = get_config()
        file = self._File(encode_filename(filename))
        file.tags = file.tags or {}
        metadata = Metadata()
        for origname, values in file.tags.items():
            for value in values:
                name = origname
                if name == "date" or name == "originaldate":
                    # YYYY-00-00 => YYYY
                    value = sanitize_date(value)
                elif name == 'performer' or name == 'comment':
                    # transform "performer=Joe Barr (Piano)" to "performer:Piano=Joe Barr"
                    name += ':'
                    if value.endswith(')'):
                        start = len(value) - 2
                        count = 1
                        while count > 0 and start > 0:
                            if value[start] == ')':
                                count += 1
                            elif value[start] == '(':
                                count -= 1
                            start -= 1
                        if start > 0:
                            name += value[start + 2:-1]
                            value = value[:start]
                elif name.startswith('rating'):
                    try:
                        name, email = name.split(':', 1)
                    except ValueError:
                        email = ''
                    if email != sanitize_key(
                            config.setting['rating_user_email']):
                        continue
                    name = '~rating'
                    try:
                        value = str(
                            round((float(value) *
                                   (config.setting['rating_steps'] - 1))))
                    except ValueError:
                        log.warning('Invalid rating value in %r: %s', filename,
                                    value)
                elif name == "fingerprint" and value.startswith(
                        "MusicMagic Fingerprint"):
                    name = "musicip_fingerprint"
                    value = value[22:]
                elif name == "tracktotal":
                    if "totaltracks" in file.tags:
                        continue
                    name = "totaltracks"
                elif name == "disctotal":
                    if "totaldiscs" in file.tags:
                        continue
                    name = "totaldiscs"
                elif name == "metadata_block_picture":
                    try:
                        image = mutagen.flac.Picture(
                            base64.standard_b64decode(value))
                        coverartimage = TagCoverArtImage(
                            file=filename,
                            tag=name,
                            types=types_from_id3(image.type),
                            comment=image.desc,
                            support_types=True,
                            data=image.data,
                        )
                    except (CoverArtImageError, TypeError, ValueError,
                            mutagen.flac.error) as e:
                        log.error('Cannot load image from %r: %s' %
                                  (filename, e))
                    else:
                        metadata.images.append(coverartimage)
                    continue
                elif name in self.__translate:
                    name = self.__translate[name]
                metadata.add(name, value)
        if self._File == mutagen.flac.FLAC:
            for image in file.pictures:
                try:
                    coverartimage = TagCoverArtImage(
                        file=filename,
                        tag='FLAC/PICTURE',
                        types=types_from_id3(image.type),
                        comment=image.desc,
                        support_types=True,
                        data=image.data,
                    )
                except CoverArtImageError as e:
                    log.error('Cannot load image from %r: %s' % (filename, e))
                else:
                    metadata.images.append(coverartimage)

        # Read the unofficial COVERART tags, for backward compatibility only
        if "metadata_block_picture" not in file.tags:
            try:
                for data in file["COVERART"]:
                    try:
                        coverartimage = TagCoverArtImage(
                            file=filename,
                            tag='COVERART',
                            data=base64.standard_b64decode(data))
                    except (CoverArtImageError, TypeError, ValueError) as e:
                        log.error('Cannot load image from %r: %s' %
                                  (filename, e))
                    else:
                        metadata.images.append(coverartimage)
            except KeyError:
                pass
        self._info(metadata, file)
        return metadata
Пример #7
0
    def _finalize_loading(self, error):
        if error:
            self.metadata.clear()
            self.status = _("[could not load album %s]") % self.id
            del self._new_metadata
            del self._new_tracks
            self.update()
            return

        if self._requests > 0:
            return

        if not self._tracks_loaded:
            artists = set()
            totalalbumtracks = 0
            absolutetracknumber = 0
            va = self._new_metadata['musicbrainz_albumartistid'] == VARIOUS_ARTISTS_ID

            djmix_ars = {}
            if hasattr(self._new_metadata, "_djmix_ars"):
                djmix_ars = self._new_metadata._djmix_ars

            for medium_node in self._release_node.medium_list[0].medium:
                mm = Metadata()
                mm.copy(self._new_metadata)
                medium_to_metadata(medium_node, mm)
                totalalbumtracks += int(mm["totaltracks"])

                for dj in djmix_ars.get(mm["discnumber"], []):
                    mm.add("djmixer", dj)

                if "pregap" in medium_node.children:
                    track = self._finalize_loading_track(medium_node.pregap[0], mm, artists, va, absolutetracknumber)
                    track.metadata['~pregap'] = "1"

                for track_node in medium_node.track_list[0].track:
                    absolutetracknumber += 1
                    track = self._finalize_loading_track(track_node, mm, artists, va, absolutetracknumber)

                if "data_track_list" in medium_node.children:
                    for track_node in medium_node.data_track_list[0].track:
                        absolutetracknumber += 1
                        track = self._finalize_loading_track(track_node, mm, artists, va, absolutetracknumber)
                        track.metadata['~datatrack'] = "1"

            totalalbumtracks = str(totalalbumtracks)

            for track in self._new_tracks:
                track.metadata["~totalalbumtracks"] = totalalbumtracks
                if len(artists) > 1:
                    track.metadata["~multiartist"] = "1"
            del self._release_node
            self._tracks_loaded = True

        if not self._requests:
            # Prepare parser for user's script
            if config.setting["enable_tagger_script"]:
                script = config.setting["tagger_script"]
                if script:
                    parser = ScriptParser()
                    for track in self._new_tracks:
                        # Run tagger script for each track
                        try:
                            parser.eval(script, track.metadata)
                        except:
                            self.error_append(traceback.format_exc())
                        # Strip leading/trailing whitespace
                        track.metadata.strip_whitespace()
                    # Run tagger script for the album itself
                    try:
                        parser.eval(script, self._new_metadata)
                    except:
                        self.error_append(traceback.format_exc())
                    self._new_metadata.strip_whitespace()

            for track in self.tracks:
                for file in list(track.linked_files):
                    file.move(self.unmatched_files)
            self.metadata = self._new_metadata
            self.tracks = self._new_tracks
            del self._new_metadata
            del self._new_tracks
            self.loaded = True
            self.status = None
            self.match_files(self.unmatched_files.files)
            self.update()
            self.tagger.window.set_statusbar_message(
                N_('Album %(id)s loaded: %(artist)s - %(album)s'),
                {
                    'id': self.id,
                    'artist': self.metadata['albumartist'],
                    'album': self.metadata['album']
                },
                timeout=3000
            )
            for func in self._after_load_callbacks:
                func()
            self._after_load_callbacks = []
Пример #8
0
 def test_preserve_leading_and_trailing_whitespace(self):
     metadata = Metadata()
     metadata['artist'] = 'The Artist'
     filename = script_to_filename(' %artist% ', metadata)
     self.assertEqual(' The Artist ', filename)
Пример #9
0
 def test_plain_filename(self):
     metadata = Metadata()
     filename = script_to_filename('AlbumArt', metadata)
     self.assertEqual('AlbumArt', filename)
Пример #10
0
 def test_remove_null_chars(self):
     metadata = Metadata()
     filename = script_to_filename('a\x00b\x00', metadata)
     self.assertEqual('ab', filename)
Пример #11
0
 def test_remove_tabs_and_linebreaks_chars(self):
     metadata = Metadata()
     filename = script_to_filename('a\tb\nc', metadata)
     self.assertEqual('abc', filename)
Пример #12
0
    def _finalize_loading(self, error):
        if error:
            self.metadata.clear()
            self.status = _("[could not load album %s]") % self.id
            del self._new_metadata
            del self._new_tracks
            self.update()
            return

        if self._requests > 0:
            return

        if not self._tracks_loaded:
            artists = set()
            totalalbumtracks = 0
            absolutetracknumber = 0
            va = self._new_metadata['musicbrainz_albumartistid'] == VARIOUS_ARTISTS_ID

            djmix_ars = {}
            if hasattr(self._new_metadata, "_djmix_ars"):
                djmix_ars = self._new_metadata._djmix_ars

            for medium_node in self._release_node['media']:
                mm = Metadata()
                mm.copy(self._new_metadata)
                medium_to_metadata(medium_node, mm)
                discpregap = False

                for dj in djmix_ars.get(mm["discnumber"], []):
                    mm.add("djmixer", dj)

                if "pregap" in medium_node:
                    discpregap = True
                    absolutetracknumber += 1
                    track = self._finalize_loading_track(medium_node['pregap'], mm, artists, va, absolutetracknumber, discpregap)
                    track.metadata['~pregap'] = "1"

                track_count = medium_node['track-count']
                if track_count:
                    tracklist_node = medium_node['tracks']
                    for track_node in tracklist_node:
                        absolutetracknumber += 1
                        track = self._finalize_loading_track(track_node, mm, artists, va, absolutetracknumber, discpregap)

                if "data-tracks" in medium_node:
                    for track_node in medium_node['data-tracks']:
                        absolutetracknumber += 1
                        track = self._finalize_loading_track(track_node, mm, artists, va, absolutetracknumber, discpregap)
                        track.metadata['~datatrack'] = "1"

            totalalbumtracks = string_(absolutetracknumber)

            for track in self._new_tracks:
                track.metadata["~totalalbumtracks"] = totalalbumtracks
                if len(artists) > 1:
                    track.metadata["~multiartist"] = "1"
            del self._release_node
            self._tracks_loaded = True

        if not self._requests:
            for track in self._new_tracks:
                track.orig_metadata.copy(track.metadata)

            self.enable_update_metadata_images(False)
            # Prepare parser for user's script
            for s_name, s_text in enabled_tagger_scripts_texts():
                parser = ScriptParser()
                for track in self._new_tracks:
                    # Run tagger script for each track
                    try:
                        parser.eval(s_text, track.metadata)
                    except:
                        log.exception("Failed to run tagger script %s on track", s_name)
                    track.metadata.strip_whitespace()
                # Run tagger script for the album itself
                try:
                    parser.eval(s_text, self._new_metadata)
                except:
                    log.exception("Failed to run tagger script %s on album", s_name)
                self._new_metadata.strip_whitespace()

            for track in self.tracks:
                track.metadata_images_changed.connect(self.update_metadata_images)
                for file in list(track.linked_files):
                    file.move(self.unmatched_files)
            self.metadata = self._new_metadata
            self.tracks = self._new_tracks
            del self._new_metadata
            del self._new_tracks
            self.loaded = True
            self.status = None
            self.match_files(self.unmatched_files.files)
            self.enable_update_metadata_images(True)
            self.update()
            self.tagger.window.set_statusbar_message(
                N_('Album %(id)s loaded: %(artist)s - %(album)s'),
                {
                    'id': self.id,
                    'artist': self.metadata['albumartist'],
                    'album': self.metadata['album']
                },
                timeout=3000
            )
            for func in self._after_load_callbacks:
                func()
            self._after_load_callbacks = []
Пример #13
0
 def parse_artists(self, artists):
     for node in artists:
         artist = Metadata()
         artist_to_metadata(node, artist)
         artist['score'] = node['score']
         self.search_results.append(artist)
Пример #14
0
 def test_cmd_set_multi_valued(self):
     context = Metadata()
     context["source"] = ["multi", "valued"]
     self.parser.eval("$set(test,%source%)", context)
     self.assertEqual(context.getall("test"),
                      ["multi; valued"])  # list has only a single value
Пример #15
0
    def _load(self, filename):
        log.debug("Loading file %r", filename)
        file = self._get_file(encode_filename(filename))
        tags = file.tags or {}
        # upgrade custom 2.3 frames to 2.4
        for old, new in self.__upgrade.items():
            if old in tags and new not in tags:
                f = tags.pop(old)
                tags.add(getattr(id3, new)(encoding=f.encoding, text=f.text))
        metadata = Metadata()
        for frame in tags.values():
            frameid = frame.FrameID
            if frameid in self.__translate:
                name = self.__translate[frameid]
                if frameid.startswith('T'):
                    for text in frame.text:
                        if text:
                            metadata.add(name, string_(text))
                elif frameid == 'COMM':
                    for text in frame.text:
                        if text:
                            metadata.add('%s:%s' % (name, frame.desc),
                                         string_(text))
                else:
                    metadata.add(name, string_(frame))
            elif frameid == "TMCL":
                for role, name in frame.people:
                    if role or name:
                        metadata.add('performer:%s' % role, name)
            elif frameid == "TIPL":
                # If file is ID3v2.3, TIPL tag could contain TMCL
                # so we will test for TMCL values and add to TIPL if not TMCL
                for role, name in frame.people:
                    if role in self._tipl_roles and name:
                        metadata.add(self._tipl_roles[role], name)
                    else:
                        metadata.add('performer:%s' % role, name)
            elif frameid == 'TXXX':
                name = frame.desc
                if name in self.__translate_freetext:
                    name = self.__translate_freetext[name]
                elif ((name in self.__rtranslate) !=
                      (name in self.__rtranslate_freetext)):
                    # If the desc of a TXXX frame conflicts with the name of a
                    # Picard tag, load it into ~id3:TXXX:desc rather than desc.
                    #
                    # This basically performs an XOR, making sure that 'name'
                    # is in __rtranslate or __rtranslate_freetext, but not
                    # both. (Being in both implies we support reading it both
                    # ways.) Currently, the only tag in both is license.
                    name = '~id3:TXXX:' + name
                for text in frame.text:
                    metadata.add(name, string_(text))
            elif frameid == 'USLT':
                name = 'lyrics'
                if frame.desc:
                    name += ':%s' % frame.desc
                metadata.add(name, string_(frame.text))
            elif frameid == 'UFID' and frame.owner == 'http://musicbrainz.org':
                metadata['musicbrainz_recordingid'] = frame.data.decode(
                    'ascii', 'ignore')
            elif frameid in self.__tag_re_parse.keys():
                m = self.__tag_re_parse[frameid].search(frame.text[0])
                if m:
                    for name, value in m.groupdict().items():
                        if value is not None:
                            metadata[name] = value
                else:
                    log.error("Invalid %s value '%s' dropped in %r", frameid,
                              frame.text[0], filename)
            elif frameid == 'APIC':
                try:
                    coverartimage = TagCoverArtImage(
                        file=filename,
                        tag=frameid,
                        types=types_from_id3(frame.type),
                        comment=frame.desc,
                        support_types=True,
                        data=frame.data,
                    )
                except CoverArtImageError as e:
                    log.error('Cannot load image from %r: %s' % (filename, e))
                else:
                    metadata.append_image(coverartimage)
            elif frameid == 'POPM':
                # Rating in ID3 ranges from 0 to 255, normalize this to the range 0 to 5
                if frame.email == config.setting['rating_user_email']:
                    rating = string_(
                        int(
                            round(frame.rating / 255.0 *
                                  (config.setting['rating_steps'] - 1))))
                    metadata.add('~rating', rating)

        if 'date' in metadata:
            sanitized = sanitize_date(metadata.getall('date')[0])
            if sanitized:
                metadata['date'] = sanitized

        self._info(metadata, file)
        return metadata
Пример #16
0
 def test_preserve_backslash(self):
     metadata = Metadata()
     metadata['artist'] = 'AC\\/DC'
     filename = script_to_filename('%artist%', metadata)
     self.assertEqual('AC__DC' if IS_WIN else 'AC\\_DC', filename)
Пример #17
0
 def parse_artists_from_xml(self, artist_xml):
     for node in artist_xml:
         artist = Metadata()
         artist_to_metadata(node, artist)
         self.search_results.append(artist)
Пример #18
0
 def test_file_metadata(self):
     metadata = Metadata()
     file = File('somepath/somefile.mp3')
     self.assertEqual('', script_to_filename('$has_file()', metadata))
     self.assertEqual(
         '1', script_to_filename('$has_file()', metadata, file=file))
Пример #19
0
 def test_recording(self):
     m = Metadata()
     t = Track("1")
     parsed_recording = parse_recording(self.json_doc)
     recording_to_metadata(parsed_recording, m, t)
     self.assertEqual(m, {})
Пример #20
0
    def _load(self, filename):
        log.debug("Loading file %r", filename)
        self.__casemap = {}
        file = MP4(encode_filename(filename))
        tags = file.tags or {}
        metadata = Metadata()
        for name, values in tags.items():
            name_lower = name.lower()
            if name in self.__text_tags:
                for value in values:
                    metadata.add(self.__text_tags[name], value)
            elif name in self.__bool_tags:
                metadata.add(self.__bool_tags[name], values and '1' or '0')
            elif name in self.__int_tags:
                for value in values:
                    metadata.add(self.__int_tags[name], value)
            elif name in self.__freeform_tags:
                tag_name = self.__freeform_tags[name]
                _add_text_values_to_metadata(metadata, tag_name, values)
            elif name_lower in self.__freeform_tags_ci:
                tag_name = self.__freeform_tags_ci[name_lower]
                self.__casemap[tag_name] = name
                _add_text_values_to_metadata(metadata, tag_name, values)
            elif name == "----:com.apple.iTunes:fingerprint":
                for value in values:
                    value = value.decode("utf-8", "replace").strip("\x00")
                    if value.startswith("MusicMagic Fingerprint"):
                        metadata.add("musicip_fingerprint", value[22:])
            elif name == "trkn":
                metadata["tracknumber"] = values[0][0]
                metadata["totaltracks"] = values[0][1]
            elif name == "disk":
                metadata["discnumber"] = values[0][0]
                metadata["totaldiscs"] = values[0][1]
            elif name == "covr":
                for value in values:
                    if value.imageformat not in (value.FORMAT_JPEG,
                                                 value.FORMAT_PNG):
                        continue
                    try:
                        coverartimage = TagCoverArtImage(
                            file=filename,
                            tag=name,
                            data=value,
                        )
                    except CoverArtImageError as e:
                        log.error('Cannot load image from %r: %s' %
                                  (filename, e))
                    else:
                        metadata.images.append(coverartimage)
            # Read other freeform tags always case insensitive
            elif name.startswith('----:com.apple.iTunes:'):
                tag_name = name_lower[22:]
                self.__casemap[tag_name] = name[22:]
                if (name not in self.__r_text_tags
                        and name not in self.__r_bool_tags
                        and name not in self.__r_int_tags
                        and name not in self.__r_freeform_tags
                        and name_lower not in self.__r_freeform_tags_ci
                        and name not in self.__other_supported_tags):
                    _add_text_values_to_metadata(metadata, tag_name, values)

        self._info(metadata, file)
        return metadata
Пример #21
0
 def test_release(self):
     m = Metadata()
     a = Album("1")
     release_to_metadata(self.json_doc, m, a)
     self.assertEqual(m, {})
Пример #22
0
def file_save_image(filename, image):
    f = picard.formats.open_(filename)
    metadata = Metadata(images=[image])
    f._save(filename, metadata)
Пример #23
0
 def test_recording_instrument_keep_case(self):
     m = Metadata()
     t = Track("1")
     recording_to_metadata(self.json_doc, m, t)
     self.assertEqual(m['performer:EWI'], 'Michael Brecker')
Пример #24
0
    def _finalize_loading(self, error):
        if error:
            self.metadata.clear()
            self.status = _("[could not load album %s]") % self.id
            del self._new_metadata
            del self._new_tracks
            self.update()
            if not self._requests:
                self.loaded = True
                for func, always in self._after_load_callbacks:
                    if always:
                        func()
            return

        if self._requests > 0:
            return

        if not self._tracks_loaded:
            artists = set()
            all_media = []
            absolutetracknumber = 0

            va = self._new_metadata[
                'musicbrainz_albumartistid'] == VARIOUS_ARTISTS_ID

            djmix_ars = {}
            if hasattr(self._new_metadata, "_djmix_ars"):
                djmix_ars = self._new_metadata._djmix_ars

            for medium_node in self._release_node['media']:
                mm = Metadata()
                mm.copy(self._new_metadata)
                medium_to_metadata(medium_node, mm)
                format = medium_node.get('format')
                if format:
                    all_media.append(format)

                for dj in djmix_ars.get(mm["discnumber"], []):
                    mm.add("djmixer", dj)

                if va:
                    mm["compilation"] = "1"
                else:
                    del mm["compilation"]

                if 'discs' in medium_node:
                    discids = [disc.get('id') for disc in medium_node['discs']]
                    mm['~musicbrainz_discids'] = discids
                    mm['musicbrainz_discid'] = list(
                        self._discids.intersection(discids))

                if "pregap" in medium_node:
                    absolutetracknumber += 1
                    mm['~discpregap'] = '1'
                    extra_metadata = {
                        '~pregap': '1',
                        '~absolutetracknumber': absolutetracknumber,
                    }
                    self._finalize_loading_track(medium_node['pregap'], mm,
                                                 artists, extra_metadata)

                track_count = medium_node['track-count']
                if track_count:
                    tracklist_node = medium_node['tracks']
                    for track_node in tracklist_node:
                        absolutetracknumber += 1
                        extra_metadata = {
                            '~absolutetracknumber': absolutetracknumber,
                        }
                        self._finalize_loading_track(track_node, mm, artists,
                                                     extra_metadata)

                if "data-tracks" in medium_node:
                    for track_node in medium_node['data-tracks']:
                        absolutetracknumber += 1
                        extra_metadata = {
                            '~datatrack': '1',
                            '~absolutetracknumber': absolutetracknumber,
                        }
                        self._finalize_loading_track(track_node, mm, artists,
                                                     extra_metadata)

            totalalbumtracks = absolutetracknumber
            self._new_metadata['~totalalbumtracks'] = totalalbumtracks
            # Generate a list of unique media, but keep order of first appearance
            self._new_metadata['media'] = " / ".join(
                list(OrderedDict.fromkeys(all_media)))

            for track in self._new_tracks:
                track.metadata["~totalalbumtracks"] = totalalbumtracks
                if len(artists) > 1:
                    track.metadata["~multiartist"] = "1"
            del self._release_node
            del self._release_artist_nodes
            self._tracks_loaded = True

        if not self._requests:
            self.enable_update_metadata_images(False)
            for track in self._new_tracks:
                track.orig_metadata.copy(track.metadata)
                track.metadata_images_changed.connect(
                    self.update_metadata_images)

            # Prepare parser for user's script
            for s_name, s_text in enabled_tagger_scripts_texts():
                parser = ScriptParser()
                for track in self._new_tracks:
                    # Run tagger script for each track
                    try:
                        parser.eval(s_text, track.metadata)
                    except ScriptError:
                        log.exception(
                            "Failed to run tagger script %s on track", s_name)
                    track.metadata.strip_whitespace()
                    track.scripted_metadata.update(track.metadata)
                # Run tagger script for the album itself
                try:
                    parser.eval(s_text, self._new_metadata)
                except ScriptError:
                    log.exception("Failed to run tagger script %s on album",
                                  s_name)
                self._new_metadata.strip_whitespace()

            unmatched_files = [
                file for track in self.tracks for file in track.files
            ]
            self.metadata = self._new_metadata
            self.orig_metadata.copy(self.metadata)
            self.orig_metadata.images.clear()
            self.tracks = self._new_tracks
            del self._new_metadata
            del self._new_tracks
            self.loaded = True
            self.status = None
            self.match_files(unmatched_files + self.unmatched_files.files)
            self.enable_update_metadata_images(True)
            self.update()
            self.tagger.window.set_statusbar_message(
                N_('Album %(id)s loaded: %(artist)s - %(album)s'), {
                    'id': self.id,
                    'artist': self.metadata['albumartist'],
                    'album': self.metadata['album']
                },
                timeout=3000)
            for func, always in self._after_load_callbacks:
                func()
            self._after_load_callbacks = []
            if self.item.isSelected():
                self.tagger.window.refresh_metadatabox()
Пример #25
0
 def test_track(self):
     m = Metadata()
     medium_to_metadata(self.json_doc, m)
     self.assertEqual(m, {})
Пример #26
0
 def test_compare_lengths(self):
     m1 = Metadata()
     m1.length = 360
     m2 = Metadata()
     m2.length = 300
     self.assertAlmostEqual(m1.compare(m2), 0.998)
Пример #27
0
 def test_release_group(self):
     m = Metadata()
     r = ReleaseGroup("1")
     release_group_to_metadata(self.json_doc, m, r)
     self.assertEqual(m, {})
Пример #28
0
 def test_compare_tracknumber_difference(self):
     m1 = Metadata()
     m1["tracknumber"] = "1"
     m2 = Metadata()
     m2["tracknumber"] = "2"
     self.assertEqual(m1.compare(m2), 0)
Пример #29
0
 def test_lyrcis_with_description(self):
     metadata = Metadata({'lyrics:foo': 'bar'})
     loaded_metadata = save_and_load_metadata(self.filename, metadata)
     self.assertEqual(metadata['lyrics:foo'], loaded_metadata['lyrics'])
Пример #30
0
 def test_cmd_unset_prefix(self):
     context = Metadata()
     context['title'] = u'Foo'
     context['~rating'] = u'4'
     self.parser.eval("$unset(_rating)", context)
     self.assertNotIn('~rating', context)