diff options
author | Paul Eggleton <paul.eggleton@linux.intel.com> | 2015-12-22 17:03:08 +1300 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-12-22 16:44:03 +0000 |
commit | 98fd5de373e16fe5d69a3065f844efc8037385bc (patch) | |
tree | 6f893fa92729821a83126e76e1546ed070bed7ad /scripts/lib | |
parent | c0754d672966901f22dff1bcd40bbd08d1219c7a (diff) | |
download | openembedded-core-98fd5de373e16fe5d69a3065f844efc8037385bc.tar.gz openembedded-core-98fd5de373e16fe5d69a3065f844efc8037385bc.tar.bz2 openembedded-core-98fd5de373e16fe5d69a3065f844efc8037385bc.zip |
scripts/lib/argparse_oe: handle intermixing of optional positional arguments
Python's argparse module can't handle when several optional positional
arguments (set with nargs='?') are intermixed with other options. If the
positional arguments aren't optional then this isn't an issue; thus when
changing positional arguments to optional (as we are doing with devtool)
we need this workaround.
This is a pretty horrible hack, but we don't want this flexibility of
ordering to disappear simply because we made some arguments optional.
Unfortunately the corresponding bug remains unresolved upstream even in
Python 3, and argparse is not really designed to be subclassed so it
doesn't make things like this easy.
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib')
-rw-r--r-- | scripts/lib/argparse_oe.py | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/scripts/lib/argparse_oe.py b/scripts/lib/argparse_oe.py index c2fee6de05..ec7eb8d191 100644 --- a/scripts/lib/argparse_oe.py +++ b/scripts/lib/argparse_oe.py @@ -9,3 +9,42 @@ class ArgumentParser(argparse.ArgumentParser): self.print_help() sys.exit(2) + def add_subparsers(self, *args, **kwargs): + ret = super(ArgumentParser, self).add_subparsers(*args, **kwargs) + ret._parser_class = ArgumentSubParser + return ret + +class ArgumentSubParser(ArgumentParser): + def parse_known_args(self, args=None, namespace=None): + # This works around argparse not handling optional positional arguments being + # intermixed with other options. A pretty horrible hack, but we're not left + # with much choice given that the bug in argparse exists and it's difficult + # to subclass. + # Borrowed from http://stackoverflow.com/questions/20165843/argparse-how-to-handle-variable-number-of-arguments-nargs + # with an extra workaround (in format_help() below) for the positional + # arguments disappearing from the --help output, as well as structural tweaks. + # Originally simplified from http://bugs.python.org/file30204/test_intermixed.py + positionals = self._get_positional_actions() + for action in positionals: + # deactivate positionals + action.save_nargs = action.nargs + action.nargs = 0 + + namespace, remaining_args = super(ArgumentSubParser, self).parse_known_args(args, namespace) + for action in positionals: + # remove the empty positional values from namespace + if hasattr(namespace, action.dest): + delattr(namespace, action.dest) + for action in positionals: + action.nargs = action.save_nargs + # parse positionals + namespace, extras = super(ArgumentSubParser, self).parse_known_args(remaining_args, namespace) + return namespace, extras + + def format_help(self): + # Quick, restore the positionals! + positionals = self._get_positional_actions() + for action in positionals: + if hasattr(action, 'save_nargs'): + action.nargs = action.save_nargs + return super(ArgumentParser, self).format_help() |