def test_pathlib_compatibility(): try: import pathlib except ImportError: return testfile = next(iter(testfiles.keys())) filename = pathlib.Path(testfolder) / testfile TinyTag.get(filename)
def test_binary_path_compatibility(): binary_file_path = os.path.join( os.path.dirname(__file__).encode('utf-8'), b'\x01.mp3') testfile = os.path.join(testfolder, next(iter(testfiles.keys()))) shutil.copy(testfile, binary_file_path) assert os.path.exists(binary_file_path) TinyTag.get(binary_file_path) os.unlink(binary_file_path) assert not os.path.exists(binary_file_path)
def test_mp3_utf_8_invalid_string_can_be_ignored(): tag = TinyTag.get(os.path.join(testfolder, 'samples/utf-8-id3v2-invalid-string.mp3'), ignore_errors=True) # the title used to be Gran dia, but I replaced the first byte with 0xFF, # which should be ignored here assert tag.title == 'ran día'
def test_file_reading(testfile, expected): filename = os.path.join(testfolder, testfile) tag = TinyTag.get(filename) for key, expected_val in expected.items(): if key.startswith('__'): continue result = getattr(tag, key) fmt_string = 'field "%s": got %s (%s) expected %s (%s)!' fmt_values = (key, repr(result), type(result), repr(expected_val), type(expected_val)) if key == 'duration' and result is not None and expected_val is not None: # allow duration to be off by 100 ms and a maximum of 1% if abs(result - expected_val) < 0.100: if expected_val and min(result, expected_val) / max( result, expected_val) > 0.99: continue assert result == expected_val, fmt_string % fmt_values # for custom samples, allow not specifying all values if expected.get('_do_not_require_all_values'): return undefined_in_fixture = {} for key, val in tag.__dict__.items(): if key.startswith('_') or val is None: continue if key not in expected: undefined_in_fixture[key] = val assert not undefined_in_fixture, 'Missing data in fixture \n%s' % str( undefined_in_fixture)
def drive_index(folder: Path): for item in folder.rglob('*'): if item.is_file(): try: track = TinyTag.get(item) yield get_track_metadata(item, track) except TinyTagException: pass
def test_mp3_image_loading2(): tag = TinyTag.get(os.path.join(testfolder, 'samples/12oz.mp3'), image=True) image_data = tag.get_image() assert image_data is not None assert 2000 < len(image_data) < 2500, ( 'Image is %d bytes but should be around 145kb' % len(image_data)) assert image_data.startswith(b'\xff\xd8\xff\xe0'), ( 'The image data must start with a jpeg ' 'header')
def test_flac_image_loading(): tag = TinyTag.get(os.path.join(testfolder, 'samples/flac_with_image.flac'), image=True) image_data = tag.get_image() assert image_data is not None assert 70000 < len(image_data) < 80000, ( 'Image is %d bytes but should be around 75kb' % len(image_data)) assert image_data.startswith(b'\xff\xd8\xff\xe0'), ( 'The image data must start with a jpeg ' 'header')
def test_mp3_image_loading_with_utf8_description(): tag = TinyTag.get(os.path.join(testfolder, 'samples/image-text-encoding.mp3'), image=True) image_data = tag.get_image() assert image_data is not None assert 5700 < len(image_data) < 6000, ( 'Image is %d bytes but should be around 6kb' % len(image_data)) assert image_data.startswith(b'\xff\xd8\xff\xe0'), ( 'The image data must start with a jpeg ' 'header')
def test_to_str(): tag = TinyTag.get(os.path.join(testfolder, 'samples/id3v22-test.mp3')) assert str(tag) # since the dict is not ordered we cannot == 'somestring' assert repr(tag) # since the dict is not ordered we cannot == 'somestring' assert str(tag) == ( '{"album": "Hymns for the Exiled", "albumartist": null, "artist": "Anais Mitchell", ' '"audio_offset": 2225, "bitrate": 160.0, "channels": 2, "comment": "Waterbug Records, ' 'www.anaismitchell.com", "composer": null, "disc": null, "disc_total": null, ' '"duration": 0.13836297152858082, "extra": {}, "filesize": 5120, "genre": null, ' '"samplerate": 44100, "title": "cosmic american", "track": "3", "track_total": "11", ' '"year": "2004"}')
def extract_music(self): """ Create a tuple that contains the songs' filename and their info :param str music_folder: path of the directory where the music is :return resp: The response from cmus from the issued command :rtype: tuple """ def song_fullpath(music_folder,filename): """ Extracts the fullpath of a song """ return ('{}{}'.format(music_folder,filename)) songs = [] try: generator = (f for f in os.listdir(self.music_folder) if os.path.isfile(os.path.join(self.music_folder, f))) except (FileNotFoundError, Exception) as err: print('Impossible to obtain the songs: {}'.format(err)) else: for song in generator: path = song_fullpath(self.music_folder, song) try: new_song = TinyTag.get(path, image=True) except Exception: try: print('ok') new_song = TinyTag.get(path) except Exception as e: print('File {} has not a valid format for a song: {}'.format(path, e)) new_song = None finally: if new_song and (new_song.bitrate and new_song.samplerate and new_song.duration): # Avoid no-song files to be added if (new_song.title is None) or (new_song.title == ''): new_song.title = song songs.append((path, new_song)) return tuple(songs)
def test_mp3_utf_8_invalid_string_raises_exception(): with raises(TinyTagException): TinyTag.get( os.path.join(testfolder, 'samples/utf-8-id3v2-invalid-string.mp3'))
def test_unpad(): # make sure that unpad only removes trailing 0-bytes assert TinyTag._unpad('foo\x00') == 'foo' assert TinyTag._unpad('foo\x00bar\x00') == 'foobar'
def test_show_hint_for_wrong_usage(): with pytest.raises(Exception) as exc_info: TinyTag('filename.mp3', 0) assert exc_info.type == Exception assert exc_info.value.args[ 0] == 'Use `TinyTag.get(filepath)` instead of `TinyTag(filepath)`'
def test_unsubclassed_tinytag_duration(): tag = TinyTag(None, 0) tag._determine_duration(None)
def test_override_encoding(): chinese_id3 = os.path.join(testfolder, 'samples/chinese_id3.mp3') tag = TinyTag.get(chinese_id3, encoding='gbk') assert tag.artist == '苏云' assert tag.album == '角落之歌'
def test_unsupported_extension(): bogus_file = os.path.join(testfolder, 'samples/there_is_no_such_ext.bogus') TinyTag.get(bogus_file)
def test_detect_magic_headers(testfile, expected): filename = os.path.join(testfolder, testfile) with io.open(filename, 'rb') as fh: parser = TinyTag.get_parser_class(filename, fh) assert parser == expected
def test_unsubclassed_tinytag_parse_tag(): tag = TinyTag(None, 0) tag._parse_tag(None)
def test_mp3_length_estimation(): ID3.set_estimation_precision(0.7) tag = TinyTag.get(os.path.join(testfolder, 'samples/silence-44-s-v1.mp3')) assert 3.5 < tag.duration < 4.0
formatting = (pop_param('--format', None) or pop_param('-f', None)) or 'json' skip_unsupported = pop_switch('--skip-unsupported', False) or pop_switch('-s', False) filenames = sys.argv[1:] except Exception as exc: print(exc) usage() sys.exit(1) header_printed = False for i, filename in enumerate(filenames): try: if skip_unsupported: if os.path.isdir(filename): continue if not TinyTag.is_supported(filename): continue tag = TinyTag.get(filename, image=save_image_path is not None) if save_image_path: # allow for saving the image of multiple files actual_save_image_path = save_image_path if len(filenames) > 1: actual_save_image_path, ext = splitext(actual_save_image_path) actual_save_image_path += '%05d' % i + ext image = tag.get_image() if image: with open(actual_save_image_path, 'wb') as fh: fh.write(image) data = {'filename': filename} data.update(tag.as_dict()) if formatting == 'json':