gh-83648: Support deprecation of options, arguments and subcommands in argparse (GH-114086)

This commit is contained in:
Serhiy Storchaka 2024-02-06 00:41:34 +02:00 committed by GitHub
parent c32bae5290
commit bb57ffdb38
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 262 additions and 27 deletions

View file

@ -5099,7 +5099,8 @@ class TestStrings(TestCase):
string = (
"Action(option_strings=['--foo', '-a', '-b'], dest='b', "
"nargs='+', const=None, default=42, type='int', "
"choices=[1, 2, 3], required=False, help='HELP', metavar='METAVAR')")
"choices=[1, 2, 3], required=False, help='HELP', "
"metavar='METAVAR', deprecated=False)")
self.assertStringEqual(option, string)
def test_argument(self):
@ -5116,7 +5117,8 @@ class TestStrings(TestCase):
string = (
"Action(option_strings=[], dest='x', nargs='?', "
"const=None, default=2.5, type=%r, choices=[0.5, 1.5, 2.5], "
"required=True, help='H HH H', metavar='MV MV MV')" % float)
"required=True, help='H HH H', metavar='MV MV MV', "
"deprecated=False)" % float)
self.assertStringEqual(argument, string)
def test_namespace(self):
@ -5308,6 +5310,139 @@ class TestTypeFunctionCallOnlyOnce(TestCase):
args = parser.parse_args('--foo spam!'.split())
self.assertEqual(NS(foo='foo_converted'), args)
# ==============================================
# Check that deprecated arguments output warning
# ==============================================
class TestDeprecatedArguments(TestCase):
def test_deprecated_option(self):
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', deprecated=True)
with captured_stderr() as stderr:
parser.parse_args(['--foo', 'spam'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: option '--foo' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
with captured_stderr() as stderr:
parser.parse_args(['-f', 'spam'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: option '-f' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
with captured_stderr() as stderr:
parser.parse_args(['--foo', 'spam', '-f', 'ham'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: option '--foo' is deprecated")
self.assertRegex(stderr, "warning: option '-f' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 2)
with captured_stderr() as stderr:
parser.parse_args(['--foo', 'spam', '--foo', 'ham'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: option '--foo' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
def test_deprecated_boolean_option(self):
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', action=argparse.BooleanOptionalAction, deprecated=True)
with captured_stderr() as stderr:
parser.parse_args(['--foo'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: option '--foo' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
with captured_stderr() as stderr:
parser.parse_args(['-f'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: option '-f' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
with captured_stderr() as stderr:
parser.parse_args(['--no-foo'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: option '--no-foo' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
with captured_stderr() as stderr:
parser.parse_args(['--foo', '--no-foo'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: option '--foo' is deprecated")
self.assertRegex(stderr, "warning: option '--no-foo' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 2)
def test_deprecated_arguments(self):
parser = argparse.ArgumentParser()
parser.add_argument('foo', nargs='?', deprecated=True)
parser.add_argument('bar', nargs='?', deprecated=True)
with captured_stderr() as stderr:
parser.parse_args([])
stderr = stderr.getvalue()
self.assertEqual(stderr.count('is deprecated'), 0)
with captured_stderr() as stderr:
parser.parse_args(['spam'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: argument 'foo' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
with captured_stderr() as stderr:
parser.parse_args(['spam', 'ham'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: argument 'foo' is deprecated")
self.assertRegex(stderr, "warning: argument 'bar' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 2)
def test_deprecated_varargument(self):
parser = argparse.ArgumentParser()
parser.add_argument('foo', nargs='*', deprecated=True)
with captured_stderr() as stderr:
parser.parse_args([])
stderr = stderr.getvalue()
self.assertEqual(stderr.count('is deprecated'), 0)
with captured_stderr() as stderr:
parser.parse_args(['spam'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: argument 'foo' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
with captured_stderr() as stderr:
parser.parse_args(['spam', 'ham'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: argument 'foo' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
def test_deprecated_subparser(self):
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
subparsers.add_parser('foo', aliases=['baz'], deprecated=True)
subparsers.add_parser('bar')
with captured_stderr() as stderr:
parser.parse_args(['bar'])
stderr = stderr.getvalue()
self.assertEqual(stderr.count('is deprecated'), 0)
with captured_stderr() as stderr:
parser.parse_args(['foo'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: command 'foo' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
with captured_stderr() as stderr:
parser.parse_args(['baz'])
stderr = stderr.getvalue()
self.assertRegex(stderr, "warning: command 'baz' is deprecated")
self.assertEqual(stderr.count('is deprecated'), 1)
# ==================================================================
# Check semantics regarding the default argument and type conversion
# ==================================================================