Skip to content

Commit 9acd2d2

Browse files
JohnVillalovosnejch
authored andcommitted
fix: add ability to add help to custom_actions
Now when registering a custom_action can add help text if desired. Also delete the VerticalHelpFormatter as no longer needed. When the help value is set to `None` or some other value, the actions will get printed vertically. Before when the help value was not set the actions would all get put onto one line.
1 parent 18aa1fc commit 9acd2d2

File tree

3 files changed

+12
-34
lines changed

3 files changed

+12
-34
lines changed

gitlab/cli.py

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import pathlib
66
import re
77
import sys
8-
import textwrap
98
from types import ModuleType
109
from typing import (
1110
Any,
@@ -37,11 +36,12 @@ class CustomAction:
3736
optional: Tuple[str, ...]
3837
in_object: bool
3938
requires_id: bool # if the `_id_attr` value should be a required argument
39+
help: Optional[str] # help text for the custom action
4040

4141

4242
# custom_actions = {
4343
# cls: {
44-
# action: (mandatory_args, optional_args, in_obj),
44+
# action: CustomAction,
4545
# },
4646
# }
4747
custom_actions: Dict[str, Dict[str, CustomAction]] = {}
@@ -54,40 +54,14 @@ class CustomAction:
5454
__F = TypeVar("__F", bound=Callable[..., Any])
5555

5656

57-
class VerticalHelpFormatter(argparse.HelpFormatter):
58-
def format_help(self) -> str:
59-
result = super().format_help()
60-
output = ""
61-
indent = self._indent_increment * " "
62-
for line in result.splitlines(keepends=True):
63-
# All of our resources are on one line and wrapped inside braces.
64-
# For example: {application,resource1,resource2}
65-
# except if there are fewer resources - then the line and help text
66-
# are collapsed on the same line.
67-
# For example: {list} Action to execute on the GitLab resource.
68-
# We then put each resource on its own line to make it easier to read.
69-
if line.strip().startswith("{"):
70-
choice_string, help_string = line.split("}", 1)
71-
choice_list = choice_string.strip(" {").split(",")
72-
help_string = help_string.strip()
73-
74-
if help_string:
75-
help_indent = len(max(choice_list, key=len)) * " "
76-
choice_list.append(f"{help_indent} {help_string}")
77-
78-
choices = "\n".join(choice_list)
79-
line = f"{textwrap.indent(choices, indent)}\n"
80-
output += line
81-
return output
82-
83-
8457
def register_custom_action(
8558
*,
8659
cls_names: Union[str, Tuple[str, ...]],
8760
required: Tuple[str, ...] = (),
8861
optional: Tuple[str, ...] = (),
8962
custom_action: Optional[str] = None,
9063
requires_id: bool = True, # if the `_id_attr` value should be a required argument
64+
help: Optional[str] = None, # help text for the action
9165
) -> Callable[[__F], __F]:
9266
def wrap(f: __F) -> __F:
9367
@functools.wraps(f)
@@ -115,6 +89,7 @@ def wrapped_f(*args: Any, **kwargs: Any) -> Any:
11589
optional=optional,
11690
in_object=in_obj,
11791
requires_id=requires_id,
92+
help=help,
11893
)
11994

12095
return cast(__F, wrapped_f)

gitlab/v4/cli.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,11 +300,14 @@ def _populate_sub_parser_by_class(
300300
if cls.__name__ in cli.custom_actions:
301301
name = cls.__name__
302302
for action_name in cli.custom_actions[name]:
303+
custom_action = cli.custom_actions[name][action_name]
303304
# NOTE(jlvillal): If we put a function for the `default` value of
304305
# the `get` it will always get called, which will break things.
305306
action_parser = action_parsers.get(action_name)
306307
if action_parser is None:
307-
sub_parser_action = sub_parser.add_parser(action_name)
308+
sub_parser_action = sub_parser.add_parser(
309+
action_name, help=custom_action.help
310+
)
308311
else:
309312
sub_parser_action = action_parser
310313
# Get the attributes for URL/path construction
@@ -315,7 +318,6 @@ def _populate_sub_parser_by_class(
315318
)
316319
sub_parser_action.add_argument("--sudo", required=False)
317320

318-
custom_action = cli.custom_actions[name][action_name]
319321
# We need to get the object somehow
320322
if not issubclass(cls, gitlab.mixins.GetWithoutIdMixin):
321323
if cls._id_attr is not None and custom_action.requires_id:
@@ -386,7 +388,6 @@ def extend_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
386388
mgr_cls = getattr(gitlab.v4.objects, mgr_cls_name)
387389
object_group = subparsers.add_parser(
388390
arg_name,
389-
formatter_class=cli.VerticalHelpFormatter,
390391
help=f"API endpoint: {mgr_cls._path}",
391392
)
392393

tests/functional/cli/test_cli.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ def test_config_error_with_help_prints_help(script_runner):
3636

3737
def test_resource_help_prints_actions_vertically(script_runner):
3838
ret = script_runner.run(["gitlab", "project", "--help"])
39-
assert """action:\n list\n get""" in ret.stdout
39+
assert " list List the GitLab resources\n" in ret.stdout
40+
assert " get Get a GitLab resource\n" in ret.stdout
4041
assert ret.returncode == 0
4142

4243

4344
def test_resource_help_prints_actions_vertically_only_one_action(script_runner):
4445
ret = script_runner.run(["gitlab", "event", "--help"])
45-
assert """action:\n list\n""" in ret.stdout
46+
assert " {list} Action to execute on the GitLab resource.\n"
47+
assert " list List the GitLab resources\n" in ret.stdout
4648
assert ret.returncode == 0
4749

4850

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy