@@ -2900,26 +2900,30 @@ def test_failures_when_not_required(self):
29002900 parse_args = self .get_parser (required = False ).parse_args
29012901 error = ArgumentParserError
29022902 for args_string in self .failures :
2903- self .assertRaises (error , parse_args , args_string .split ())
2903+ with self .subTest (args = args_string ):
2904+ self .assertRaises (error , parse_args , args_string .split ())
29042905
29052906 def test_failures_when_required (self ):
29062907 parse_args = self .get_parser (required = True ).parse_args
29072908 error = ArgumentParserError
29082909 for args_string in self .failures + ['' ]:
2909- self .assertRaises (error , parse_args , args_string .split ())
2910+ with self .subTest (args = args_string ):
2911+ self .assertRaises (error , parse_args , args_string .split ())
29102912
29112913 def test_successes_when_not_required (self ):
29122914 parse_args = self .get_parser (required = False ).parse_args
29132915 successes = self .successes + self .successes_when_not_required
29142916 for args_string , expected_ns in successes :
2915- actual_ns = parse_args (args_string .split ())
2916- self .assertEqual (actual_ns , expected_ns )
2917+ with self .subTest (args = args_string ):
2918+ actual_ns = parse_args (args_string .split ())
2919+ self .assertEqual (actual_ns , expected_ns )
29172920
29182921 def test_successes_when_required (self ):
29192922 parse_args = self .get_parser (required = True ).parse_args
29202923 for args_string , expected_ns in self .successes :
2921- actual_ns = parse_args (args_string .split ())
2922- self .assertEqual (actual_ns , expected_ns )
2924+ with self .subTest (args = args_string ):
2925+ actual_ns = parse_args (args_string .split ())
2926+ self .assertEqual (actual_ns , expected_ns )
29232927
29242928 def test_usage_when_not_required (self ):
29252929 format_usage = self .get_parser (required = False ).format_usage
@@ -3306,6 +3310,111 @@ def get_parser(self, required):
33063310 test_successes_when_not_required = None
33073311 test_successes_when_required = None
33083312
3313+
3314+ class TestMutuallyExclusiveOptionalOptional (MEMixin , TestCase ):
3315+ def get_parser (self , required = None ):
3316+ parser = ErrorRaisingArgumentParser (prog = 'PROG' )
3317+ group = parser .add_mutually_exclusive_group (required = required )
3318+ group .add_argument ('--foo' )
3319+ group .add_argument ('--bar' , nargs = '?' )
3320+ return parser
3321+
3322+ failures = [
3323+ '--foo X --bar Y' ,
3324+ '--foo X --bar' ,
3325+ ]
3326+ successes = [
3327+ ('--foo X' , NS (foo = 'X' , bar = None )),
3328+ ('--bar X' , NS (foo = None , bar = 'X' )),
3329+ ('--bar' , NS (foo = None , bar = None )),
3330+ ]
3331+ successes_when_not_required = [
3332+ ('' , NS (foo = None , bar = None )),
3333+ ]
3334+ usage_when_required = '''\
3335+ usage: PROG [-h] (--foo FOO | --bar [BAR])
3336+ '''
3337+ usage_when_not_required = '''\
3338+ usage: PROG [-h] [--foo FOO | --bar [BAR]]
3339+ '''
3340+ help = '''\
3341+
3342+ options:
3343+ -h, --help show this help message and exit
3344+ --foo FOO
3345+ --bar [BAR]
3346+ '''
3347+
3348+
3349+ class TestMutuallyExclusiveOptionalWithDefault (MEMixin , TestCase ):
3350+ def get_parser (self , required = None ):
3351+ parser = ErrorRaisingArgumentParser (prog = 'PROG' )
3352+ group = parser .add_mutually_exclusive_group (required = required )
3353+ group .add_argument ('--foo' )
3354+ group .add_argument ('--bar' , type = bool , default = True )
3355+ return parser
3356+
3357+ failures = [
3358+ '--foo X --bar Y' ,
3359+ '--foo X --bar=' ,
3360+ ]
3361+ successes = [
3362+ ('--foo X' , NS (foo = 'X' , bar = True )),
3363+ ('--bar X' , NS (foo = None , bar = True )),
3364+ ('--bar=' , NS (foo = None , bar = False )),
3365+ ]
3366+ successes_when_not_required = [
3367+ ('' , NS (foo = None , bar = True )),
3368+ ]
3369+ usage_when_required = '''\
3370+ usage: PROG [-h] (--foo FOO | --bar BAR)
3371+ '''
3372+ usage_when_not_required = '''\
3373+ usage: PROG [-h] [--foo FOO | --bar BAR]
3374+ '''
3375+ help = '''\
3376+
3377+ options:
3378+ -h, --help show this help message and exit
3379+ --foo FOO
3380+ --bar BAR
3381+ '''
3382+
3383+
3384+ class TestMutuallyExclusivePositionalWithDefault (MEMixin , TestCase ):
3385+ def get_parser (self , required = None ):
3386+ parser = ErrorRaisingArgumentParser (prog = 'PROG' )
3387+ group = parser .add_mutually_exclusive_group (required = required )
3388+ group .add_argument ('--foo' )
3389+ group .add_argument ('bar' , nargs = '?' , type = bool , default = True )
3390+ return parser
3391+
3392+ failures = [
3393+ '--foo X Y' ,
3394+ ]
3395+ successes = [
3396+ ('--foo X' , NS (foo = 'X' , bar = True )),
3397+ ('X' , NS (foo = None , bar = True )),
3398+ ]
3399+ successes_when_not_required = [
3400+ ('' , NS (foo = None , bar = True )),
3401+ ]
3402+ usage_when_required = '''\
3403+ usage: PROG [-h] (--foo FOO | bar)
3404+ '''
3405+ usage_when_not_required = '''\
3406+ usage: PROG [-h] [--foo FOO | bar]
3407+ '''
3408+ help = '''\
3409+
3410+ positional arguments:
3411+ bar
3412+
3413+ options:
3414+ -h, --help show this help message and exit
3415+ --foo FOO
3416+ '''
3417+
33093418# =================================================
33103419# Mutually exclusive group in parent parser tests
33113420# =================================================
0 commit comments