[elbe-devel] [PATCH 2/3] elbepack: pbuilder: migrate to argparse
Thomas Weißschuh
thomas.weissschuh at linutronix.de
Fri Jul 26 10:55:11 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).
Replace the custom action registry with a simple dispatch table, which
is both less code and easier to understand.
Also move the options to the subcommands where they make sense.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh at linutronix.de>
---
elbepack/commands/pbuilder.py | 77 ++------
elbepack/pbuilderaction.py | 425 ++++++++++++++++++++----------------------
2 files changed, 218 insertions(+), 284 deletions(-)
diff --git a/elbepack/commands/pbuilder.py b/elbepack/commands/pbuilder.py
index 851e277973b3..1bf16edd2ae3 100644
--- a/elbepack/commands/pbuilder.py
+++ b/elbepack/commands/pbuilder.py
@@ -2,75 +2,26 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2015-2017 Linutronix GmbH
-import sys
-from optparse import OptionParser
+import argparse
-from elbepack.commands.preprocess import add_xmlpreprocess_passthrough_options
-from elbepack.pbuilderaction import PBuilderAction
+from elbepack.cli import add_arguments_from_decorated_function
+from elbepack.commands.preprocess import add_xmlpreprocess_passthrough_arguments
+from elbepack.pbuilderaction import pbuilder_actions
def run_command(argv):
- oparser = OptionParser(usage='usage: elbe pbuilder [options] <command>')
+ aparser = argparse.ArgumentParser(prog='elbe pbuilder')
- oparser.add_option('--project', dest='project', default=None,
- help='project directory on the initvm')
+ add_xmlpreprocess_passthrough_arguments(aparser)
- oparser.add_option('--xmlfile', dest='xmlfile', default=None,
- help='xmlfile to use')
+ subparsers = aparser.add_subparsers(required=True)
- oparser.add_option('--writeproject', dest='writeproject', default=None,
- help='write project name to file')
+ for action_name, do_action in pbuilder_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)
- oparser.add_option('--skip-download', action='store_true',
- dest='skip_download', default=False,
- help='Skip downloading generated Files')
+ args = aparser.parse_args(argv)
+ args.parser = aparser
- oparser.add_option(
- '--origfile',
- dest='origfile',
- default=[],
- action='append',
- help='upload orig file')
-
- oparser.add_option('--source', dest='srcdir', default='.',
- help='directory containing sources')
-
- oparser.add_option('--output', dest='outdir', default='..',
- help='directory where to save downloaded Files')
-
- oparser.add_option('--profile', dest='profile', default='',
- help='profile that shall be built')
-
- oparser.add_option('--cross', dest='cross', default=False,
- action='store_true',
- help='Creates an environment for crossbuilding if '
- 'combined with create. Combined with build it'
- ' will use this environment.')
-
- oparser.add_option('--no-ccache', dest='noccache', default=False,
- action='store_true',
- help="Deactivates the compiler cache 'ccache'")
-
- oparser.add_option('--ccache-size', dest='ccachesize', default='10G',
- action='store', type='string',
- help='set a limit for the compiler cache size '
- '(should be a number followed by an optional '
- 'suffix: k, M, G, T. Use 0 for no limit.)')
-
- add_xmlpreprocess_passthrough_options(oparser)
-
- (opt, args) = oparser.parse_args(argv)
-
- if not args:
- print('elbe pbuilder - no subcommand given', file=sys.stderr)
- PBuilderAction.print_actions()
- return
-
- try:
- action = PBuilderAction(args[0])
- except KeyError:
- print('elbe pbuilder - unknown subcommand', file=sys.stderr)
- PBuilderAction.print_actions()
- sys.exit(92)
-
- action.execute(opt, args[1:])
+ args.func(args)
diff --git a/elbepack/pbuilderaction.py b/elbepack/pbuilderaction.py
index b8bc6d5f05b1..b2e8b2ec14bf 100644
--- a/elbepack/pbuilderaction.py
+++ b/elbepack/pbuilderaction.py
@@ -5,271 +5,254 @@
import subprocess
import sys
+from elbepack.cli import add_argument
from elbepack.directories import run_elbe
from elbepack.filesystem import TmpdirFilesystem
from elbepack.xmlpreprocess import preprocess_file
-class PBuilderAction:
- actiondict = {}
-
- @classmethod
- def register(cls, action):
- cls.actiondict[action.tag] = action
-
- @classmethod
- def print_actions(cls):
- print('available subcommands are:', file=sys.stderr)
- for a in cls.actiondict:
- print(f' {a}', file=sys.stderr)
-
- def __new__(cls, node):
- action = cls.actiondict[node]
- return object.__new__(action)
-
- def __init__(self, node):
- self.node = node
-
- def execute(self, _opt, _args):
- raise NotImplementedError('execute() not implemented')
-
-
-class CreateAction(PBuilderAction):
-
- tag = 'create'
-
- def execute(self, opt, _args):
- crossopt = []
- if opt.cross:
- crossopt = ['--cross']
- if opt.noccache:
- ccacheopt = ['--no-ccache']
- else:
- ccacheopt = ['--ccache-size', opt.ccachesize]
-
- if opt.xmlfile:
- with preprocess_file(opt.xmlfile, opt.variants) as preproc:
- ps = run_elbe(['control', 'create_project'],
- capture_output=True, encoding='utf-8')
- if ps.returncode != 0:
- print('elbe control create_project failed.',
- file=sys.stderr)
- print(ps.stderr, file=sys.stderr)
- print('Giving up', file=sys.stderr)
- sys.exit(152)
-
- prjdir = ps.stdout.strip()
- ps = run_elbe(['control', 'set_xml', prjdir, preproc],
- capture_output=True, encoding='utf-8')
-
- if ps.returncode != 0:
- print('elbe control set_xml failed.', file=sys.stderr)
- print(ps.stderr, file=sys.stderr)
- print('Giving up', file=sys.stderr)
- sys.exit(153)
+ at add_argument('--writeproject', help='write project name to file')
+ at add_argument('--ccache-size', dest='ccachesize', default='10G',
+ help='set a limit for the compiler cache size '
+ '(should be a number followed by an optional '
+ 'suffix: k, M, G, T. Use 0 for no limit.)')
+ at add_argument('--cross', dest='cross', default=False,
+ action='store_true',
+ help='Creates an environment for crossbuilding if '
+ 'combined with create. Combined with build it'
+ ' will use this environment.')
+ at add_argument('--no-ccache', dest='noccache', default=False,
+ action='store_true',
+ help="Deactivates the compiler cache 'ccache'")
+ at add_argument('--xmlfile', help='xmlfile to use')
+ at add_argument('--project', help='project directory on the initvm')
+def _create(args):
+ crossopt = []
+ if args.cross:
+ crossopt = ['--cross']
+ if args.noccache:
+ ccacheopt = ['--no-ccache']
+ else:
+ ccacheopt = ['--ccache-size', args.ccachesize]
+
+ if args.xmlfile:
+ with preprocess_file(args.xmlfile, args.variants) as preproc:
+ ps = run_elbe(['control', 'create_project'],
+ capture_output=True, encoding='utf-8')
+ if ps.returncode != 0:
+ print('elbe control create_project failed.',
+ file=sys.stderr)
+ print(ps.stderr, file=sys.stderr)
+ print('Giving up', file=sys.stderr)
+ sys.exit(152)
- if opt.writeproject:
- wpf = open(opt.writeproject, 'w')
- wpf.write(prjdir)
- wpf.close()
+ prjdir = ps.stdout.strip()
+ ps = run_elbe(['control', 'set_xml', prjdir, preproc],
+ capture_output=True, encoding='utf-8')
- elif opt.project:
- prjdir = opt.project
- else:
- print('you need to specify --project option', file=sys.stderr)
- sys.exit(155)
+ if ps.returncode != 0:
+ print('elbe control set_xml failed.', file=sys.stderr)
+ print(ps.stderr, file=sys.stderr)
+ print('Giving up', file=sys.stderr)
+ sys.exit(153)
+
+ if args.writeproject:
+ wpf = open(args.writeproject, 'w')
+ wpf.write(prjdir)
+ wpf.close()
+
+ elif args.project:
+ prjdir = args.project
+ else:
+ args.parser.error('you need to specify --project option')
+
+ print('Creating pbuilder')
+
+ try:
+ run_elbe(['control', 'build_pbuilder', prjdir, *crossopt, *ccacheopt],
+ check=True)
+ except subprocess.CalledProcessError:
+ print('elbe control build_pbuilder Failed', file=sys.stderr)
+ print('Giving up', file=sys.stderr)
+ sys.exit(156)
+
+ try:
+ run_elbe(['control', 'wait_busy', prjdir], check=True)
+ except subprocess.CalledProcessError:
+ print('elbe control wait_busy Failed', file=sys.stderr)
+ print('Giving up', file=sys.stderr)
+ sys.exit(157)
+
+ print('')
+ print('Building Pbuilder finished !')
+ print('')
+
+
+ at add_argument('--project', required=True, help='project directory on the initvm')
+def _update(args):
+ prjdir = args.project
+
+ print('Updating pbuilder')
+
+ try:
+ run_elbe(['control', 'update_pbuilder', prjdir], check=True)
+ except subprocess.CalledProcessError:
+ print('elbe control update_pbuilder Failed', file=sys.stderr)
+ print('Giving up', file=sys.stderr)
+ sys.exit(159)
+
+ print('')
+ print('Updating Pbuilder finished !')
+ print('')
+
+
+ at add_argument('--origfile', default=[], action='append', help='upload orig file')
+ at add_argument('--profile', default='', help='profile that shall be built')
+ at add_argument('--skip-download', action='store_true', dest='skip_download', default=False,
+ help='Skip downloading generated Files')
+ at add_argument('--source', dest='srcdir', default='.', help='directory containing sources')
+ at add_argument('--cross', dest='cross', default=False,
+ action='store_true',
+ help='Creates an environment for crossbuilding if '
+ 'combined with create. Combined with build it'
+ ' will use this environment.')
+ at add_argument('--output', dest='outdir', default='..',
+ help='directory where to save downloaded Files')
+ at add_argument('--xmlfile', help='xmlfile to use')
+ at add_argument('--project', help='project directory on the initvm')
+def _build(args):
+ crossopt = []
+ if args.cross:
+ crossopt = ['--cross']
+ tmp = TmpdirFilesystem()
+
+ if args.xmlfile:
+ ps = run_elbe(['control', '--retries', '60', 'create_project', args.xmlfile],
+ capture_output=True, encoding='utf-8')
+ if ps.returncode != 0:
+ print('elbe control create_project failed.', file=sys.stderr)
+ print(ps.stderr, file=sys.stderr)
+ print('Giving up', file=sys.stderr)
+ sys.exit(160)
- print('Creating pbuilder')
+ prjdir = ps.stdout.strip()
try:
- run_elbe(['control', 'build_pbuilder', prjdir, *crossopt, *ccacheopt],
- check=True)
+ run_elbe(['control', 'build_pbuilder', prjdir], check=True)
except subprocess.CalledProcessError:
print('elbe control build_pbuilder Failed', file=sys.stderr)
print('Giving up', file=sys.stderr)
- sys.exit(156)
+ sys.exit(161)
try:
run_elbe(['control', 'wait_busy', prjdir], check=True)
except subprocess.CalledProcessError:
print('elbe control wait_busy Failed', file=sys.stderr)
print('Giving up', file=sys.stderr)
- sys.exit(157)
+ sys.exit(162)
print('')
print('Building Pbuilder finished !')
print('')
-
-
-PBuilderAction.register(CreateAction)
-
-
-class UpdateAction(PBuilderAction):
-
- tag = 'update'
-
- def execute(self, opt, _args):
-
- if not opt.project:
- print('you need to specify --project option', file=sys.stderr)
- sys.exit(158)
-
- prjdir = opt.project
-
- print('Updating pbuilder')
-
+ elif args.project:
+ prjdir = args.project
+ run_elbe(['control', 'rm_log', prjdir], check=True)
+ else:
+ args.parser.error('you need to specify --project or --xmlfile option')
+
+ print('')
+ print('Packing Source into tmp archive')
+ print('')
+ try:
+ subprocess.run(['tar', '-C', args.srcdir, '-czf', tmp.fname('pdebuild.tar.gz'), '.'],
+ check=True)
+ except subprocess.CalledProcessError:
+ print('tar Failed', file=sys.stderr)
+ print('Giving up', file=sys.stderr)
+ sys.exit(164)
+
+ for of in args.origfile:
+ print('')
+ print(f"Pushing orig file '{of}' into pbuilder")
+ print('')
try:
- run_elbe(['control', 'update_pbuilder', prjdir], check=True)
+ run_elbe(['control', 'set_orig', prjdir, of], check=True)
except subprocess.CalledProcessError:
- print('elbe control update_pbuilder Failed', file=sys.stderr)
+ print('elbe control set_orig Failed', file=sys.stderr)
print('Giving up', file=sys.stderr)
- sys.exit(159)
-
+ sys.exit(165)
+
+ print('')
+ print('Pushing source into pbuilder')
+ print('')
+
+ try:
+ run_elbe([
+ 'control', 'set_pdebuild',
+ '--profile', args.profile, *crossopt,
+ prjdir, tmp.fname('pdebuild.tar.gz'),
+ ], check=True)
+ except subprocess.CalledProcessError:
+ print('elbe control set_pdebuild Failed', file=sys.stderr)
+ print('Giving up', file=sys.stderr)
+ sys.exit(166)
+ try:
+ run_elbe(['control', 'wait_busy', prjdir], check=True)
+ except subprocess.CalledProcessError:
+ print('elbe control wait_busy Failed', file=sys.stderr)
+ print('Giving up', file=sys.stderr)
+ sys.exit(167)
+ print('')
+ print('Pdebuild finished !')
+ print('')
+
+ if args.skip_download:
print('')
- print('Updating Pbuilder finished !')
- print('')
-
-
-PBuilderAction.register(CreateAction)
-
-
-class BuildAction(PBuilderAction):
-
- tag = 'build'
-
- def execute(self, opt, _args):
-
- crossopt = []
- if opt.cross:
- crossopt = ['--cross']
- tmp = TmpdirFilesystem()
-
- if opt.xmlfile:
- ps = run_elbe(['control', '--retries', '60', 'create_project', opt.xmlfile],
- capture_output=True, encoding='utf-8')
- if ps.returncode != 0:
- print('elbe control create_project failed.', file=sys.stderr)
- print(ps.stderr, file=sys.stderr)
- print('Giving up', file=sys.stderr)
- sys.exit(160)
-
- prjdir = ps.stdout.strip()
-
- try:
- run_elbe(['control', 'build_pbuilder', prjdir], check=True)
- except subprocess.CalledProcessError:
- print('elbe control build_pbuilder Failed', file=sys.stderr)
- print('Giving up', file=sys.stderr)
- sys.exit(161)
-
- try:
- run_elbe(['control', 'wait_busy', prjdir], check=True)
- except subprocess.CalledProcessError:
- print('elbe control wait_busy Failed', file=sys.stderr)
- print('Giving up', file=sys.stderr)
- sys.exit(162)
-
- print('')
- print('Building Pbuilder finished !')
- print('')
- elif opt.project:
- prjdir = opt.project
- run_elbe(['control', 'rm_log', prjdir], check=True)
- else:
- print(
- 'you need to specify --project or --xmlfile option',
- file=sys.stderr)
- sys.exit(163)
-
- print('')
- print('Packing Source into tmp archive')
+ print('Listing available files:')
print('')
try:
- subprocess.run(['tar', '-C', opt.srcdir, '-czf', tmp.fname('pdebuild.tar.gz'), '.'],
- check=True)
+ run_elbe(['control', 'get_files', '--pbuilder-only', prjdir], check=True)
except subprocess.CalledProcessError:
- print('tar Failed', file=sys.stderr)
- print('Giving up', file=sys.stderr)
- sys.exit(164)
+ print('elbe control get_files Failed', file=sys.stderr)
+ print('', file=sys.stderr)
+ print('dumping logfile', file=sys.stderr)
- for of in opt.origfile:
- print('')
- print(f"Pushing orig file '{of}' into pbuilder")
- print('')
try:
- run_elbe(['control', 'set_orig', prjdir, of], check=True)
+ run_elbe(['control', 'dump_file', prjdir, 'log.txt'], check=True)
except subprocess.CalledProcessError:
- print('elbe control set_orig Failed', file=sys.stderr)
+ print('elbe control dump_file Failed', file=sys.stderr)
+ print('', file=sys.stderr)
print('Giving up', file=sys.stderr)
- sys.exit(165)
+ sys.exit(168)
+
+ print('')
+ print(f"Get Files with: 'elbe control get_file {prjdir} <filename>'")
+ else:
print('')
- print('Pushing source into pbuilder')
+ print(f'Saving generated Files to {args.outdir}')
print('')
try:
- run_elbe([
- 'control', 'set_pdebuild',
- '--profile', opt.profile, *crossopt,
- prjdir, tmp.fname('pdebuild.tar.gz'),
- ], check=True)
- except subprocess.CalledProcessError:
- print('elbe control set_pdebuild Failed', file=sys.stderr)
- print('Giving up', file=sys.stderr)
- sys.exit(166)
- try:
- run_elbe(['control', 'wait_busy', prjdir], check=True)
+ run_elbe(['control', 'get_files', '--pbuilder-only',
+ '--output', args.outdir, prjdir], check=True)
except subprocess.CalledProcessError:
- print('elbe control wait_busy Failed', file=sys.stderr)
- print('Giving up', file=sys.stderr)
- sys.exit(167)
- print('')
- print('Pdebuild finished !')
- print('')
-
- if opt.skip_download:
- print('')
- print('Listing available files:')
- print('')
- try:
- run_elbe(['control', 'get_files', '--pbuilder-only', prjdir], check=True)
- except subprocess.CalledProcessError:
- print('elbe control get_files Failed', file=sys.stderr)
- print('', file=sys.stderr)
- print('dumping logfile', file=sys.stderr)
-
- try:
- run_elbe(['control', 'dump_file', prjdir, 'log.txt'], check=True)
- except subprocess.CalledProcessError:
- print('elbe control dump_file Failed', file=sys.stderr)
- print('', file=sys.stderr)
- print('Giving up', file=sys.stderr)
-
- sys.exit(168)
-
- print('')
- print(f"Get Files with: 'elbe control get_file {prjdir} <filename>'")
- else:
- print('')
- print(f'Saving generated Files to {opt.outdir}')
- print('')
+ print('elbe control get_files Failed', file=sys.stderr)
+ print('', file=sys.stderr)
+ print('dumping logfile', file=sys.stderr)
try:
- run_elbe(['control', 'get_files', '--pbuilder-only',
- '--output', opt.outdir, prjdir], check=True)
+ run_elbe(['control', 'dump_file', prjdir, 'log.txt'], check=True)
except subprocess.CalledProcessError:
- print('elbe control get_files Failed', file=sys.stderr)
+ print('elbe control dump_file Failed', file=sys.stderr)
print('', file=sys.stderr)
- print('dumping logfile', file=sys.stderr)
-
- try:
- run_elbe(['control', 'dump_file', prjdir, 'log.txt'], check=True)
- except subprocess.CalledProcessError:
- print('elbe control dump_file Failed', file=sys.stderr)
- print('', file=sys.stderr)
- print('Giving up', file=sys.stderr)
+ print('Giving up', file=sys.stderr)
- sys.exit(169)
+ sys.exit(169)
-PBuilderAction.register(BuildAction)
+pbuilder_actions = {
+ 'create': _create,
+ 'update': _update,
+ 'build': _build,
+}
--
2.45.2
More information about the elbe-devel
mailing list