summaryrefslogtreecommitdiff
path: root/gitlab/v4/cli.py
diff options
context:
space:
mode:
authorJohn L. Villalovos <john@sodarock.com>2022-05-09 06:39:36 -0700
committerJohn L. Villalovos <john@sodarock.com>2022-05-09 06:39:36 -0700
commitf553fd3c79579ab596230edea5899dc5189b0ac6 (patch)
treee815d58e0964f42793e1fba9170f339a57a3b14d /gitlab/v4/cli.py
parent6b47c26d053fe352d68eb22a1eaf4b9a3c1c93e7 (diff)
downloadgitlab-f553fd3c79579ab596230edea5899dc5189b0ac6.tar.gz
fix: duplicate subparsers being added to argparse
Python 3.11 added an additional check in the argparse libary which detected duplicate subparsers being added. We had duplicate subparsers being added. Make sure we don't add duplicate subparsers. Closes: #2015
Diffstat (limited to 'gitlab/v4/cli.py')
-rw-r--r--gitlab/v4/cli.py25
1 files changed, 18 insertions, 7 deletions
diff --git a/gitlab/v4/cli.py b/gitlab/v4/cli.py
index 245897e..98430b9 100644
--- a/gitlab/v4/cli.py
+++ b/gitlab/v4/cli.py
@@ -200,11 +200,15 @@ def _populate_sub_parser_by_class(
mgr_cls_name = f"{cls.__name__}Manager"
mgr_cls = getattr(gitlab.v4.objects, mgr_cls_name)
+ action_parsers: Dict[str, argparse.ArgumentParser] = {}
for action_name in ["list", "get", "create", "update", "delete"]:
if not hasattr(mgr_cls, action_name):
continue
- sub_parser_action = sub_parser.add_parser(action_name)
+ sub_parser_action = sub_parser.add_parser(
+ action_name, conflict_handler="resolve"
+ )
+ action_parsers[action_name] = sub_parser_action
sub_parser_action.add_argument("--sudo", required=False)
if mgr_cls._from_parent_attrs:
for x in mgr_cls._from_parent_attrs:
@@ -268,7 +272,11 @@ def _populate_sub_parser_by_class(
if cls.__name__ in cli.custom_actions:
name = cls.__name__
for action_name in cli.custom_actions[name]:
- sub_parser_action = sub_parser.add_parser(action_name)
+ # NOTE(jlvillal): If we put a function for the `default` value of
+ # the `get` it will always get called, which will break things.
+ sub_parser_action = action_parsers.get(action_name)
+ if sub_parser_action is None:
+ sub_parser_action = sub_parser.add_parser(action_name)
# Get the attributes for URL/path construction
if mgr_cls._from_parent_attrs:
for x in mgr_cls._from_parent_attrs:
@@ -298,7 +306,11 @@ def _populate_sub_parser_by_class(
if mgr_cls.__name__ in cli.custom_actions:
name = mgr_cls.__name__
for action_name in cli.custom_actions[name]:
- sub_parser_action = sub_parser.add_parser(action_name)
+ # NOTE(jlvillal): If we put a function for the `default` value of
+ # the `get` it will always get called, which will break things.
+ sub_parser_action = action_parsers.get(action_name)
+ if sub_parser_action is None:
+ sub_parser_action = sub_parser.add_parser(action_name)
if mgr_cls._from_parent_attrs:
for x in mgr_cls._from_parent_attrs:
sub_parser_action.add_argument(
@@ -326,16 +338,15 @@ def extend_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
subparsers.required = True
# populate argparse for all Gitlab Object
- classes = []
+ classes = set()
for cls in gitlab.v4.objects.__dict__.values():
if not isinstance(cls, type):
continue
if issubclass(cls, gitlab.base.RESTManager):
if cls._obj_cls is not None:
- classes.append(cls._obj_cls)
- classes.sort(key=operator.attrgetter("__name__"))
+ classes.add(cls._obj_cls)
- for cls in classes:
+ for cls in sorted(classes, key=operator.attrgetter("__name__")):
arg_name = cli.cls_to_what(cls)
object_group = subparsers.add_parser(arg_name)