Пример #1
0
 def test_make_v1_from_tyer(self):
     self.assertEquals(
         MakeID3v1({"TDRC": TDRC(text="2010-10-10")}),
         MakeID3v1({"TYER": TYER(text="2010")}))
     self.assertEquals(
         ParseID3v1(MakeID3v1({"TDRC": TDRC(text="2010-10-10")})),
         ParseID3v1(MakeID3v1({"TYER": TYER(text="2010")})))
Пример #2
0
 def test_v1_not_v11(self):
     self.id3["TRCK"] = TRCK(encoding=0, text="32")
     tag = MakeID3v1(self.id3)
     self.failUnless(32, ParseID3v1(tag)["TRCK"])
     del (self.id3["TRCK"])
     tag = MakeID3v1(self.id3)
     tag = tag[:125] + b'  ' + tag[-1:]
     self.failIf("TRCK" in ParseID3v1(tag))
Пример #3
0
    def test_load_v1_v2_tcon_translate(self):
        tags = ID3()
        tags.add(TCON(text=["12"]))
        v1_data = MakeID3v1(tags)

        filename = get_temp_copy(self.empty)
        try:
            tags = ID3()
            tags.save(filename=filename, v1=0)
            with open(filename, "ab") as h:
                h.write(v1_data)
            tags = ID3(filename, load_v1=True)
            assert tags["TCON"][0] == "Other"
            tags = ID3(filename, load_v1=False)
            assert "TCON" not in tags
        finally:
            os.unlink(filename)
Пример #4
0
                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
                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 __save_frame(self, frame, v2):
        flags = 0
        if self.PEDANTIC and isinstance(frame, TextFrame):
            if len(str(frame)) == 0:
                return ''
        framedata = frame._writeData()
Пример #5
0
 def test_v1_genre(self):
     tag = {}
     tag["TCON"] = TCON(encoding=0, text="Pop")
     v1tag = MakeID3v1(tag)
     self.failUnlessEqual(ParseID3v1(v1tag)["TCON"].genres, ["Pop"])
Пример #6
0
 def test_invalid_track(self):
     tag = {}
     tag["TRCK"] = TRCK(encoding=0, text="not a number")
     v1tag = MakeID3v1(tag)
     self.failIf("TRCK" in ParseID3v1(v1tag))
Пример #7
0
 def test_make_from_empty(self):
     empty = b'TAG' + b'\x00' * 124 + b'\xff'
     self.assertEquals(MakeID3v1({}), empty)
     self.assertEquals(MakeID3v1({'TCON': TCON()}), empty)
     self.assertEquals(MakeID3v1({'COMM': COMM(encoding=0, text="")}),
                       empty)
Пример #8
0
 def test_roundtrip(self):
     frames = {}
     for key in ["TIT2", "TALB", "TPE1", "TDRC"]:
         frames[key] = self.id3[key]
     self.assertEquals(ParseID3v1(MakeID3v1(frames)), frames)
Пример #9
0
 def test_long(self):
     s = MakeID3v1(dict(TDRC="123456789"))
     self.failUnlessEqual(len(s), 128)
     tag = ParseID3v1(s)
     self.failUnlessEqual(tag["TDRC"], "1234")
Пример #10
0
 def test_short(self):
     s = MakeID3v1(dict(TDRC="1"))
     self.failUnlessEqual(len(s), 128)
     tag = ParseID3v1(s)
     self.failUnlessEqual(tag["TDRC"], "0001")
Пример #11
0
 def test_empty(self):
     s = MakeID3v1(dict(TDRC=""))
     self.failUnlessEqual(len(s), 128)
     tag = ParseID3v1(s)
     self.failIf("TDRC" in tag)
Пример #12
0
 def test_none(self):
     s = MakeID3v1(dict())
     self.failUnlessEqual(len(s), 128)
     tag = ParseID3v1(s)
     self.failIf("TDRC" in tag)
Пример #13
0
            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
                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 __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
Пример #14
0
    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()
Пример #15
0
    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))