@@ -856,12 +856,15 @@ class Command:
856
856
If enabled this will add ``--help`` as argument
857
857
if no arguments are passed
858
858
:param hidden: hide this command from help outputs.
859
-
860
- :param deprecated: issues a message indicating that
861
- the command is deprecated.
859
+ :param deprecated: If ``True`` or non-empty string, issues a message
860
+ indicating that the command is deprecated and highlights
861
+ its deprecation in --help. The message can be customized
862
+ by using a string as the value.
862
863
863
864
.. versionchanged:: 8.2
864
865
This is the base class for all commands, not ``BaseCommand``.
866
+ ``deprecated`` can be set to a string as well to customize the
867
+ deprecation message.
865
868
866
869
.. versionchanged:: 8.1
867
870
``help``, ``epilog``, and ``short_help`` are stored unprocessed,
@@ -905,7 +908,7 @@ def __init__(
905
908
add_help_option : bool = True ,
906
909
no_args_is_help : bool = False ,
907
910
hidden : bool = False ,
908
- deprecated : bool = False ,
911
+ deprecated : bool | str = False ,
909
912
) -> None :
910
913
#: the name the command thinks it has. Upon registering a command
911
914
#: on a :class:`Group` the group will default the command name
@@ -1059,7 +1062,14 @@ def get_short_help_str(self, limit: int = 45) -> str:
1059
1062
text = ""
1060
1063
1061
1064
if self .deprecated :
1062
- text = _ ("(Deprecated) {text}" ).format (text = text )
1065
+ deprecated_message = (
1066
+ f"(DEPRECATED: { self .deprecated } )"
1067
+ if isinstance (self .deprecated , str )
1068
+ else "(DEPRECATED)"
1069
+ )
1070
+ text = _ ("{text} {deprecated_message}" ).format (
1071
+ text = text , deprecated_message = deprecated_message
1072
+ )
1063
1073
1064
1074
return text .strip ()
1065
1075
@@ -1089,7 +1099,14 @@ def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None:
1089
1099
text = ""
1090
1100
1091
1101
if self .deprecated :
1092
- text = _ ("(Deprecated) {text}" ).format (text = text )
1102
+ deprecated_message = (
1103
+ f"(DEPRECATED: { self .deprecated } )"
1104
+ if isinstance (self .deprecated , str )
1105
+ else "(DEPRECATED)"
1106
+ )
1107
+ text = _ ("{text} {deprecated_message}" ).format (
1108
+ text = text , deprecated_message = deprecated_message
1109
+ )
1093
1110
1094
1111
if text :
1095
1112
formatter .write_paragraph ()
@@ -1183,9 +1200,13 @@ def invoke(self, ctx: Context) -> t.Any:
1183
1200
in the right way.
1184
1201
"""
1185
1202
if self .deprecated :
1203
+ extra_message = (
1204
+ f" { self .deprecated } " if isinstance (self .deprecated , str ) else ""
1205
+ )
1186
1206
message = _ (
1187
1207
"DeprecationWarning: The command {name!r} is deprecated."
1188
- ).format (name = self .name )
1208
+ "{extra_message}"
1209
+ ).format (name = self .name , extra_message = extra_message )
1189
1210
echo (style (message , fg = "red" ), err = True )
1190
1211
1191
1212
if self .callback is not None :
@@ -1988,6 +2009,18 @@ class Parameter:
1988
2009
given. Takes ``ctx, param, incomplete`` and must return a list
1989
2010
of :class:`~click.shell_completion.CompletionItem` or a list of
1990
2011
strings.
2012
+ :param deprecated: If ``True`` or non-empty string, issues a message
2013
+ indicating that the argument is deprecated and highlights
2014
+ its deprecation in --help. The message can be customized
2015
+ by using a string as the value. A deprecated parameter
2016
+ cannot be required, a ValueError will be raised otherwise.
2017
+
2018
+ .. versionchanged:: 8.2.0
2019
+ Introduction of ``deprecated``.
2020
+
2021
+ .. versionchanged:: 8.2
2022
+ Adding duplicate parameter names to a :class:`~click.core.Command` will
2023
+ result in a ``UserWarning`` being shown.
1991
2024
1992
2025
.. versionchanged:: 8.2
1993
2026
Adding duplicate parameter names to a :class:`~click.core.Command` will
@@ -2044,6 +2077,7 @@ def __init__(
2044
2077
[Context , Parameter , str ], list [CompletionItem ] | list [str ]
2045
2078
]
2046
2079
| None = None ,
2080
+ deprecated : bool | str = False ,
2047
2081
) -> None :
2048
2082
self .name : str | None
2049
2083
self .opts : list [str ]
@@ -2071,6 +2105,7 @@ def __init__(
2071
2105
self .metavar = metavar
2072
2106
self .envvar = envvar
2073
2107
self ._custom_shell_complete = shell_complete
2108
+ self .deprecated = deprecated
2074
2109
2075
2110
if __debug__ :
2076
2111
if self .type .is_composite and nargs != self .type .arity :
@@ -2113,6 +2148,13 @@ def __init__(
2113
2148
f"'default' { subject } must match nargs={ nargs } ."
2114
2149
)
2115
2150
2151
+ if required and deprecated :
2152
+ raise ValueError (
2153
+ f"The { self .param_type_name } '{ self .human_readable_name } ' "
2154
+ "is deprecated and still required. A deprecated "
2155
+ f"{ self .param_type_name } cannot be required."
2156
+ )
2157
+
2116
2158
def to_info_dict (self ) -> dict [str , t .Any ]:
2117
2159
"""Gather information that could be useful for a tool generating
2118
2160
user-facing documentation.
@@ -2332,6 +2374,29 @@ def handle_parse_result(
2332
2374
) -> tuple [t .Any , list [str ]]:
2333
2375
with augment_usage_errors (ctx , param = self ):
2334
2376
value , source = self .consume_value (ctx , opts )
2377
+
2378
+ if (
2379
+ self .deprecated
2380
+ and value is not None
2381
+ and source
2382
+ not in (
2383
+ ParameterSource .DEFAULT ,
2384
+ ParameterSource .DEFAULT_MAP ,
2385
+ )
2386
+ ):
2387
+ extra_message = (
2388
+ f" { self .deprecated } " if isinstance (self .deprecated , str ) else ""
2389
+ )
2390
+ message = _ (
2391
+ "DeprecationWarning: The {param_type} {name!r} is deprecated."
2392
+ "{extra_message}"
2393
+ ).format (
2394
+ param_type = self .param_type_name ,
2395
+ name = self .human_readable_name ,
2396
+ extra_message = extra_message ,
2397
+ )
2398
+ echo (style (message , fg = "red" ), err = True )
2399
+
2335
2400
ctx .set_parameter_source (self .name , source ) # type: ignore
2336
2401
2337
2402
try :
@@ -2402,7 +2467,8 @@ class Option(Parameter):
2402
2467
Normally, environment variables are not shown.
2403
2468
:param prompt: If set to ``True`` or a non empty string then the
2404
2469
user will be prompted for input. If set to ``True`` the prompt
2405
- will be the option name capitalized.
2470
+ will be the option name capitalized. A deprecated option cannot be
2471
+ prompted.
2406
2472
:param confirmation_prompt: Prompt a second time to confirm the
2407
2473
value if it was prompted for. Can be set to a string instead of
2408
2474
``True`` to customize the message.
@@ -2469,13 +2535,16 @@ def __init__(
2469
2535
hidden : bool = False ,
2470
2536
show_choices : bool = True ,
2471
2537
show_envvar : bool = False ,
2538
+ deprecated : bool | str = False ,
2472
2539
** attrs : t .Any ,
2473
2540
) -> None :
2474
2541
if help :
2475
2542
help = inspect .cleandoc (help )
2476
2543
2477
2544
default_is_missing = "default" not in attrs
2478
- super ().__init__ (param_decls , type = type , multiple = multiple , ** attrs )
2545
+ super ().__init__ (
2546
+ param_decls , type = type , multiple = multiple , deprecated = deprecated , ** attrs
2547
+ )
2479
2548
2480
2549
if prompt is True :
2481
2550
if self .name is None :
@@ -2487,6 +2556,14 @@ def __init__(
2487
2556
else :
2488
2557
prompt_text = prompt
2489
2558
2559
+ if deprecated :
2560
+ deprecated_message = (
2561
+ f"(DEPRECATED: { deprecated } )"
2562
+ if isinstance (deprecated , str )
2563
+ else "(DEPRECATED)"
2564
+ )
2565
+ help = help + deprecated_message if help is not None else deprecated_message
2566
+
2490
2567
self .prompt = prompt_text
2491
2568
self .confirmation_prompt = confirmation_prompt
2492
2569
self .prompt_required = prompt_required
@@ -2548,6 +2625,9 @@ def __init__(
2548
2625
self .show_envvar = show_envvar
2549
2626
2550
2627
if __debug__ :
2628
+ if deprecated and prompt :
2629
+ raise ValueError ("`deprecated` options cannot use `prompt`." )
2630
+
2551
2631
if self .nargs == - 1 :
2552
2632
raise TypeError ("nargs=-1 is not supported for options." )
2553
2633
@@ -2983,6 +3063,8 @@ def make_metavar(self) -> str:
2983
3063
var = self .type .get_metavar (self )
2984
3064
if not var :
2985
3065
var = self .name .upper () # type: ignore
3066
+ if self .deprecated :
3067
+ var += "!"
2986
3068
if not self .required :
2987
3069
var = f"[{ var } ]"
2988
3070
if self .nargs != 1 :
0 commit comments