def test_ASFUnicodeAttribute(self): if PY3: self.assertRaises(TypeError, ASFUnicodeAttribute, b"\xff") else: self.assertRaises(ValueError, ASFUnicodeAttribute, b"\xff") val = u'\xf6\xe4\xfc' self.assertEqual(ASFUnicodeAttribute(val.encode("utf-8")), val) self.assertRaises(ASFError, ASFUnicodeAttribute, data=b"\x00") self.assertEqual(ASFUnicodeAttribute(u"foo").value, u"foo")
def load_tag(self): """(re)Writes the tag data to the GUI.""" tag = self.tag for each in self.primary_line: try: data = tag[each[0]] except KeyError: pass else: each[1].set_text("/".join(unicode(y) for y in data)) additional = [] for key in self.secondaries: values = tag.get(key, [ASFUnicodeAttribute("")]) for val in values: additional.append( key.encode("utf-8") + "=" + unicode(val).encode("utf-8")) for key in self.text_set: if key not in self.primary_data and key not in self.secondaries: values = tag[key] for val in values: additional.append( key.encode("utf-8") + "=" + unicode(val).encode("utf-8")) self.tag_frame.tb.set_text("\n".join(additional))
def test_ASFUnicodeAttribute_dunder(self): attr = ASFUnicodeAttribute(u"foo") self.assertEqual(bytes(attr), b"f\x00o\x00o\x00") self.assertEqual(str(attr), u"foo") self.assertEqual(repr(attr), "ASFUnicodeAttribute('foo')") self.assertRaises(TypeError, int, attr)
def save_tag(self): """Updates the tag with the GUI data.""" tag = self.tag tb = self.tag_frame.tb for key in self.text_set: try: del tag[key] except KeyError: pass for each in self.primary_line: val = each[1].get_text().strip() if val: tag[each[0]] = val else: try: del tag[each[0]] except KeyError: pass lines = tb.get_text(tb.get_start_iter(), tb.get_end_iter()).splitlines() for line in lines: try: key, val = line.split("=", 1) except ValueError: continue else: key = key.strip() val = val.strip() if val: try: tag[key] += [ASFUnicodeAttribute(val.decode("utf-8"))] except (KeyError, AttributeError): try: tag[key] = [ ASFUnicodeAttribute(val.decode("utf-8")) ] except KeyError: print("Unacceptable key", key) tag.save()
def test_ASFUnicodeAttribute(self): self.assertRaises(TypeError, ASFUnicodeAttribute, b"\xff") self.assertRaises(ASFError, ASFUnicodeAttribute, data=b"\x00") self.assertEqual(ASFUnicodeAttribute(u"foo").value, u"foo") assert ASFUnicodeAttribute(data=b"") == u""
def producer(self, producer: str): self.file['WM/Producer'] = ASFUnicodeAttribute(value=producer) return self
def composer(self, composer: str): self.file['WM/Composer'] = ASFUnicodeAttribute(value=composer) return self
def subtitle(self, subtitle: str): self.file['WM/SubTitle'] = ASFUnicodeAttribute(value=subtitle) return self
def genre(self, genre: str): self.file['WM/Genre'] = ASFUnicodeAttribute(value=genre) return self
def track_number(self, track_number: str): self.file['WM/TrackNumber'] = ASFUnicodeAttribute(value=track_number) return self
def year(self, year: str): self.file['WM/Year'] = ASFUnicodeAttribute(value=year) return self
def album(self, album: str): self.file['WM/AlbumTitle'] = ASFUnicodeAttribute(value=album) return self
def album_artist(self, artist: str): self.file['WM/AlbumArtist'] = ASFUnicodeAttribute(value=artist) return self
def artist(self, artist: str): self.file['Author'] = ASFUnicodeAttribute(value=artist) return self
def comments(self, comments: str): self.file['Description'] = ASFUnicodeAttribute(value=comments) return self
def save_lyrics(self): """ Called by self.download_lyrics to save lyrics according to Config.save_to_file, Config.save_to_tag settings. Handles the case if lyrics is not found. Logs errors to console and Song object. """ if not self.lyrics: print('Failed:', self.error) return if self.lyrics and Config.save_to_file: try: with open(self.lyrics_file_path, 'w', encoding='utf-8') as f: f.write('Artist - ' + self.artist + '\n') f.write('Title - ' + self.title + '\n') album_str = 'Album - Unkown' if self.album: album_str = 'Album - ' + self.album f.write(album_str) f.write('\n\n') f.write(self.lyrics) # update class variable Song.lyrics_saved_to_file_count += 1 # update the Song instance flag self.saved_to_file = True print('Success: Lyrics saved to file.') except IOError as e: err_str = str(e) if e.errno == 22: err_str = 'Cannot save lyrics to file. Unable to create file with song metadata.' if e.errno == 13: err_str = 'Cannot save lyrics to file. The file is opened or in use.' if e.errno == 2: err_str = '"lyrics_dir" does not exist. Please set a "lyric_dir" which exists.' self.error = err_str print('Failed:', err_str) if self.lyrics and Config.save_to_tag: lyrics_key = FORMAT_KEYS[self.format]['lyrics'] try: if self.format == 'mp3': # encoding = 3 for UTF-8 self.tag.add(USLT(encoding=3, lang = u'eng', desc = u'lyrics.wikia', text=self.lyrics)) if self.format == 'm4a' or self.format == 'mp4': # lyrics_key = '\xa9lyr' if sys.version_info[0] < 3: lyrics_key = lyrics_key.encode('latin-1') self.tag[lyrics_key] = self.lyrics # Both flac and ogg/oga(Vorbis & FLAC), are being read/write as Vorbis Comments. # Vorbis Comments don't have a standard 'lyrics' tag. The 'LYRICS' tag is # most common non-standard tag used for lyrics. if self.format == 'flac' or self.format == 'ogg' or self.format == 'oga': self.tag[lyrics_key] = self.lyrics if self.format == 'wma': # ASF Format uses ASFUnicodeAttribute objects instead of Python's Unicode self.tag[lyrics_key] = ASFUnicodeAttribute(self.lyrics) self.tag.save() self.saved_to_tag = True Song.lyrics_saved_to_tag_count += 1 print('Success: Lyrics saved to tag.') except MutagenError: err_str = 'Cannot save lyrics to tag. Codec/Format not supported' self.error = err_str print('Failed:', err_str) except IOError as e: err_str = 'Cannot save lyrics to tag. The file is opened or in use.' self.error = err_str print('Failed:', err_str)
def disc_number(self, disc: str): self.file['WM/PartOfSet'] = ASFUnicodeAttribute(value=disc) return self
def title(self, title: str): self.file['Title'] = ASFUnicodeAttribute(value=title) return self