summaryrefslogtreecommitdiff
path: root/cliff/_argparse.py
diff options
context:
space:
mode:
Diffstat (limited to 'cliff/_argparse.py')
-rw-r--r--cliff/_argparse.py80
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,
+ )