def save_frame(frame): #Copied from mutagen.id3.ID3 flags = 0 framedata = frame._writeData() datasize = BitPaddedInt.to_str(len(framedata), width=4) header = pack('>4s4sH', type(frame).__name__, datasize, flags) return header + framedata
def test_long(self): if PY2: data = BitPaddedInt.to_str(sys.maxint + 1, width=16) val = BitPaddedInt(data) self.assertEqual(val, sys.maxint + 1) self.assertTrue(isinstance(val, BitPaddedLong)) else: self.assertTrue(BitPaddedInt is BitPaddedLong)
def __save_frame(self, frame, v2): flags = 0 if self.PEDANTIC and isinstance(frame, TextFrame): if len(str(frame)) == 0: return '' framedata = frame._writeData() if v2 == 3: bits=8 else: bits=7 datasize = BitPaddedInt.to_str(len(framedata), width=4, bits=bits) header = pack('>4s4sH', type(frame).__name__, datasize, flags) return header + framedata
def test_s65(self): self.assertEquals(BitPaddedInt.to_str(0x41, 6), b'\x00\x00\x01\x01')
def test_s129(self): self.assertEquals(BitPaddedInt.to_str(129), b'\x00\x00\x01\x01')
def test_s1l(self): self.assertEquals( BitPaddedInt.to_str(1, bigendian=False), b'\x01\x00\x00\x00')
def test_s0(self): self.assertEquals(BitPaddedInt.to_str(0), b'\x00\x00\x00\x00')
def save(self, filename=None, v1=1, v2=4): """Save changes to a file. If no filename is given, the one most recently loaded is used. Keyword arguments: v1 -- if 0, ID3v1 tags will be removed if 1, ID3v1 tags will be updated but not added if 2, ID3v1 tags will be created and/or updated v2 -- version of ID3v2 tags (3 or 4). By default Mutagen saves ID3v2.4 tags. If you want to save ID3v2.3 tags, you must call method update_to_v23 before saving the file. The lack of a way to update only an ID3v1 tag is intentional. """ # Sort frames by 'importance' order = ["TIT2", "TPE1", "TRCK", "TALB", "TPOS", "TDRC", "TCON"] order = dict(zip(order, range(len(order)))) last = len(order) frames = self.items() frames.sort(lambda a, b: cmp(order.get(a[0][:4], last), order.get(b[0][:4], last))) framedata = [self.__save_frame(frame, v2) for (key, frame) in frames] framedata.extend([data for data in self.unknown_frames if len(data) > 10]) if not framedata: try: self.delete(filename) except EnvironmentError as err: from errno import ENOENT if err.errno != ENOENT: raise return framedata = ''.join(framedata) framesize = len(framedata) if filename is None: filename = self.filename try: f = open(filename, 'rb+') except IOError as err: from errno import ENOENT if err.errno != ENOENT: raise f = open(filename, 'ab') # create, then reopen f = open(filename, 'rb+') try: idata = f.read(10) try: id3, vmaj, vrev, flags, insize = unpack('>3sBBB4s', idata) except struct.error: id3, insize = '', 0 insize = BitPaddedInt(insize) if id3 != 'ID3': insize = -10 if insize >= framesize: outsize = insize else: outsize = (framesize + 1023) & ~0x3FF framedata += '\x00' * (outsize - framesize) framesize = BitPaddedInt.to_str(outsize, width=4) flags = 0 header = pack('>3sBBB4s', 'ID3', v2, 0, flags, framesize) data = header + framedata if (insize < outsize): insert_bytes(f, outsize - insize, insize + 10) f.seek(0) f.write(data) try: f.seek(-128, 2) except IOError as err: from errno import EINVAL if err.errno != EINVAL: raise f.seek(0, 2) # ensure read won't get "TAG" if f.read(3) == "TAG": f.seek(-128, 2) if v1 > 0: f.write(MakeID3v1(self)) else: f.truncate() elif v1 == 2: f.seek(0, 2) f.write(MakeID3v1(self)) finally: f.close()
def test_varwidth(self): self.assertEquals(len(BitPaddedInt.to_str(100)), 4) self.assertEquals(len(BitPaddedInt.to_str(100, width=-1)), 4) self.assertEquals(len(BitPaddedInt.to_str(2 ** 32, width=-1)), 5)
def save(self, filename=None, v1=0): """Save changes to a file. If no filename is given, the one most recently loaded is used. Keyword arguments: v1 -- if 0, ID3v1 tags will be removed if 1, ID3v1 tags will be updated but not added if 2, ID3v1 tags will be created and/or updated The lack of a way to update only an ID3v1 tag is intentional. """ # Sort frames by 'importance' order = ["TIT2", "TPE1", "TRCK", "TALB", "TPOS", "TDRC", "TCON"] order = dict(zip(order, range(len(order)))) last = len(order) frames = self.items() frames.sort(lambda a, b: cmp(order.get(a[0][:4], last), order.get(b[0][:4], last))) framedata = [self.__save_frame(frame) for (key, frame) in frames] framedata.extend([data for data in self.unknown_frames if len(data) > 10]) framedata = "".join(framedata) framesize = len(framedata) if filename is None: filename = self.filename f = open(filename, "rb+") try: idata = f.read(10) try: id3, vmaj, vrev, flags, insize = struct.unpack(">3sBBB4s", idata) except struct.error: id3, insize = "", 0 insize = BitPaddedInt(insize) if id3 != "ID3": insize = -10 if insize >= framesize: outsize = insize else: outsize = (framesize + 1023) & ~0x3FF framedata += "\x00" * (outsize - framesize) framesize = BitPaddedInt.to_str(outsize, width=4) flags = 0 header = struct.pack(">3sBBB4s", "ID3", 4, 0, flags, framesize) data = header + framedata if insize < outsize: insert_bytes(f, outsize - insize, insize + 10) f.seek(0) try: f.seek(-128, 2) except IOError, err: if err.errno != EINVAL: raise f.seek(0, 2) # ensure read won't get "TAG" if f.read(3) == "TAG": f.seek(-128, 2) if v1 > 0: f.write(MakeID3v1(self)) else: f.truncate() elif v1 == 2: f.seek(0, 2) f.write(MakeID3v1(self))
def test_s1(self): self.assertEquals(BitPaddedInt.to_str(1), "\x00\x00\x00\x01")
idata = f.read(10) try: id3, vmaj, vrev, flags, insize = unpack('>3sBBB4s', idata) except struct.error: id3, insize = '', 0 insize = BitPaddedInt(insize) if id3 != 'ID3': insize = -10 if insize >= framesize: outsize = insize else: outsize = (framesize + 1023) & ~0x3FF framedata += '\x00' * (outsize - framesize) framesize = BitPaddedInt.to_str(outsize, width=4) flags = 0 header = pack('>3sBBB4s', 'ID3', v2, 0, flags, framesize) data = header + framedata if (insize < outsize): insert_bytes(f, outsize-insize, insize+10) f.seek(0) f.write(data) try: f.seek(-128, 2) except IOError, err: from errno import EINVAL if err.errno != EINVAL: raise
def save(self, filename=None, v1=1, v2_version=4): """Save changes to a file. If no filename is given, the one most recently loaded is used. Keyword arguments: v1 -- if 0, ID3v1 tags will be removed if 1, ID3v1 tags will be updated but not added if 2, ID3v1 tags will be created and/or updated v2_version -- version of ID3v2 tags (3 or 4). By default Mutagen saves ID3v2.4 tags. If you want to save ID3v2.3 tags, you must call method update_to_v23 before saving the file. The lack of a way to update only an ID3v1 tag is intentional. """ # Sort frames by 'importance' order = ["TIT2", "TPE1", "TRCK", "TALB", "TPOS", "TDRC", "TCON"] order = dict(zip(order, range(len(order)))) last = len(order) frames = self.items() frames.sort(lambda a, b: cmp(order.get(a[0][:4], last), order.get(b[0][:4], last))) framedata = [ self.__save_frame(frame, v2_version) for (key, frame) in frames ] framedata.extend( [data for data in self.unknown_frames if len(data) > 10]) if not framedata: try: self.delete(filename) except EnvironmentError as err: from errno import ENOENT if err.errno != ENOENT: raise return framedata = ''.join(framedata) framesize = len(framedata) if filename is None: filename = self.filename try: f = open(filename, 'rb+') except IOError as err: from errno import ENOENT if err.errno != ENOENT: raise f = open(filename, 'ab') # create, then reopen f = open(filename, 'rb+') try: idata = f.read(10) try: id3, vmaj, vrev, flags, insize = unpack('>3sBBB4s', idata) except struct.error: id3, insize = '', 0 insize = BitPaddedInt(insize) if id3 != 'ID3': insize = -10 if insize >= framesize: outsize = insize else: outsize = (framesize + 1023) & ~0x3FF framedata += '\x00' * (outsize - framesize) framesize = BitPaddedInt.to_str(outsize, width=4) flags = 0 header = pack('>3sBBB4s', 'ID3', v2_version, 0, flags, framesize) data = header + framedata if (insize < outsize): insert_bytes(f, outsize - insize, insize + 10) f.seek(0) f.write(data) try: f.seek(-128, 2) except IOError as err: from errno import EINVAL if err.errno != EINVAL: raise f.seek(0, 2) # ensure read won't get "TAG" if f.read(3) == "TAG": f.seek(-128, 2) if v1 > 0: f.write(MakeID3v1(self)) else: f.truncate() elif v1 == 2: f.seek(0, 2) f.write(MakeID3v1(self)) finally: f.close()
def test_w129(self): self.assertEquals(BitPaddedInt.to_str(129, width=2), b'\x01\x01')
def test_w129l(self): self.assertEquals( BitPaddedInt.to_str(129, width=2, bigendian=False), b'\x01\x01')
idata = f.read(10) try: id3, vmaj, vrev, flags, insize = unpack('>3sBBB4s', idata) except struct.error: id3, insize = '', 0 insize = BitPaddedInt(insize) if id3 != 'ID3': insize = -10 if insize >= framesize: outsize = insize else: outsize = (framesize + 1023) & ~0x3FF framedata += '\x00' * (outsize - framesize) framesize = BitPaddedInt.to_str(outsize, width=4) flags = 0 header = pack('>3sBBB4s', 'ID3', v2, 0, flags, framesize) data = header + framedata if (insize < outsize): insert_bytes(f, outsize - insize, insize + 10) f.seek(0) f.write(data) try: f.seek(-128, 2) except IOError, err: from errno import EINVAL if err.errno != EINVAL: raise
def test_minwidth(self): self.assertEquals( len(BitPaddedInt.to_str(100, width=-1, minwidth=6)), 6)
def save(self, filename=None, v1=0): """Save changes to a file. If no filename is given, the one most recently loaded is used. Keyword arguments: v1 -- if 0, ID3v1 tags will be removed if 1, ID3v1 tags will be updated but not added if 2, ID3v1 tags will be created and/or updated The lack of a way to update only an ID3v1 tag is intentional. """ # Sort frames by 'importance' order = ["TIT2", "TPE1", "TRCK", "TALB", "TPOS", "TDRC", "TCON"] order = dict(zip(order, range(len(order)))) last = len(order) frames = self.items() frames.sort(lambda a, b: cmp(order.get(a[0][:4], last), order.get(b[0][:4], last))) framedata = [self.__save_frame(frame) for (key, frame) in frames] framedata.extend([data for data in self.unknown_frames if len(data) > 10]) framedata = ''.join(framedata) framesize = len(framedata) if filename is None: filename = self.filename f = open(filename, 'rb+') try: idata = f.read(10) try: id3, vmaj, vrev, flags, insize = struct.unpack('>3sBBB4s', idata) except struct.error: id3, insize = '', 0 insize = BitPaddedInt(insize) if id3 != 'ID3': insize = -10 if insize >= framesize: outsize = insize else: outsize = (framesize + 1023) & ~0x3FF framedata += '\x00' * (outsize - framesize) framesize = BitPaddedInt.to_str(outsize, width=4) flags = 0 header = struct.pack('>3sBBB4s', 'ID3', 4, 0, flags, framesize) data = header + framedata if (insize < outsize): insert_bytes(f, outsize-insize, insize+10) f.seek(0) try: f.seek(-128, 2) except IOError, err: if err.errno != EINVAL: raise f.seek(0, 2) # ensure read won't get "TAG" if f.read(3) == "TAG": f.seek(-128, 2) if v1 > 0: f.write(MakeID3v1(self)) else: f.truncate() elif v1 == 2: f.seek(0, 2) f.write(MakeID3v1(self))