Skip to content

Commit

Permalink
Deduplicate help option definition
Browse files Browse the repository at this point in the history
  • Loading branch information
kdeldycke committed Feb 23, 2024
1 parent cab9483 commit e436986
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 35 deletions.
1 change: 1 addition & 0 deletions src/click/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .decorators import confirmation_option as confirmation_option
from .decorators import group as group
from .decorators import help_option as help_option
from .decorators import HelpOption as HelpOption
from .decorators import make_pass_decorator as make_pass_decorator
from .decorators import option as option
from .decorators import pass_context as pass_context
Expand Down
22 changes: 8 additions & 14 deletions src/click/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -989,25 +989,19 @@ def get_help_option_names(self, ctx: Context) -> list[str]:
return list(all_names)

def get_help_option(self, ctx: Context) -> Option | None:
"""Returns the help option object."""
"""Returns the help option object.
Unless ``add_help_option`` is ``False``.
"""
help_options = self.get_help_option_names(ctx)

if not help_options or not self.add_help_option:
return None

def show_help(ctx: Context, param: Parameter, value: str) -> None:
if value and not ctx.resilient_parsing:
echo(ctx.get_help(), color=ctx.color)
ctx.exit()

return Option(
help_options,
is_flag=True,
is_eager=True,
expose_value=False,
callback=show_help,
help=_("Show this message and exit."),
)
# Avoid circular import.
from .decorators import HelpOption

return HelpOption(help_options)

def make_parser(self, ctx: Context) -> _OptionParser:
"""Creates the underlying option parser for this command."""
Expand Down
52 changes: 31 additions & 21 deletions src/click/decorators.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import collections.abc as cabc
import inspect
import typing as t
from functools import update_wrapper
Expand Down Expand Up @@ -532,32 +533,41 @@ def callback(ctx: Context, param: Parameter, value: bool) -> None:
return option(*param_decls, **kwargs)


def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]:
"""Add a ``--help`` option which immediately prints the help page
class HelpOption(Option):
"""Pre-configured ``--help`` option which immediately prints the help page
and exits the program.
"""

This is usually unnecessary, as the ``--help`` option is added to
each command automatically unless ``add_help_option=False`` is
passed.
def __init__(
self,
param_decls: cabc.Sequence[str] | None = None,
**kwargs: t.Any,
) -> None:
if not param_decls:
param_decls = ("--help",)

:param param_decls: One or more option names. Defaults to the single
value ``"--help"``.
:param kwargs: Extra arguments are passed to :func:`option`.
"""
kwargs.setdefault("is_flag", True)
kwargs.setdefault("expose_value", False)
kwargs.setdefault("is_eager", True)
kwargs.setdefault("help", _("Show this message and exit."))
kwargs.setdefault("callback", self.show_help)

def callback(ctx: Context, param: Parameter, value: bool) -> None:
if not value or ctx.resilient_parsing:
return
super().__init__(param_decls, **kwargs)

echo(ctx.get_help(), color=ctx.color)
ctx.exit()
@staticmethod
def show_help(ctx: Context, param: Parameter, value: bool) -> None:
"""Callback that print the help page on ``<stdout>`` and exits."""
if value and not ctx.resilient_parsing:
echo(ctx.get_help(), color=ctx.color)
ctx.exit()

if not param_decls:
param_decls = ("--help",)

kwargs.setdefault("is_flag", True)
kwargs.setdefault("expose_value", False)
kwargs.setdefault("is_eager", True)
kwargs.setdefault("help", _("Show this message and exit."))
kwargs["callback"] = callback
def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]:
"""Decorator for the pre-configured ``--help`` option defined above.
:param param_decls: One or more option names. Defaults to the single
value ``"--help"``.
:param kwargs: Extra arguments are passed to :func:`option`.
"""
kwargs.setdefault("cls", HelpOption)
return option(*param_decls, **kwargs)

0 comments on commit e436986

Please sign in to comment.