diff --git a/CHANGES.rst b/CHANGES.rst index f46e760b1f..cf24100645 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -57,6 +57,10 @@ Unreleased ``hide_input=True`` fails validation, instead of always showing a generic message. Built-in type messages mask the input value. :issue:`2809` :pr:`3256` +- Fix missing space between option help text and the ``(DEPRECATED)`` + label, and localize the option label so it matches the command label. + The label and the ``DeprecationWarning`` reason suffix are now produced + by shared helpers. :pr:`3423` - Document short option stacking (``-abc`` is parsed as ``-a -b -c``) and clarify that multi-character short option names are not supported. :issue:`2779` :pr:`3431` diff --git a/src/click/core.py b/src/click/core.py index 08669d784c..ac62ae9bfb 100644 --- a/src/click/core.py +++ b/src/click/core.py @@ -93,6 +93,23 @@ def _check_nested_chain( raise RuntimeError(message) +def _format_deprecated_label(deprecated: bool | str) -> str: + """Return the parenthesized deprecation label shown in help text.""" + label = _("deprecated").upper() + if isinstance(deprecated, str): + return f"({label}: {deprecated})" + return f"({label})" + + +def _format_deprecated_suffix(deprecated: bool | str) -> str: + """Return the trailing reason for a ``DeprecationWarning`` message, + prefixed with a space, or an empty string when no reason was given. + """ + if isinstance(deprecated, str): + return f" {deprecated}" + return "" + + def batch(iterable: cabc.Iterable[V], batch_size: int) -> list[tuple[V, ...]]: return list(zip(*repeat(iter(iterable), batch_size), strict=False)) @@ -1136,13 +1153,7 @@ def get_short_help_str(self, limit: int = 45) -> str: text = "" if self.deprecated: - localised_deprectated = _("deprecated").upper() - deprecated_message = ( - f"({localised_deprectated}: {self.deprecated})" - if isinstance(self.deprecated, str) - else f"({localised_deprectated})" - ) - text = f"{_(text)} {deprecated_message}" + text = f"{_(text)} {_format_deprecated_label(self.deprecated)}" return text.strip() @@ -1172,13 +1183,7 @@ def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: text = "" if self.deprecated: - localised_deprectated = _("deprecated").upper() - deprecated_message = ( - f"({localised_deprectated}: {self.deprecated})" - if isinstance(self.deprecated, str) - else f"({localised_deprectated})" - ) - text = f"{_(text)} {deprecated_message}" + text = f"{_(text)} {_format_deprecated_label(self.deprecated)}" if text: formatter.write_paragraph() @@ -1285,12 +1290,12 @@ def invoke(self, ctx: Context) -> t.Any: in the right way. """ if self.deprecated: - extra_message = ( - f" {self.deprecated}" if isinstance(self.deprecated, str) else "" - ) message = _( "DeprecationWarning: The command {name!r} is deprecated.{extra_message}" - ).format(name=self.name, extra_message=extra_message) + ).format( + name=self.name, + extra_message=_format_deprecated_suffix(self.deprecated), + ) echo(style(message, fg="red"), err=True) if self.callback is not None: @@ -2592,16 +2597,13 @@ def handle_parse_result( and value is not UNSET and source < ParameterSource.DEFAULT_MAP ): - extra_message = ( - f" {self.deprecated}" if isinstance(self.deprecated, str) else "" - ) message = _( "DeprecationWarning: The {param_type} {name!r} is deprecated." "{extra_message}" ).format( param_type=self.param_type_name, name=self.human_readable_name, - extra_message=extra_message, + extra_message=_format_deprecated_suffix(self.deprecated), ) echo(style(message, fg="red"), err=True) @@ -2781,16 +2783,8 @@ def __init__( prompt_text = prompt if deprecated: - deprecated_message = ( - f"(DEPRECATED: {deprecated})" - if isinstance(deprecated, str) - else "(DEPRECATED)" - ) - help = ( - f"{help} {deprecated_message}" - if help is not None - else deprecated_message - ) + label = _format_deprecated_label(deprecated) + help = f"{help} {label}" if help is not None else label self.prompt = prompt_text self.confirmation_prompt = confirmation_prompt