From 76acdfdf8707868d4666970818e5c370077d2889 Mon Sep 17 00:00:00 2001 From: Andreas Backx Date: Sat, 2 Nov 2024 22:25:19 +0000 Subject: [PATCH] Command.deprecated can be a string to customize the message. --- src/click/core.py | 35 ++++++++++++++++++++++++++++------- tests/test_commands.py | 18 +++++++++++++----- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/click/core.py b/src/click/core.py index 0481ec333..a8ecbc76d 100644 --- a/src/click/core.py +++ b/src/click/core.py @@ -848,12 +848,15 @@ class Command: If enabled this will add ``--help`` as argument if no arguments are passed :param hidden: hide this command from help outputs. - - :param deprecated: issues a message indicating that - the command is deprecated. + :param deprecated: If ``True`` or non-empty string, issues a message + indicating that the command is deprecated and highlights + its deprecation in --help. The message can be customized + by using a string as the value. .. versionchanged:: 8.2 This is the base class for all commands, not ``BaseCommand``. + ``deprecated`` can be set to a string as well to customize the + deprecation message. .. versionchanged:: 8.1 ``help``, ``epilog``, and ``short_help`` are stored unprocessed, @@ -897,7 +900,7 @@ def __init__( add_help_option: bool = True, no_args_is_help: bool = False, hidden: bool = False, - deprecated: bool = False, + deprecated: bool | str = False, ) -> None: #: the name the command thinks it has. Upon registering a command #: on a :class:`Group` the group will default the command name @@ -1035,7 +1038,14 @@ def get_short_help_str(self, limit: int = 45) -> str: text = "" if self.deprecated: - text = _("(Deprecated) {text}").format(text=text) + deprecated_message = ( + f"(DEPRECATED: {self.deprecated})" + if isinstance(self.deprecated, str) + else "(DEPRECATED)" + ) + text = _("{text} {deprecated_message}").format( + text=text, deprecated_message=deprecated_message + ) return text.strip() @@ -1065,7 +1075,14 @@ def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: text = "" if self.deprecated: - text = _("(Deprecated) {text}").format(text=text) + deprecated_message = ( + f"(DEPRECATED: {self.deprecated})" + if isinstance(self.deprecated, str) + else "(DEPRECATED)" + ) + text = _("{text} {deprecated_message}").format( + text=text, deprecated_message=deprecated_message + ) if text: formatter.write_paragraph() @@ -1160,9 +1177,13 @@ 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." - ).format(name=self.name) + "{extra_message}" + ).format(name=self.name, extra_message=extra_message) echo(style(message, fg="red"), err=True) if self.callback is not None: diff --git a/tests/test_commands.py b/tests/test_commands.py index 5a56799ad..fc13b2fc7 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -322,23 +322,31 @@ def cli(verbose, args): @pytest.mark.parametrize("doc", ["CLI HELP", None]) -def test_deprecated_in_help_messages(runner, doc): - @click.command(deprecated=True, help=doc) +@pytest.mark.parametrize("deprecated", [True, "USE OTHER COMMAND INSTEAD"]) +def test_deprecated_in_help_messages(runner, doc, deprecated): + @click.command(deprecated=deprecated, help=doc) def cli(): pass result = runner.invoke(cli, ["--help"]) - assert "(Deprecated)" in result.output + assert "(DEPRECATED" in result.output + if isinstance(deprecated, str): + assert deprecated in result.output -def test_deprecated_in_invocation(runner): - @click.command(deprecated=True) + +@pytest.mark.parametrize("deprecated", [True, "USE OTHER COMMAND INSTEAD"]) +def test_deprecated_in_invocation(runner, deprecated): + @click.command(deprecated=deprecated) def deprecated_cmd(): pass result = runner.invoke(deprecated_cmd) assert "DeprecationWarning:" in result.output + if isinstance(deprecated, str): + assert deprecated in result.output + def test_command_parse_args_collects_option_prefixes(): @click.command()