import argparse import re import typing import symuid def _walk_track_attrs(path, path_ignore_regex) -> typing.Iterator[dict]: for track in symuid.Track.walk(path, path_ignore_regex): yield {'path': track.path, 'comment': track.comment, 'play_count': track.get_play_count_sum()} def _init_argparser(): argparser = argparse.ArgumentParser(description='filter & sort tracks') argparser.add_argument('path') argparser.add_argument( '--path-ignore-regex', default=symuid.Track.PATH_DEFAULT_IGNORE_REGEX, dest='path_ignore_regex', nargs=1, type=re.compile, metavar='pattern', help='(default: %(default)s)', ) argparser.add_argument( '--filter', metavar='expression', dest='filter_expression', help='(example: {!r} or {!r})'.format( "play_count > 16 and path.endswith('.mp3')", "comment is None or len(comment) < 16", ), ) argparser.add_argument( '--sort', metavar='expression', dest='sort_expression', help='(example: {!r} or {!r})'.format( "play_count * -1", "(play_count, len(path))", ), ) argparser.add_argument( '--limit', type=int, help='(default: none)', ) argparser.add_argument( '--prefix', type=str, default='', help='add prefix to each resulting path (default: %(default)r)', ) return argparser def _main(): args = _init_argparser().parse_args() # use generators until sort is required track_attrs = _walk_track_attrs(path=args.path, path_ignore_regex=args.path_ignore_regex) # pylint: disable=eval-used if args.filter_expression: track_attrs = filter(lambda a: eval(args.filter_expression, a), track_attrs) if args.sort_expression: track_attrs = sorted(track_attrs, key=lambda a: eval(args.sort_expression, a)) for track_index, attr in enumerate(track_attrs): if args.limit and track_index == args.limit: break print(args.prefix + attr['path'])