def test_is_archival(self): self.assertTrue(order.is_archival("3/7")) self.assertFalse(order.is_archival("bad")) self.assertFalse(order.is_archival("3")) self.assertFalse(order.is_archival("3 of 7")) self.assertFalse(order.is_archival("7/3")) self.assertFalse(order.is_archival(" 3/7"))
def find_tags_errors(au_file): """Return a list of errors found in a file's ID3 tags. Args: au_file: An AudioFile object. Returns: A list of human-readable strings describing errors or inconsistencies found in the AudioFile object's ID3 tags, or the empty list if no errors are found. """ errors = [] # Make sure all required tags are there. for tag in constants.ID3_TAG_REQUIRED: if tag not in au_file.mutagen_id3: errors.append(ERROR_TAG_MISSING_REQUIRED + tag) # Checks that are not really tag-specific. for tag in au_file.mutagen_id3.itervalues(): # Make sure all tags are on the whitelist. if (tag.FrameID not in constants.ID3_TAG_WHITELIST and tag.HashKey not in constants.ID3_TAG_WHITELIST): errors.append(ERROR_TAG_NOT_WHITELISTED + tag.FrameID) # Make sure all text tags have the correct encoding. if tag.FrameID.startswith("T"): encoding = getattr(tag, "encoding", "missing") if (encoding != "missing" and encoding != constants.DEFAULT_ID3_TEXT_ENCODING): errors.append(ERROR_TAG_WRONG_ENCODING + tag.FrameID) # Check that numeric tags are actually numeric. for frame_id in ("TBPM", "TLEN", "TORY", "TYER"): tag = au_file.mutagen_id3.get(frame_id) if tag and not (len(tag.text) == 1 and tag.text[0].isdigit()): errors.append(ERROR_NUMERIC_MALFORMED + frame_id) # Check that TFLT contains a whitelisted file type. this_tflt = au_file.mutagen_id3.get("TFLT") if (this_tflt and not (len(this_tflt.text) == 1 and this_tflt.text[0] in constants.TFLT_WHITELIST)): errors.append(ERROR_TFLT_NON_WHITELISTED) # Check that TLEN contains the correct length. this_tlen = au_file.mutagen_id3.get("TLEN") if (this_tlen and not (len(this_tlen.text) == 1 and str(au_file.duration_ms) == this_tlen.text[0])): errors.append(ERROR_TLEN_INCORRECT) # Check that the TXXX with the frame count is correct. this_fc = au_file.mutagen_id3.get(constants.TXXX_FRAME_COUNT_KEY) if (this_fc and not (len(this_fc.text) == 1 and str(au_file.frame_count) == this_fc.text[0])): errors.append(ERROR_TXXX_FRAME_COUNT_INCORRECT) # Check that the TXXX with the frame size is correct. this_fs = au_file.mutagen_id3.get(constants.TXXX_FRAME_SIZE_KEY) if (this_fs and not (len(this_fs.text) == 1 and str(au_file.frame_size) == this_fs.text[0])): errors.append(ERROR_TXXX_FRAME_SIZE_INCORRECT) # Check that TOWN contains the expected string. this_town = au_file.mutagen_id3.get("TOWN") if (this_town and not (len(this_town.text) == 1 and this_town.text[0] == constants.TOWN_FILE_OWNER)): errors.append(ERROR_TOWN_INCORRECT) # Check that the TPE tags contain known artists. for tag in au_file.mutagen_id3.itervalues(): if tag.FrameID.startswith("TPE"): for txt in tag.text: if not artists.is_standardized(txt): errors.append(ERROR_TPE_NONSTANDARD + txt) # Check that TRCK and TPOS contains a valid order-numbering in our # standard form. for this_tag in (au_file.mutagen_id3.get("TPOS"), au_file.mutagen_id3.get("TRCK")): if this_tag and not (len(this_tag.text) == 1 and order.is_archival(this_tag.text[0])): errors.append( "%s%s %s" % (ERROR_ORDER_MALFORMED, this_tag.FrameID, this_tag.text)) # Check the UFID. this_ufid = au_file.mutagen_id3.get(constants.MUTAGEN_UFID_KEY) if this_ufid: try: vol, ts, fp = ufid.parse(this_ufid.data) if au_file.volume != vol: errors.append(ERROR_UFID_BAD_VOLUME) if au_file.import_timestamp != ts: errors.append(ERROR_UFID_BAD_TIMESTAMP) if au_file.fingerprint != fp: errors.append(ERROR_UFID_BAD_FINGERPRINT) except ValueError, ex: errors.append(ERROR_UFID_BAD_MALFORMED)
def find_tags_errors(au_file): """Return a list of errors found in a file's ID3 tags. Args: au_file: An AudioFile object. Returns: A list of human-readable strings describing errors or inconsistencies found in the AudioFile object's ID3 tags, or the empty list if no errors are found. """ errors = [] # Make sure all required tags are there. for tag in constants.ID3_TAG_REQUIRED: if tag not in au_file.mutagen_id3: errors.append(ERROR_TAG_MISSING_REQUIRED + tag) # Checks that are not really tag-specific. for tag in au_file.mutagen_id3.itervalues(): # Make sure all tags are on the whitelist. if (tag.FrameID not in constants.ID3_TAG_WHITELIST and tag.HashKey not in constants.ID3_TAG_WHITELIST): errors.append(ERROR_TAG_NOT_WHITELISTED + tag.FrameID) # Make sure all text tags have the correct encoding. if tag.FrameID.startswith("T"): encoding = getattr(tag, "encoding", "missing") if (encoding != "missing" and encoding != constants.DEFAULT_ID3_TEXT_ENCODING): errors.append(ERROR_TAG_WRONG_ENCODING + tag.FrameID) # Check that numeric tags are actually numeric. for frame_id in ("TBPM", "TLEN", "TORY", "TYER"): tag = au_file.mutagen_id3.get(frame_id) if tag and not (len(tag.text) == 1 and tag.text[0].isdigit()): errors.append(ERROR_NUMERIC_MALFORMED + frame_id) # Check that TFLT contains a whitelisted file type. this_tflt = au_file.mutagen_id3.get("TFLT") if (this_tflt and not (len(this_tflt.text) == 1 and this_tflt.text[0] in constants.TFLT_WHITELIST)): errors.append(ERROR_TFLT_NON_WHITELISTED) # Check that TLEN contains the correct length. this_tlen = au_file.mutagen_id3.get("TLEN") if (this_tlen and not (len(this_tlen.text) == 1 and str(au_file.duration_ms) == this_tlen.text[0])): errors.append(ERROR_TLEN_INCORRECT) # Check that the TXXX with the frame count is correct. this_fc = au_file.mutagen_id3.get(constants.TXXX_FRAME_COUNT_KEY) if (this_fc and not (len(this_fc.text) == 1 and str(au_file.frame_count) == this_fc.text[0])): errors.append(ERROR_TXXX_FRAME_COUNT_INCORRECT) # Check that the TXXX with the frame size is correct. this_fs = au_file.mutagen_id3.get(constants.TXXX_FRAME_SIZE_KEY) if (this_fs and not (len(this_fs.text) == 1 and str(au_file.frame_size) == this_fs.text[0])): errors.append(ERROR_TXXX_FRAME_SIZE_INCORRECT) # Check that TOWN contains the expected string. this_town = au_file.mutagen_id3.get("TOWN") if (this_town and not (len(this_town.text) == 1 and this_town.text[0] == constants.TOWN_FILE_OWNER)): errors.append(ERROR_TOWN_INCORRECT) # Check that the TPE tags contain known artists. for tag in au_file.mutagen_id3.itervalues(): if tag.FrameID.startswith("TPE"): for txt in tag.text: if not artists.is_standardized(txt): errors.append(ERROR_TPE_NONSTANDARD + txt) # Check that TRCK and TPOS contains a valid order-numbering in our # standard form. for this_tag in (au_file.mutagen_id3.get("TPOS"), au_file.mutagen_id3.get("TRCK")): if this_tag and not (len(this_tag.text) == 1 and order.is_archival(this_tag.text[0])): errors.append("%s%s %s" % (ERROR_ORDER_MALFORMED, this_tag.FrameID, this_tag.text)) # Check the UFID. this_ufid = au_file.mutagen_id3.get(constants.MUTAGEN_UFID_KEY) if this_ufid: try: vol, ts, fp = ufid.parse(this_ufid.data) if au_file.volume != vol: errors.append(ERROR_UFID_BAD_VOLUME) if au_file.import_timestamp != ts: errors.append(ERROR_UFID_BAD_TIMESTAMP) if au_file.fingerprint != fp: errors.append(ERROR_UFID_BAD_FINGERPRINT) except ValueError, ex: errors.append(ERROR_UFID_BAD_MALFORMED)