summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_argparse.py
diff options
context:
space:
mode:
authorSavannah Ostrowski <savannahostrowski@gmail.com>2024-10-17 07:07:37 (GMT)
committerGitHub <noreply@github.com>2024-10-17 07:07:37 (GMT)
commit624be8699aec22bef137041478078c6fafaf032e (patch)
tree9527b230b7e991a25536b6ce66b63b82d827f810 /Lib/test/test_argparse.py
parenta5a7f5e16d8c3938d266703ea8fba8ffee3e3ae5 (diff)
downloadcpython-624be8699aec22bef137041478078c6fafaf032e.zip
cpython-624be8699aec22bef137041478078c6fafaf032e.tar.gz
cpython-624be8699aec22bef137041478078c6fafaf032e.tar.bz2
GH-99749: Add optional feature to suggest correct names (ArgumentParser) (GH-124456)
Diffstat (limited to 'Lib/test/test_argparse.py')
-rw-r--r--Lib/test/test_argparse.py103
1 files changed, 90 insertions, 13 deletions
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index 78692fd..a3c096e 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -2253,6 +2253,95 @@ class TestNegativeNumber(ParserTestCase):
('--complex -1e-3j', NS(int=None, float=None, complex=-0.001j)),
]
+class TestArgumentAndSubparserSuggestions(TestCase):
+ """Test error handling and suggestion when a user makes a typo"""
+
+ def test_wrong_argument_error_with_suggestions(self):
+ parser = ErrorRaisingArgumentParser(suggest_on_error=True)
+ parser.add_argument('foo', choices=['bar', 'baz'])
+ with self.assertRaises(ArgumentParserError) as excinfo:
+ parser.parse_args(('bazz',))
+ self.assertIn(
+ "error: argument foo: invalid choice: 'bazz', maybe you meant 'baz'? (choose from bar, baz)",
+ excinfo.exception.stderr
+ )
+
+ def test_wrong_argument_error_no_suggestions(self):
+ parser = ErrorRaisingArgumentParser(suggest_on_error=False)
+ parser.add_argument('foo', choices=['bar', 'baz'])
+ with self.assertRaises(ArgumentParserError) as excinfo:
+ parser.parse_args(('bazz',))
+ self.assertIn(
+ "error: argument foo: invalid choice: 'bazz' (choose from bar, baz)",
+ excinfo.exception.stderr,
+ )
+
+ def test_wrong_argument_subparsers_with_suggestions(self):
+ parser = ErrorRaisingArgumentParser(suggest_on_error=True)
+ subparsers = parser.add_subparsers(required=True)
+ subparsers.add_parser('foo')
+ subparsers.add_parser('bar')
+ with self.assertRaises(ArgumentParserError) as excinfo:
+ parser.parse_args(('baz',))
+ self.assertIn(
+ "error: argument {foo,bar}: invalid choice: 'baz', maybe you meant"
+ " 'bar'? (choose from foo, bar)",
+ excinfo.exception.stderr,
+ )
+
+ def test_wrong_argument_subparsers_no_suggestions(self):
+ parser = ErrorRaisingArgumentParser(suggest_on_error=False)
+ subparsers = parser.add_subparsers(required=True)
+ subparsers.add_parser('foo')
+ subparsers.add_parser('bar')
+ with self.assertRaises(ArgumentParserError) as excinfo:
+ parser.parse_args(('baz',))
+ self.assertIn(
+ "error: argument {foo,bar}: invalid choice: 'baz' (choose from foo, bar)",
+ excinfo.exception.stderr,
+ )
+
+ def test_wrong_argument_no_suggestion_implicit(self):
+ parser = ErrorRaisingArgumentParser()
+ parser.add_argument('foo', choices=['bar', 'baz'])
+ with self.assertRaises(ArgumentParserError) as excinfo:
+ parser.parse_args(('bazz',))
+ self.assertIn(
+ "error: argument foo: invalid choice: 'bazz' (choose from bar, baz)",
+ excinfo.exception.stderr,
+ )
+
+ def test_suggestions_choices_empty(self):
+ parser = ErrorRaisingArgumentParser(suggest_on_error=True)
+ parser.add_argument('foo', choices=[])
+ with self.assertRaises(ArgumentParserError) as excinfo:
+ parser.parse_args(('bazz',))
+ self.assertIn(
+ "error: argument foo: invalid choice: 'bazz' (choose from )",
+ excinfo.exception.stderr,
+ )
+
+ def test_suggestions_choices_int(self):
+ parser = ErrorRaisingArgumentParser(suggest_on_error=True)
+ parser.add_argument('foo', choices=[1, 2])
+ with self.assertRaises(ArgumentParserError) as excinfo:
+ parser.parse_args(('3',))
+ self.assertIn(
+ "error: argument foo: invalid choice: '3' (choose from 1, 2)",
+ excinfo.exception.stderr,
+ )
+
+ def test_suggestions_choices_mixed_types(self):
+ parser = ErrorRaisingArgumentParser(suggest_on_error=True)
+ parser.add_argument('foo', choices=[1, '2'])
+ with self.assertRaises(ArgumentParserError) as excinfo:
+ parser.parse_args(('3',))
+ self.assertIn(
+ "error: argument foo: invalid choice: '3' (choose from 1, 2)",
+ excinfo.exception.stderr,
+ )
+
+
class TestInvalidAction(TestCase):
"""Test invalid user defined Action"""
@@ -2505,18 +2594,6 @@ class TestAddSubparsers(TestCase):
'error: the following arguments are required: {foo,bar}\n$'
)
- def test_wrong_argument_subparsers_no_destination_error(self):
- parser = ErrorRaisingArgumentParser()
- subparsers = parser.add_subparsers(required=True)
- subparsers.add_parser('foo')
- subparsers.add_parser('bar')
- with self.assertRaises(ArgumentParserError) as excinfo:
- parser.parse_args(('baz',))
- self.assertRegex(
- excinfo.exception.stderr,
- r"error: argument {foo,bar}: invalid choice: 'baz' \(choose from foo, bar\)\n$"
- )
-
def test_optional_subparsers(self):
parser = ErrorRaisingArgumentParser()
subparsers = parser.add_subparsers(dest='command', required=False)
@@ -2862,7 +2939,7 @@ class TestParentParsers(TestCase):
parser = ErrorRaisingArgumentParser(parents=[self.ab_mutex_parent])
self._test_mutex_ab(parser.parse_args)
- def test_single_granparent_mutex(self):
+ def test_single_grandparent_mutex(self):
parents = [self.ab_mutex_parent]
parser = ErrorRaisingArgumentParser(add_help=False, parents=parents)
parser = ErrorRaisingArgumentParser(parents=[parser])