diff options
Diffstat (limited to 'cliff/_argparse.py')
-rw-r--r-- | cliff/_argparse.py | 80 |
1 files changed, 78 insertions, 2 deletions
diff --git a/cliff/_argparse.py b/cliff/_argparse.py index e48dc79..5358e72 100644 --- a/cliff/_argparse.py +++ b/cliff/_argparse.py @@ -14,11 +14,14 @@ from __future__ import absolute_import from argparse import * # noqa +import argparse import sys +import warnings -if sys.version_info < (3, 5): - class ArgumentParser(ArgumentParser): # noqa +class ArgumentParser(argparse.ArgumentParser): + + if sys.version_info < (3, 5): def __init__(self, *args, **kwargs): self.allow_abbrev = kwargs.pop("allow_abbrev", True) super(ArgumentParser, self).__init__(*args, **kwargs) @@ -28,3 +31,76 @@ if sys.version_info < (3, 5): return super(ArgumentParser, self)._get_option_tuples( option_string) return () + + # NOTE(dhellmann): We have to override the methods for creating + # groups to return our objects that know how to deal with the + # special conflict handler. + + def add_argument_group(self, *args, **kwargs): + group = _ArgumentGroup(self, *args, **kwargs) + self._action_groups.append(group) + return group + + def add_mutually_exclusive_group(self, **kwargs): + group = _MutuallyExclusiveGroup(self, **kwargs) + self._mutually_exclusive_groups.append(group) + return group + + def _handle_conflict_ignore(self, action, conflicting_actions): + _handle_conflict_ignore( + self, + self._option_string_actions, + action, + conflicting_actions, + ) + + +def _handle_conflict_ignore(container, option_string_actions, + new_action, conflicting_actions): + + # Remember the option strings the new action starts with so we can + # restore them as part of error reporting if we need to. + original_option_strings = new_action.option_strings + + # Remove all of the conflicting option strings from the new action + # and report an error if none are left at the end. + for option_string, action in conflicting_actions: + + # remove the conflicting option from the new action + new_action.option_strings.remove(option_string) + warnings.warn( + ('Ignoring option string {} for new action ' + 'because it conflicts with an existing option.').format( + option_string)) + + # if the option now has no option string, remove it from the + # container holding it + if not new_action.option_strings: + new_action.option_strings = original_option_strings + raise argparse.ArgumentError( + new_action, + ('Cannot resolve conflicting option string, ' + 'all names conflict.'), + ) + + +class _ArgumentGroup(argparse._ArgumentGroup): + + def _handle_conflict_ignore(self, action, conflicting_actions): + _handle_conflict_ignore( + self, + self._option_string_actions, + action, + conflicting_actions, + ) + + +class _MutuallyExclusiveGroup(argparse._MutuallyExclusiveGroup): + + def _handle_conflict_ignore(self, action, conflicting_actions): + _handle_conflict_ignore( + self, + self._option_string_actions, + action, + conflicting_actions, + ) |