[elbe-devel] [PATCH 1/2] elbepack: db: migrate to argparse

Thomas Weißschuh thomas.weissschuh at linutronix.de
Thu Jul 25 14:25:40 CEST 2024


argparse has various advantages over optparse:

* Autogenerated command synopsis.
* Required arguments.
* Flexible argument types.
* Subparsers.

Furthermore optparse is deprecated since Python 3.2 (2011).

Signed-off-by: Thomas Weißschuh <thomas.weissschuh at linutronix.de>
---
 elbepack/commands/db.py |  24 +--
 elbepack/dbaction.py    | 543 ++++++++++++++++--------------------------------
 2 files changed, 189 insertions(+), 378 deletions(-)

diff --git a/elbepack/commands/db.py b/elbepack/commands/db.py
index 0a9694a14836..cfc2ea4cb699 100644
--- a/elbepack/commands/db.py
+++ b/elbepack/commands/db.py
@@ -2,21 +2,21 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 # SPDX-FileCopyrightText: 2014, 2017 Linutronix GmbH
 
-from elbepack.dbaction import DbAction
+import argparse
+
+from elbepack.cli import add_arguments_from_decorated_function
+from elbepack.dbaction import db_actions
 
 
 def run_command(argv):
+    aparser = argparse.ArgumentParser(prog='elbe db')
+    subparsers = aparser.add_subparsers(required=True)
 
-    if not argv:
-        print('elbe db - no action given')
-        DbAction.print_actions()
-        return
+    for action_name, do_action in db_actions.items():
+        action_parser = subparsers.add_parser(action_name)
+        action_parser.set_defaults(func=do_action)
+        add_arguments_from_decorated_function(action_parser, do_action)
 
-    try:
-        DbAction(argv[0]).execute(argv[1:])
-    except KeyError:
-        print('elbe db - unknown action given')
-        DbAction.print_actions()
-        return
+    args = aparser.parse_args(argv)
 
-    return
+    args.func(args)
diff --git a/elbepack/dbaction.py b/elbepack/dbaction.py
index b7da9f218cbb..0eeef8331c54 100644
--- a/elbepack/dbaction.py
+++ b/elbepack/dbaction.py
@@ -4,383 +4,194 @@
 
 import sys
 from getpass import getpass
-from optparse import OptionParser
 from shutil import copyfileobj
 
+from elbepack.cli import add_argument
 from elbepack.db import ElbeDB, ElbeDBError
 
 
-class DbAction:
-
-    actiondict = {}
-
-    @classmethod
-    def register(cls, action):
-        cls.actiondict[action.tag] = action
-
-    @classmethod
-    def print_actions(cls):
-        print('available actions are:')
-        for a in cls.actiondict:
-            print(f'   {a}')
-
-    def __new__(cls, node):
-        action = cls.actiondict[node]
-        return object.__new__(action)
-
-    def __init__(self, node):
-        self.node = node
-
-    def execute(self, _args):
-        raise NotImplementedError('execute() not implemented')
-
-
-class InitAction(DbAction):
-    tag = 'init'
-
-    def execute(self, args):
-        oparser = OptionParser(usage='usage: %prog db init [options]')
-        oparser.add_option('--name', dest='name', default='root')
-        oparser.add_option('--fullname', dest='fullname', default='Admin')
-        oparser.add_option('--password', dest='password', default='foo')
-        oparser.add_option('--email', dest='email', default='root at localhost')
-        oparser.add_option('--noadmin', dest='admin', default=True,
-                           action='store_false')
-
-        (opt, _) = oparser.parse_args(args)
-
-        ElbeDB.init_db(opt.name, opt.fullname, opt.password,
-                       opt.email, opt.admin)
-
-
-DbAction.register(InitAction)
-
-
-class AddUserAction(DbAction):
-    tag = 'add_user'
-
-    def execute(self, args):
-        oparser = OptionParser(
-            usage='usage: %prog db add_user [options] <username>')
-        oparser.add_option('--fullname', dest='fullname')
-        oparser.add_option('--password', dest='password')
-        oparser.add_option('--email', dest='email')
-        oparser.add_option('--admin', dest='admin', default=False,
-                           action='store_true')
-
-        (opt, arg) = oparser.parse_args(args)
-
-        if len(arg) != 1:
-            print('wrong number of arguments')
-            oparser.print_help()
-            return
-
-        if not opt.password:
-            password = getpass('Password for the new user: ')
-        else:
-            password = opt.password
-
-        db = ElbeDB()
-        db.add_user(arg[0], opt.fullname, password, opt.email, opt.admin)
-
-
-DbAction.register(AddUserAction)
-
-
-class DelUserAction(DbAction):
-    tag = 'del_user'
-
-    def execute(self, args):
-        oparser = OptionParser(
-            usage='usage: %prog db del_user [options] <userid>')
-        oparser.add_option('--delete-projects', dest='delete_projects',
-                           default=False, action='store_true')
-        oparser.add_option('--quiet', dest='quiet',
-                           default=False, action='store_true')
-
-        (opt, arg) = oparser.parse_args(args)
-
-        if len(arg) != 1:
-            print('usage: elbe db del_user <userid>')
-            return
-
-        try:
-            userid = int(arg[0])
-        except ValueError as E:
-            print(f'userid must be an integer - {E}')
-            return
-
-        db = ElbeDB()
-
-        projects = db.del_user(userid)
-
-        if projects:
-            if not opt.quiet:
-                if opt.delete_projects:
-                    print('removing projects owned by the deleted user:')
-                else:
-                    print('keeping projects owned by the deleted user:')
-
-        for p in projects:
-            if not opt.quiet:
-                print(f'{p.builddir}: {p.name} [{p.version}] {p.edit}')
-            if opt.delete_projects:
-                try:
-                    db.del_project(p.builddir)
-                except ElbeDBError as e:
-                    print(f'  ==> {e} ')
-
-
-DbAction.register(DelUserAction)
-
-
-class ListProjectsAction(DbAction):
-
-    tag = 'list_projects'
-
-    def execute(self, _args):
-        db = ElbeDB()
-        projects = db.list_projects()
-
-        for p in projects:
-            print(f'{p.builddir}: {p.name} [{p.version}] {p.edit}')
-
-
-DbAction.register(ListProjectsAction)
-
-
-class ListUsersAction(DbAction):
-
-    tag = 'list_users'
-
-    def execute(self, _args):
-        db = ElbeDB()
-        users = db.list_users()
-
-        for u in users:
-            print(f'{u.name}: {u.fullname} <{u.email}>')
-
-
-DbAction.register(ListUsersAction)
-
-
-class CreateProjectAction(DbAction):
-
-    tag = 'create_project'
-
-    def execute(self, args):
-        oparser = OptionParser(
-            usage='usage: %prog db create_project [options] <project_dir>')
-        oparser.add_option('--user', dest='user',
-                           help='user name of the designated project owner')
-        (opt, arg) = oparser.parse_args(args)
-
-        if len(arg) != 1:
-            oparser.print_help()
-            return
-
-        db = ElbeDB()
-        owner_id = db.get_user_id(opt.user)
-        db.create_project(arg[0], owner_id)
-
-
-DbAction.register(CreateProjectAction)
-
-
-class DeleteProjectAction(DbAction):
-
-    tag = 'del_project'
-
-    def execute(self, args):
-        if len(args) != 1:
-            print('usage: elbe db del_project <project_dir>')
-            return
-
-        db = ElbeDB()
-        db.del_project(args[0])
-
-
-DbAction.register(DeleteProjectAction)
-
-
-class SetXmlAction(DbAction):
-
-    tag = 'set_xml'
-
-    def execute(self, args):
-        if len(args) != 2:
-            print('usage: elbe db set_xml <project_dir> <xml>')
-            return
-
-        db = ElbeDB()
-        db.set_xml(args[0], args[1])
-
-
-DbAction.register(SetXmlAction)
-
-
-class BuildAction(DbAction):
-
-    tag = 'build'
-
-    def execute(self, args):
-        if len(args) != 1:
-            print('usage: elbe db build <project_dir>')
-            return
-
-        db = ElbeDB()
-        db.set_busy(args[0], ['empty_project', 'needs_build', 'has_changes',
-                              'build_done', 'build_failed'])
-        try:
-            ep = db.load_project(args[0])
-            ep.build()
-            db.update_project_files(ep)
-        except Exception as e:
-            db.update_project_files(ep)
-            db.reset_busy(args[0], 'build_failed')
-            print(str(e))
-            return
-        db.reset_busy(args[0], 'build_done')
-
-
-DbAction.register(BuildAction)
-
-
-class GetFilesAction(DbAction):
-
-    tag = 'get_files'
-
-    def execute(self, args):
-        if len(args) != 1:
-            print('usage: elbe db get_files <project_dir>')
-            return
-
-        db = ElbeDB()
-        files = db.get_project_files(args[0])
-        for f in files:
-            if f.description:
-                print(f'{f.name:40}  {f.description}')
-            else:
-                print(f.name)
-
-
-DbAction.register(GetFilesAction)
-
-
-class ResetProjectAction(DbAction):
-
-    tag = 'reset_project'
-
-    def execute(self, args):
-        oparser = OptionParser(
-            usage='usage: %prog db reset_project [options] <project_dir>')
-        oparser.add_option('--clean', dest='clean', default=False,
-                           action='store_true')
-
-        (opt, arg) = oparser.parse_args(args)
-
-        if len(arg) != 1:
-            print('wrong number of arguments')
-            oparser.print_help()
-            return
-
-        db = ElbeDB()
-        db.reset_project(arg[0], opt.clean)
-
-
-DbAction.register(ResetProjectAction)
-
-
-class SetProjectVersionAction(DbAction):
-
-    tag = 'set_project_version'
-
-    def execute(self, args):
-        if len(args) != 2:
-            print('usage: elbe db set_project_version <project_dir> <version>')
-            return
-
-        db = ElbeDB()
-        db.set_project_version(args[0], args[1])
-
-
-DbAction.register(SetProjectVersionAction)
-
-
-class ListVersionsAction(DbAction):
-
-    tag = 'list_versions'
-
-    def execute(self, args):
-        if len(args) != 1:
-            print('usage: elbe db list_versions <project_dir>')
-            return
-
-        db = ElbeDB()
-        versions = db.list_project_versions(args[0])
-
-        for v in versions:
-            if v.description:
-                print(f'{v.version}: {v.description}')
+ at add_argument('--name', default='root')
+ at add_argument('--fullname', default='Admin')
+ at add_argument('--password', default='foo')
+ at add_argument('--email', default='root at localhost')
+ at add_argument('--noadmin', dest='admin', default=True, action='store_false')
+def _init(self, args):
+    ElbeDB.init_db(args.name, args.fullname, args.password,
+                   args.email, args.admin)
+
+
+ at add_argument('--fullname')
+ at add_argument('--password')
+ at add_argument('--email')
+ at add_argument('--admin', default=False, action='store_true')
+ at add_argument('username')
+def _add_user(self, args):
+    if not args.password:
+        password = getpass('Password for the new user: ')
+    else:
+        password = args.password
+
+    db = ElbeDB()
+    db.add_user(args.username, args.fullname, password, args.email, args.admin)
+
+
+ at add_argument('--delete-projects', dest='delete_projects',
+              default=False, action='store_true')
+ at add_argument('--quiet', dest='quiet',
+              default=False, action='store_true')
+ at add_argument('userid', type=int)
+def _del_user(args):
+    db = ElbeDB()
+
+    projects = db.del_user(args.userid)
+
+    if projects:
+        if not args.opt.quiet:
+            if args.opt.delete_projects:
+                print('removing projects owned by the deleted user:')
             else:
-                print(v.version)
-
-
-DbAction.register(ListVersionsAction)
-
-
-class SaveVersionAction(DbAction):
+                print('keeping projects owned by the deleted user:')
 
-    tag = 'save_version'
-
-    def execute(self, args):
-        oparser = OptionParser(
-            usage='usage: %prog db save_version <project_dir>')
-        oparser.add_option('--description', dest='description')
-
-        (opt, arg) = oparser.parse_args(args)
-
-        if len(arg) != 1:
-            print('wrong number of arguments')
-            oparser.print_help()
-            return
-
-        db = ElbeDB()
-        db.save_version(arg[0], opt.description)
-
-
-DbAction.register(SaveVersionAction)
-
-
-class DelVersionAction(DbAction):
-
-    tag = 'del_version'
-
-    def execute(self, args):
-        if len(args) != 2:
-            print('usage: elbe db del_version <project_dir> <version>')
-            return
-
-        db = ElbeDB()
-        db.del_version(args[0], args[1])
-
-
-DbAction.register(DelVersionAction)
+    for p in projects:
+        if not args.opt.quiet:
+            print(f'{p.builddir}: {p.name} [{p.version}] {p.edit}')
+        if args.opt.delete_projects:
+            try:
+                db.del_project(p.builddir)
+            except ElbeDBError as e:
+                print(f'  ==> {e} ')
+
+
+def _list_projects(args):
+    db = ElbeDB()
+    projects = db.list_projects()
+
+    for p in projects:
+        print(f'{p.builddir}: {p.name} [{p.version}] {p.edit}')
+
+
+def _list_users(args):
+    db = ElbeDB()
+    users = db.list_users()
+
+    for u in users:
+        print(f'{u.name}: {u.fullname} <{u.email}>')
+
+
+ at add_argument('--user', dest='user',
+              help='user name of the designated project owner')
+ at add_argument('project_dir')
+def _create_project(args):
+    db = ElbeDB()
+    owner_id = db.get_user_id(args.user)
+    db.create_project(args.project_dir, owner_id)
+
+
+ at add_argument('project_dir')
+def _del_project(args):
+    db = ElbeDB()
+    db.del_project(args.project_dir)
+
+
+ at add_argument('project_dir')
+ at add_argument('xml')
+def _set_xml(args):
+    db = ElbeDB()
+    db.set_xml(args.project_dir, args.xml)
+
+
+ at add_argument('project_dir')
+def _build(args):
+    db = ElbeDB()
+    db.set_busy(args.project_dir, ['empty_project', 'needs_build', 'has_changes',
+                                   'build_done', 'build_failed'])
+    try:
+        ep = db.load_project(args.project_dir)
+        ep.build()
+        db.update_project_files(ep)
+    except Exception as e:
+        db.update_project_files(ep)
+        db.reset_busy(args.project_dir, 'build_failed')
+        print(str(e))
+        return
+    db.reset_busy(args.project_dir, 'build_done')
+
+
+ at add_argument('project_dir')
+def _get_files(args):
+    db = ElbeDB()
+    files = db.get_project_files(args.project_dir)
+    for f in files:
+        if f.description:
+            print(f'{f.name:40}  {f.description}')
+        else:
+            print(f.name)
 
 
-class PrintVersionXMLAction(DbAction):
+ at add_argument('--clean', dest='clean', default=False, action='store_true')
+ at add_argument('project_dir')
+def _reset_project(args):
+    db = ElbeDB()
+    db.reset_project(args.project_dir, args.clean)
 
-    tag = 'print_version_xml'
 
-    def execute(self, args):
-        if len(args) != 2:
-            print('usage: elbe db print_version_xml <project_dir> <version>')
-            return
+ at add_argument('project_dir')
+ at add_argument('version')
+def _set_project_version(args):
+    db = ElbeDB()
+    db.set_project_version(args.project_dir, args.version)
 
-        db = ElbeDB()
-        filename = db.get_version_xml(args[0], args[1])
-        with open(filename) as f:
-            copyfileobj(f, sys.stdout)
 
+ at add_argument('project_dir')
+def _list_versions(args):
+    db = ElbeDB()
+    versions = db.list_project_versions(args.project_dir)
 
-DbAction.register(PrintVersionXMLAction)
+    for v in versions:
+        if v.description:
+            print(f'{v.version}: {v.description}')
+        else:
+            print(v.version)
+
+
+ at add_argument('--description', dest='description')
+ at add_argument('project_dir')
+def _save_version(args):
+    db = ElbeDB()
+    db.save_version(args.project_dir, args.description)
+
+
+ at add_argument('project_dir')
+ at add_argument('version')
+def _del_version(args):
+    db = ElbeDB()
+    db.del_version(args.project_dir, args.version)
+
+
+ at add_argument('project_dir')
+ at add_argument('version')
+def _print_version_xml(args):
+    db = ElbeDB()
+    filename = db.get_version_xml(args.project_dir, args.version)
+    with open(filename) as f:
+        copyfileobj(f, sys.stdout)
+
+
+db_actions = {
+    'init':                _init,
+    'add_user':            _add_user,
+    'del_user':            _del_user,
+    'list_projects':       _list_projects,
+    'list_users':          _list_users,
+    'create_project':      _create_project,
+    'del_project':         _del_project,
+    'set_xml':             _set_xml,
+    'build':               _build,
+    'get_files':           _get_files,
+    'reset_project':       _reset_project,
+    'set_project_version': _set_project_version,
+    'list_versions':       _list_versions,
+    'save_version':        _save_version,
+    'del_versions':        _del_version,
+    'print_version_xml':   _print_version_xml,
+}

-- 
2.45.2



More information about the elbe-devel mailing list