async def bests(ctx, path, prefix, suffix, **kwargs): '''Generate bests playlists with some rules''' ctx.obj.mf = filter.Filter(**kwargs) if len(prefix): ctx.obj.mf.relative = True playlists = await ctx.obj.db.bests(ctx.obj.mf) with tqdm(total=len(playlists), file=sys.stdout, desc="Bests playlists", disable=config.quiet) as bar: for p in playlists: playlist_filepath = os.path.join(path, p['name'] + suffix + '.m3u') content = indent(p['content'], prefix, lambda line: line != '#EXTM3U') if not config.dry: try: with codecs.open(playlist_filepath, 'w', "utf-8-sig") as playlist_file: debug( 'Writing playlist to {} with content:\n{}'.format( playlist_filepath, content)) playlist_file.write(content) except: info('Unable to write playlist to: {}'.format( playlist_filepath)) else: info( 'DRY RUN: Writing playlist to {} with content:\n{}'.format( playlist_filepath, content)) bar.update(1)
async def errors(ctx, **kwargs): '''Detect errors''' ctx.obj.db = collection.collection(**kwargs) mf = filter.Filter(**kwargs) errors = await ctx.obj.db.errors(mf) for e in errors: print(e)
async def new(ctx, path, **kwargs): '''Generate a new playlist''' ctx.obj.mf = filter.Filter(**kwargs) p = await ctx.obj.db.playlist(ctx.obj.mf) if not config.dry: print(p['content'], file=path) else: info('DRY RUN: Writing playlist to {} with content:\n{}'.format( path, p['content']))
async def cli(ctx, **kwargs): '''Generate some stats for music collection with filters''' ctx.obj.db = collection.Collection(**kwargs) ctx.obj.mf = filter.Filter(**kwargs) stats = await ctx.obj.db.stats(ctx.obj.mf) print("Music :", stats['musics']) print("Artist :", stats['artists']) print("Album :", stats['albums']) print("Genre :", stats['genres']) print("Keywords :", stats['keywords']) print("Size :", bytesToHuman(stats['size'])) print("Total duration :", str(timedelta(seconds=stats['duration'])))
async def test_new_playlist(self): mf = filter.Filter(relative=True) playlist = await self.collection.playlist(mf) final = """#EXTM3U 1995/La Source/La Flemme.mp3 Buckethead/1994 - Giant Robot/01 - Doomride.flac Buckethead/1994 - Giant Robot/02 - Welcome To Bucketheadland - Cut.flac Buckethead/1994 - Giant Robot/02 - Welcome To Bucketheadland.flac Buckethead/1994 - Giant Robot/03 - I Come In Peace.flac""" self.maxDiff = None self.assertMultiLineEqual(playlist['content'], final) print('Output:', playlist['content']) print('Final:', final)
async def sync(ctx, destination, **kwargs): '''Copy selected musics with filters to destination folder''' info('Destination: {}'.format(destination)) ctx.obj.mf = filter.Filter(**kwargs) musics = await ctx.obj.db.musics(ctx.obj.mf) files = lib.all_files(destination) destinations = {f[len(destination) + 1:]: f for f in files} sources = {m['path'][len(m['folder']) + 1:]: m['path'] for m in musics} to_delete = set(destinations.keys()) - set(sources.keys()) to_copy = set(sources.keys()) - set(destinations.keys()) with tqdm(total=len(to_delete), file=sys.stdout, desc="Deleting music", leave=True, position=0, disable=config.quiet) as bar: for d in to_delete: if not config.dry: try: info("Deleting {}".format(destinations[d])) os.remove(destinations[d]) except Exception as e: error(e) else: info("[DRY-RUN] False Deleting {}".format(destinations[d])) bar.update(1) with tqdm(total=len(to_copy), file=sys.stdout, desc="Copying music", leave=True, position=0, disable=config.quiet) as bar: from shutil import copyfile for c in sorted(to_copy): final_destination = os.path.join(destination, c) if not config.dry: info("Copying {} to {}".format(sources[c], final_destination)) os.makedirs(os.path.dirname(final_destination), exist_ok=True) copyfile(sources[c], final_destination) else: info("[DRY-RUN] False Copying {} to {}".format( sources[c], final_destination)) bar.update(1) import shutil for d in empty_dirs(destination): if not config.dry: shutil.rmtree(d) info("[DRY-RUN] Removing empty dir {}".format(d))
async def test_tag_filter(self): musics = await self.collection.musics( filter.Filter(genres=['Avantgarde'])) self.assertEqual(len(musics), 4) musics = await self.collection.musics( filter.Filter(artists=['Buckethead'])) self.assertEqual(len(musics), 4) musics = await self.collection.musics( filter.Filter(artists=['Buckethead'], min_rating=5.0)) self.assertEqual(len(musics), 3) musics = await self.collection.musics( filter.Filter(artists=['Buckethead'], min_duration=2)) self.assertEqual(len(musics), 0) musics = await self.collection.musics( filter.Filter(artists=['Buckethead'], keywords=['experimental'])) self.assertEqual(len(musics), 2) musics = await self.collection.musics( filter.Filter(artists=['Buckethead'], no_keywords=['heavy'])) self.assertEqual(len(musics), 3) musics = await self.collection.musics(filter.Filter(artists=['1995'])) self.assertEqual(len(musics), 1)
async def test_filtered_stats(self): mf = filter.Filter(keywords=['rock']) stats = await self.collection.stats(mf) self.assertEqual(dict(stats), filtered_teststats)
def cli(ctx, **kwargs): '''Music tags management''' ctx.obj.db = collection.Collection(**kwargs) ctx.obj.mf = filter.Filter(**kwargs)
def cli(ctx, concurrency, **kwargs): '''Youtube management''' ctx.obj.db = collection.Collection(**kwargs) ctx.obj.mf = filter.Filter(**kwargs) ctx.obj.concurrency = concurrency