Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/1267.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed `pulp --help` not showing all available commands.
21 changes: 19 additions & 2 deletions src/pulp_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pulp_glue.common.i18n import get_translation

from pulp_cli.config import CONFIG_LOCATIONS, config, config_options, validate_config
from pulp_cli.generic import PulpCLIContext, pulp_group
from pulp_cli.generic import PulpCLIContext, PulpGroup

if sys.version_info >= (3, 11):
import tomllib
Expand Down Expand Up @@ -60,6 +60,23 @@ def load_plugins(
PROFILE_KEY = f"{__name__}.profile"


class MainPulpGroup(PulpGroup):
"""PulpGroup subclass for the main CLI entry point.

Ensures plugins are loaded before help is displayed. This is needed because
Click's ``iter_params_for_processing`` sorts eager parameters by invocation
order, so ``--help`` (which is on the command line) gets processed before
``--config`` and ``--profile`` (which are not). This causes ``--help`` to
exit before the plugin-loading callbacks ever fire, resulting in a help page
that only shows directly-registered commands.
"""

def format_help(self, ctx: click.Context, formatter: click.HelpFormatter) -> None:
if PLUGIN_KEY not in ctx.meta:
ctx.meta[PLUGIN_KEY] = load_plugins()
super().format_help(ctx, formatter)


# config and config-profile need to be combined in order to fetch the desired defaults.
# Click will call both these callbacks exactly once, but we cannot know the order.
# Therefore whichever one has seen the that the other deposited it's value will coninue with
Expand Down Expand Up @@ -183,7 +200,7 @@ def _version_callback(ctx: click.Context, param: t.Any, value: bool) -> None:
),
)
@config_options
@pulp_group(no_args_is_help=False)
@click.group(cls=MainPulpGroup, no_args_is_help=False)
@click.pass_context
def main(
ctx: click.Context,
Expand Down
8 changes: 8 additions & 0 deletions tests/test_help_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ def test_accessing_the_help_page_does_not_invoke_api(
assert result.stdout.startswith("Usage:") or result.stdout.startswith("DeprecationWarning:")


def test_help_shows_all_available_commands(no_api: None) -> None:
runner = CliRunner()
result = runner.invoke(main, ["--help"], catch_exceptions=False)
assert result.exit_code == 0
for command in main.commands.keys():
assert command in result.stdout


@pytest.mark.parametrize(
"command,options",
[
Expand Down
Loading