Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7e56ab1

Browse files
serhiy-storchakafsc-eriker
authored andcommitted
pythongh-83648: Support deprecation of options, arguments and subcommands in argparse (pythonGH-114086)
1 parent7f2fa48 commit7e56ab1

File tree

5 files changed

+262
-27
lines changed

5 files changed

+262
-27
lines changed

‎Doc/library/argparse.rst

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,8 @@ The add_argument() method
777777
*dest_ - The name of the attribute to be added to the object returned by
778778
:meth:`parse_args`.
779779

780+
*deprecated_ - Whether or not use of the argument is deprecated.
781+
780782
The following sections describe how each of these are used.
781783

782784

@@ -1439,6 +1441,34 @@ behavior::
14391441
>>> parser.parse_args('--foo XXX'.split())
14401442
Namespace(bar='XXX')
14411443

1444+
1445+
.. _deprecated:
1446+
1447+
deprecated
1448+
^^^^^^^^^^
1449+
1450+
During a project's lifetime, some arguments may need to be removed from the
1451+
command line. Before removing them, you should inform
1452+
your users that the arguments are deprecated and will be removed.
1453+
The ``deprecated`` keyword argument of
1454+
:meth:`~ArgumentParser.add_argument`, which defaults to ``False``,
1455+
specifies if the argument is deprecated and will be removed
1456+
in the future.
1457+
For arguments, if ``deprecated`` is ``True``, then a warning will be
1458+
printed to standard error when the argument is used::
1459+
1460+
>>> import argparse
1461+
>>> parser = argparse.ArgumentParser(prog='snake.py')
1462+
>>> parser.add_argument('--legs', default=0, type=int, deprecated=True)
1463+
>>> parser.parse_args([])
1464+
Namespace(legs=0)
1465+
>>> parser.parse_args(['--legs', '4']) # doctest: +SKIP
1466+
snake.py: warning: option '--legs' is deprecated
1467+
Namespace(legs=4)
1468+
1469+
..versionchanged::3.13
1470+
1471+
14421472
Action classes
14431473
^^^^^^^^^^^^^^
14441474

@@ -1842,7 +1872,8 @@ Sub-commands
18421872

18431873
{foo,bar} additional help
18441874

1845-
Furthermore, ``add_parser`` supports an additional ``aliases`` argument,
1875+
Furthermore,:meth:`~_SubParsersAction.add_parser` supports an additional
1876+
*aliases* argument,
18461877
which allows multiple strings to refer to the same subparser. This example,
18471878
like ``svn``, aliases ``co`` as a shorthand for ``checkout``::
18481879

@@ -1853,6 +1884,20 @@ Sub-commands
18531884
>>> parser.parse_args(['co', 'bar'])
18541885
Namespace(foo='bar')
18551886

1887+
:meth:`~_SubParsersAction.add_parser` supports also an additional
1888+
*deprecated* argument, which allows to deprecate the subparser.
1889+
1890+
>>>import argparse
1891+
>>>parser= argparse.ArgumentParser(prog='chicken.py')
1892+
>>>subparsers= parser.add_subparsers()
1893+
>>>run= subparsers.add_parser('run')
1894+
>>>fly= subparsers.add_parser('fly',deprecated=True)
1895+
>>>parser.parse_args(['fly'])# doctest: +SKIP
1896+
chicken.py: warning: command 'fly' is deprecated
1897+
Namespace()
1898+
1899+
..versionadded::3.13
1900+
18561901
One particularly effective way of handling sub-commands is to combine the use
18571902
of the:meth:`add_subparsers` method with calls to:meth:`set_defaults` so
18581903
that each subparser knows which Python function it should execute. For

‎Doc/whatsnew/3.13.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,15 @@ New Modules
169169
Improved Modules
170170
================
171171

172+
argparse
173+
--------
174+
175+
* Add parameter *deprecated* in methods
176+
:meth:`~argparse.ArgumentParser.add_argument` and:meth:`!add_parser`
177+
which allows to deprecate command-line options, positional arguments and
178+
subcommands.
179+
(Contributed by Serhiy Storchaka in:gh:`83648`).
180+
172181
array
173182
-----
174183

‎Lib/argparse.py

Lines changed: 68 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,8 @@ def __init__(self,
843843
choices=None,
844844
required=False,
845845
help=None,
846-
metavar=None):
846+
metavar=None,
847+
deprecated=False):
847848
self.option_strings=option_strings
848849
self.dest=dest
849850
self.nargs=nargs
@@ -854,6 +855,7 @@ def __init__(self,
854855
self.required=required
855856
self.help=help
856857
self.metavar=metavar
858+
self.deprecated=deprecated
857859

858860
def_get_kwargs(self):
859861
names= [
@@ -867,6 +869,7 @@ def _get_kwargs(self):
867869
'required',
868870
'help',
869871
'metavar',
872+
'deprecated',
870873
]
871874
return [(name,getattr(self,name))fornameinnames]
872875

@@ -889,7 +892,8 @@ def __init__(self,
889892
choices=_deprecated_default,
890893
required=False,
891894
help=None,
892-
metavar=_deprecated_default):
895+
metavar=_deprecated_default,
896+
deprecated=False):
893897

894898
_option_strings= []
895899
foroption_stringinoption_strings:
@@ -927,7 +931,8 @@ def __init__(self,
927931
choices=choices,
928932
required=required,
929933
help=help,
930-
metavar=metavar)
934+
metavar=metavar,
935+
deprecated=deprecated)
931936

932937

933938
def__call__(self,parser,namespace,values,option_string=None):
@@ -950,7 +955,8 @@ def __init__(self,
950955
choices=None,
951956
required=False,
952957
help=None,
953-
metavar=None):
958+
metavar=None,
959+
deprecated=False):
954960
ifnargs==0:
955961
raiseValueError('nargs for store actions must be != 0; if you '
956962
'have nothing to store, actions such as store '
@@ -967,7 +973,8 @@ def __init__(self,
967973
choices=choices,
968974
required=required,
969975
help=help,
970-
metavar=metavar)
976+
metavar=metavar,
977+
deprecated=deprecated)
971978

972979
def__call__(self,parser,namespace,values,option_string=None):
973980
setattr(namespace,self.dest,values)
@@ -982,15 +989,17 @@ def __init__(self,
982989
default=None,
983990
required=False,
984991
help=None,
985-
metavar=None):
992+
metavar=None,
993+
deprecated=False):
986994
super(_StoreConstAction,self).__init__(
987995
option_strings=option_strings,
988996
dest=dest,
989997
nargs=0,
990998
const=const,
991999
default=default,
9921000
required=required,
993-
help=help)
1001+
help=help,
1002+
deprecated=deprecated)
9941003

9951004
def__call__(self,parser,namespace,values,option_string=None):
9961005
setattr(namespace,self.dest,self.const)
@@ -1003,14 +1012,16 @@ def __init__(self,
10031012
dest,
10041013
default=False,
10051014
required=False,
1006-
help=None):
1015+
help=None,
1016+
deprecated=False):
10071017
super(_StoreTrueAction,self).__init__(
10081018
option_strings=option_strings,
10091019
dest=dest,
10101020
const=True,
1011-
default=default,
1021+
deprecated=deprecated,
10121022
required=required,
1013-
help=help)
1023+
help=help,
1024+
default=default)
10141025

10151026

10161027
class_StoreFalseAction(_StoreConstAction):
@@ -1020,14 +1031,16 @@ def __init__(self,
10201031
dest,
10211032
default=True,
10221033
required=False,
1023-
help=None):
1034+
help=None,
1035+
deprecated=False):
10241036
super(_StoreFalseAction,self).__init__(
10251037
option_strings=option_strings,
10261038
dest=dest,
10271039
const=False,
10281040
default=default,
10291041
required=required,
1030-
help=help)
1042+
help=help,
1043+
deprecated=deprecated)
10311044

10321045

10331046
class_AppendAction(Action):
@@ -1042,7 +1055,8 @@ def __init__(self,
10421055
choices=None,
10431056
required=False,
10441057
help=None,
1045-
metavar=None):
1058+
metavar=None,
1059+
deprecated=False):
10461060
ifnargs==0:
10471061
raiseValueError('nargs for append actions must be != 0; if arg '
10481062
'strings are not supplying the value to append, '
@@ -1059,7 +1073,8 @@ def __init__(self,
10591073
choices=choices,
10601074
required=required,
10611075
help=help,
1062-
metavar=metavar)
1076+
metavar=metavar,
1077+
deprecated=deprecated)
10631078

10641079
def__call__(self,parser,namespace,values,option_string=None):
10651080
items=getattr(namespace,self.dest,None)
@@ -1077,7 +1092,8 @@ def __init__(self,
10771092
default=None,
10781093
required=False,
10791094
help=None,
1080-
metavar=None):
1095+
metavar=None,
1096+
deprecated=False):
10811097
super(_AppendConstAction,self).__init__(
10821098
option_strings=option_strings,
10831099
dest=dest,
@@ -1086,7 +1102,8 @@ def __init__(self,
10861102
default=default,
10871103
required=required,
10881104
help=help,
1089-
metavar=metavar)
1105+
metavar=metavar,
1106+
deprecated=deprecated)
10901107

10911108
def__call__(self,parser,namespace,values,option_string=None):
10921109
items=getattr(namespace,self.dest,None)
@@ -1102,14 +1119,16 @@ def __init__(self,
11021119
dest,
11031120
default=None,
11041121
required=False,
1105-
help=None):
1122+
help=None,
1123+
deprecated=False):
11061124
super(_CountAction,self).__init__(
11071125
option_strings=option_strings,
11081126
dest=dest,
11091127
nargs=0,
11101128
default=default,
11111129
required=required,
1112-
help=help)
1130+
help=help,
1131+
deprecated=deprecated)
11131132

11141133
def__call__(self,parser,namespace,values,option_string=None):
11151134
count=getattr(namespace,self.dest,None)
@@ -1124,13 +1143,15 @@ def __init__(self,
11241143
option_strings,
11251144
dest=SUPPRESS,
11261145
default=SUPPRESS,
1127-
help=None):
1146+
help=None,
1147+
deprecated=False):
11281148
super(_HelpAction,self).__init__(
11291149
option_strings=option_strings,
11301150
dest=dest,
11311151
default=default,
11321152
nargs=0,
1133-
help=help)
1153+
help=help,
1154+
deprecated=deprecated)
11341155

11351156
def__call__(self,parser,namespace,values,option_string=None):
11361157
parser.print_help()
@@ -1144,7 +1165,8 @@ def __init__(self,
11441165
version=None,
11451166
dest=SUPPRESS,
11461167
default=SUPPRESS,
1147-
help="show program's version number and exit"):
1168+
help="show program's version number and exit",
1169+
deprecated=False):
11481170
super(_VersionAction,self).__init__(
11491171
option_strings=option_strings,
11501172
dest=dest,
@@ -1188,6 +1210,7 @@ def __init__(self,
11881210
self._parser_class=parser_class
11891211
self._name_parser_map= {}
11901212
self._choices_actions= []
1213+
self._deprecated=set()
11911214

11921215
super(_SubParsersAction,self).__init__(
11931216
option_strings=option_strings,
@@ -1198,7 +1221,7 @@ def __init__(self,
11981221
help=help,
11991222
metavar=metavar)
12001223

1201-
defadd_parser(self,name,**kwargs):
1224+
defadd_parser(self,name,*,deprecated=False,**kwargs):
12021225
# set prog from the existing prefix
12031226
ifkwargs.get('prog')isNone:
12041227
kwargs['prog']='%s %s'% (self._prog_prefix,name)
@@ -1226,6 +1249,10 @@ def add_parser(self, name, **kwargs):
12261249
foraliasinaliases:
12271250
self._name_parser_map[alias]=parser
12281251

1252+
ifdeprecated:
1253+
self._deprecated.add(name)
1254+
self._deprecated.update(aliases)
1255+
12291256
returnparser
12301257

12311258
def_get_subactions(self):
@@ -1241,21 +1268,25 @@ def __call__(self, parser, namespace, values, option_string=None):
12411268

12421269
# select the parser
12431270
try:
1244-
parser=self._name_parser_map[parser_name]
1271+
subparser=self._name_parser_map[parser_name]
12451272
exceptKeyError:
12461273
args= {'parser_name':parser_name,
12471274
'choices':', '.join(self._name_parser_map)}
12481275
msg=_('unknown parser %(parser_name)r (choices: %(choices)s)')%args
12491276
raiseArgumentError(self,msg)
12501277

1278+
ifparser_nameinself._deprecated:
1279+
parser._warning(_("command '%(parser_name)s' is deprecated")%
1280+
{'parser_name':parser_name})
1281+
12511282
# parse all the remaining options into the namespace
12521283
# store any unrecognized options on the object, so that the top
12531284
# level parser can decide what to do with them
12541285

12551286
# In case this subparser defines new defaults, we parse them
12561287
# in a new namespace object and then update the original
12571288
# namespace for the relevant parts.
1258-
subnamespace,arg_strings=parser.parse_known_args(arg_strings,None)
1289+
subnamespace,arg_strings=subparser.parse_known_args(arg_strings,None)
12591290
forkey,valueinvars(subnamespace).items():
12601291
setattr(namespace,key,value)
12611292

@@ -1975,6 +2006,7 @@ def _parse_known_args(self, arg_strings, namespace):
19752006
# converts arg strings to the appropriate and then takes the action
19762007
seen_actions=set()
19772008
seen_non_default_actions=set()
2009+
warned=set()
19782010

19792011
deftake_action(action,argument_strings,option_string=None):
19802012
seen_actions.add(action)
@@ -2070,6 +2102,10 @@ def consume_optional(start_index):
20702102
# the Optional's string args stopped
20712103
assertaction_tuples
20722104
foraction,args,option_stringinaction_tuples:
2105+
ifaction.deprecatedandoption_stringnotinwarned:
2106+
self._warning(_("option '%(option)s' is deprecated")%
2107+
{'option':option_string})
2108+
warned.add(option_string)
20732109
take_action(action,args,option_string)
20742110
returnstop
20752111

@@ -2089,6 +2125,10 @@ def consume_positionals(start_index):
20892125
foraction,arg_countinzip(positionals,arg_counts):
20902126
args=arg_strings[start_index:start_index+arg_count]
20912127
start_index+=arg_count
2128+
ifargsandaction.deprecatedandaction.destnotinwarned:
2129+
self._warning(_("argument '%(argument_name)s' is deprecated")%
2130+
{'argument_name':action.dest})
2131+
warned.add(action.dest)
20922132
take_action(action,args)
20932133

20942134
# slice off the Positionals that we just parsed and return the
@@ -2650,3 +2690,7 @@ def error(self, message):
26502690
self.print_usage(_sys.stderr)
26512691
args= {'prog':self.prog,'message':message}
26522692
self.exit(2,_('%(prog)s: error: %(message)s\n')%args)
2693+
2694+
def_warning(self,message):
2695+
args= {'prog':self.prog,'message':message}
2696+
self._print_message(_('%(prog)s: warning: %(message)s\n')%args,_sys.stderr)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp