From 91b441215294ba71ca602b123a1d2705179696d5 Mon Sep 17 00:00:00 2001 From: spl0k Date: Sun, 8 Sep 2013 17:23:38 +0200 Subject: [PATCH] CLI: autogenerate do_ and help_ methods from parsers --- cli.py | 230 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 127 insertions(+), 103 deletions(-) diff --git a/cli.py b/cli.py index 8124a4e..b2c3d76 100755 --- a/cli.py +++ b/cli.py @@ -11,6 +11,47 @@ class CLIParser(argparse.ArgumentParser): class CLI(cmd.Cmd): prompt = "supysonic> " + def _make_do(self, command): + def method(obj, line): + try: + args = getattr(obj, command + '_parser').parse_args(line.split()) + except RuntimeError, e: + print >>sys.stderr, e + return + + if hasattr(obj.__class__, command + '_subparsers'): + try: + func = getattr(obj, '{}_{}'.format(command, args.action)) + except AttributeError: + return obj.default(line) + return func(** { key: vars(args)[key] for key in vars(args) if key != 'action' }) + else: + try: + func = getattr(obj, command) + except AttributeError: + return obj.default(line) + return func(**vars(args)) + + return method + + def __init__(self): + cmd.Cmd.__init__(self) + + # Generate do_* and help_* methods + for parser_name in filter(lambda attr: attr.endswith('_parser') and '_' not in attr[:-7], dir(self.__class__)): + command = parser_name[:-7] + + if not hasattr(self.__class__, 'do_' + command): + setattr(self.__class__, 'do_' + command, self._make_do(command)) + + if hasattr(self.__class__, 'do_' + command) and not hasattr(self.__class__, 'help_' + command): + setattr(self.__class__, 'help_' + command, getattr(self.__class__, parser_name).print_help) + if hasattr(self.__class__, command + '_subparsers'): + for action in getattr(self.__class__, command + '_subparsers').choices.keys(): + subparser = getattr(self.__class__, '{}_{}_parser'.format(command, action), None) + if subparser: + setattr(self, 'help_{} {}'.format(command, action), subparser.print_help) + def do_EOF(self, line): return True @@ -23,7 +64,7 @@ class CLI(cmd.Cmd): def completedefault(self, text, line, begidx, endidx): command = line.split()[0] - parsers = getattr(self, command + '_subparsers', None) + parsers = getattr(self.__class__, command + '_subparsers', None) if not parsers: return [] @@ -38,56 +79,47 @@ class CLI(cmd.Cmd): folder_add_parser = folder_subparsers.add_parser('add', help = 'Adds a folder', add_help = False) folder_add_parser.add_argument('name', help = 'Name of the folder to add') folder_add_parser.add_argument('path', help = 'Path to the directory pointed by the folder') - folder_del_parser = folder_subparsers.add_parser('delete', help = 'Deletes a folder', add_help = False) - folder_del_parser.add_argument('name', help = 'Name of the folder to delete') + folder_delete_parser = folder_subparsers.add_parser('delete', help = 'Deletes a folder', add_help = False) + folder_delete_parser.add_argument('name', help = 'Name of the folder to delete') folder_scan_parser = folder_subparsers.add_parser('scan', help = 'Run a scan on specified folders', add_help = False) folder_scan_parser.add_argument('folders', metavar = 'folder', nargs = '*', help = 'Folder(s) to be scanned. If ommitted, all folders are scanned') - def do_folder(self, line): - try: - args = self.folder_parser.parse_args(line.split()) - except RuntimeError, e: - print >>sys.stderr, e - return + def folder_list(self): + print 'Name\t\tPath\n----\t\t----' + print '\n'.join('{0: <16}{1}'.format(f.name, f.path) for f in db.Folder.query.filter(db.Folder.root == True)) - if args.action == 'list': - print 'Name\t\tPath\n----\t\t----' - print '\n'.join('{0: <16}{1}'.format(f.name, f.path) for f in db.Folder.query.filter(db.Folder.root == True)) - elif args.action == 'add': - ret = FolderManager.add(args.name, args.path) - if ret != FolderManager.SUCCESS: - print FolderManager.error_str(ret) - else: - print "Folder '%s' added" % args.name - elif args.action == 'delete': - ret = FolderManager.delete_by_name(args.name) - if ret != FolderManager.SUCCESS: - print FolderManager.error_str(ret) - else: - print "Deleted folder '%s'" % args.name - elif args.action == 'scan': - s = Scanner(db.session) - if args.folders: - folders = map(lambda n: db.Folder.query.filter(db.Folder.name == n and db.Folder.root == True).first() or n, args.folders) - if any(map(lambda f: isinstance(f, basestring), folders)): - print "No such folder(s): " + ' '.join(f for f in folders if isinstance(f, basestring)) - for folder in filter(lambda f: isinstance(f, db.Folder), folders): - FolderManager.scan(folder.id, s) - else: - for folder in db.Folder.query.filter(db.Folder.root == True): - FolderManager.scan(folder.id, s) + def folder_add(self, name, path): + ret = FolderManager.add(name, path) + if ret != FolderManager.SUCCESS: + print FolderManager.error_str(ret) + else: + print "Folder '{}' added".format(name) - added, deleted = s.stats() - db.session.commit() + def folder_delete(self, name): + ret = FolderManager.delete_by_name(name) + if ret != FolderManager.SUCCESS: + print FolderManager.error_str(ret) + else: + print "Deleted folder '{}'".format(name) - print "Scanning done" - print 'Added: %i artists, %i albums, %i tracks' % (added[0], added[1], added[2]) - print 'Deleted: %i artists, %i albums, %i tracks' % (deleted[0], deleted[1], deleted[2]) + def folder_scan(self, folders): + s = Scanner(db.session) + if folders: + folders = map(lambda n: db.Folder.query.filter(db.Folder.name == n and db.Folder.root == True).first() or n, folders) + if any(map(lambda f: isinstance(f, basestring), folders)): + print "No such folder(s): " + ' '.join(f for f in folders if isinstance(f, basestring)) + for folder in filter(lambda f: isinstance(f, db.Folder), folders): + FolderManager.scan(folder.id, s) + else: + for folder in db.Folder.query.filter(db.Folder.root == True): + FolderManager.scan(folder.id, s) - def help_folder(self): - self.folder_parser.print_help() - #for cmd, parser in self.folder_subparsers.choices.iteritems(): - # parser.print_help() + added, deleted = s.stats() + db.session.commit() + + print "Scanning done" + print 'Added: %i artists, %i albums, %i tracks' % (added[0], added[1], added[2]) + print 'Deleted: %i artists, %i albums, %i tracks' % (deleted[0], deleted[1], deleted[2]) user_parser = CLIParser(prog = 'user', add_help = False) user_subparsers = user_parser.add_subparsers(dest = 'action') @@ -97,68 +129,60 @@ class CLI(cmd.Cmd): user_add_parser.add_argument('-a', '--admin', action = 'store_true', help = 'Give admin rights to the new user') user_add_parser.add_argument('-p', '--password', help = "Specifies the user's password") user_add_parser.add_argument('-e', '--email', default = '', help = "Sets the user's email address") - user_del_parser = user_subparsers.add_parser('delete', help = 'Deletes a user', add_help = False) - user_del_parser.add_argument('name', help = 'Name/login of the user to delete') - user_admin_parser = user_subparsers.add_parser('set-admin', help = 'Enable/disable admin rights for a user', add_help = False) - user_admin_parser.add_argument('name', help = 'Name/login of the user to grant/revoke admin rights') - user_admin_parser.add_argument('--off', action = 'store_true', help = 'Revoke admin rights if present, grant them otherwise') - user_pass_parser = user_subparsers.add_parser('changepass', help = "Changes a user's password", add_help = False) - user_pass_parser.add_argument('name', help = 'Name/login of the user to which change the password') - user_pass_parser.add_argument('password', nargs = '?', help = 'New password') + user_delete_parser = user_subparsers.add_parser('delete', help = 'Deletes a user', add_help = False) + user_delete_parser.add_argument('name', help = 'Name/login of the user to delete') + user_setadmin_parser = user_subparsers.add_parser('setadmin', help = 'Enable/disable admin rights for a user', add_help = False) + user_setadmin_parser.add_argument('name', help = 'Name/login of the user to grant/revoke admin rights') + user_setadmin_parser.add_argument('--off', action = 'store_true', help = 'Revoke admin rights if present, grant them otherwise') + user_changepass_parser = user_subparsers.add_parser('changepass', help = "Changes a user's password", add_help = False) + user_changepass_parser.add_argument('name', help = 'Name/login of the user to which change the password') + user_changepass_parser.add_argument('password', nargs = '?', help = 'New password') - def do_user(self, line): - try: - args = self.user_parser.parse_args(line.split()) - except RuntimeError, e: - print >>sys.stderr, e - return + def user_list(self): + print 'Name\t\tAdmin\tEmail\n----\t\t-----\t-----' + print '\n'.join('{0: <16}{1}\t{2}'.format(u.name, '*' if u.admin else '', u.mail) for u in db.User.query.all()) - if args.action == 'list': - print 'Name\t\tAdmin\tEmail\n----\t\t-----\t-----' - print '\n'.join('{0: <16}{1}\t{2}'.format(u.name, '*' if u.admin else '', u.mail) for u in db.User.query.all()) - elif args.action == 'add': - if not args.password: - password = getpass.getpass() - confirm = getpass.getpass('Confirm password: ') - if password != confirm: - print >>sys.stderr, "Passwords don't match" - return - args.password = password - status = UserManager.add(args.name, args.password, args.email, args.admin) - if status != UserManager.SUCCESS: - print >>sys.stderr, UserManager.error_str(status) - elif args.action == 'delete': - user = db.User.query.filter(db.User.name == args.name).first() - if not user: - print >>sys.stderr, 'No such user' - else: - db.session.delete(user) - db.session.commit() - print "User '{0.name}' deleted".format(args) - elif args.action == 'set-admin': - user = db.User.query.filter(db.User.name == args.name).first() - if not user: - print >>sys.stderr, 'No such user' - else: - user.admin = not args.off - db.session.commit() - print "{0} '{1}' admin rights".format('Revoked' if args.off else 'Granted', args.name) - elif args.action == 'changepass': - if not args.password: - password = getpass.getpass() - confirm = getpass.getpass('Confirm password: ') - if password != confirm: - print >>sys.stderr, "Passwords don't match" - return - args.password = password - status = UserManager.change_password2(args.name, args.password) - if status != UserManager.SUCCESS: - print >>sys.stderr, UserManager.error_str(status) - else: - print "Successfully changed '{}' password".format(args.name) + def user_add(self, name, admin, password, email): + if not password: + password = getpass.getpass() + confirm = getpass.getpass('Confirm password: ') + if password != confirm: + print >>sys.stderr, "Passwords don't match" + return + status = UserManager.add(name, password, email, admin) + if status != UserManager.SUCCESS: + print >>sys.stderr, UserManager.error_str(status) - def help_user(self): - self.user_parser.print_help() + def user_delete(self, name): + user = db.User.query.filter(db.User.name == name).first() + if not user: + print >>sys.stderr, 'No such user' + else: + db.session.delete(user) + db.session.commit() + print "User '{}' deleted".format(name) + + def user_setadmin(self, name, off): + user = db.User.query.filter(db.User.name == name).first() + if not user: + print >>sys.stderr, 'No such user' + else: + user.admin = not off + db.session.commit() + print "{0} '{1}' admin rights".format('Revoked' if off else 'Granted', name) + + def user_changepass(self, name, password): + if not password: + password = getpass.getpass() + confirm = getpass.getpass('Confirm password: ') + if password != confirm: + print >>sys.stderr, "Passwords don't match" + return + status = UserManager.change_password2(name, password) + if status != UserManager.SUCCESS: + print >>sys.stderr, UserManager.error_str(status) + else: + print "Successfully changed '{}' password".format(name) if __name__ == "__main__": if not config.check():