@@ -2879,26 +2879,30 @@ def test_failures_when_not_required(self):
28792879 parse_args = self .get_parser (required = False ).parse_args
28802880 error = ArgumentParserError
28812881 for args_string in self .failures :
2882- self .assertRaises (error , parse_args , args_string .split ())
2882+ with self .subTest (args = args_string ):
2883+ self .assertRaises (error , parse_args , args_string .split ())
28832884
28842885 def test_failures_when_required (self ):
28852886 parse_args = self .get_parser (required = True ).parse_args
28862887 error = ArgumentParserError
28872888 for args_string in self .failures + ['' ]:
2888- self .assertRaises (error , parse_args , args_string .split ())
2889+ with self .subTest (args = args_string ):
2890+ self .assertRaises (error , parse_args , args_string .split ())
28892891
28902892 def test_successes_when_not_required (self ):
28912893 parse_args = self .get_parser (required = False ).parse_args
28922894 successes = self .successes + self .successes_when_not_required
28932895 for args_string , expected_ns in successes :
2894- actual_ns = parse_args (args_string .split ())
2895- self .assertEqual (actual_ns , expected_ns )
2896+ with self .subTest (args = args_string ):
2897+ actual_ns = parse_args (args_string .split ())
2898+ self .assertEqual (actual_ns , expected_ns )
28962899
28972900 def test_successes_when_required (self ):
28982901 parse_args = self .get_parser (required = True ).parse_args
28992902 for args_string , expected_ns in self .successes :
2900- actual_ns = parse_args (args_string .split ())
2901- self .assertEqual (actual_ns , expected_ns )
2903+ with self .subTest (args = args_string ):
2904+ actual_ns = parse_args (args_string .split ())
2905+ self .assertEqual (actual_ns , expected_ns )
29022906
29032907 def test_usage_when_not_required (self ):
29042908 format_usage = self .get_parser (required = False ).format_usage
@@ -3285,6 +3289,111 @@ def get_parser(self, required):
32853289 test_successes_when_not_required = None
32863290 test_successes_when_required = None
32873291
3292+
3293+ class TestMutuallyExclusiveOptionalOptional (MEMixin , TestCase ):
3294+ def get_parser (self , required = None ):
3295+ parser = ErrorRaisingArgumentParser (prog = 'PROG' )
3296+ group = parser .add_mutually_exclusive_group (required = required )
3297+ group .add_argument ('--foo' )
3298+ group .add_argument ('--bar' , nargs = '?' )
3299+ return parser
3300+
3301+ failures = [
3302+ '--foo X --bar Y' ,
3303+ '--foo X --bar' ,
3304+ ]
3305+ successes = [
3306+ ('--foo X' , NS (foo = 'X' , bar = None )),
3307+ ('--bar X' , NS (foo = None , bar = 'X' )),
3308+ ('--bar' , NS (foo = None , bar = None )),
3309+ ]
3310+ successes_when_not_required = [
3311+ ('' , NS (foo = None , bar = None )),
3312+ ]
3313+ usage_when_required = '''\
3314+ usage: PROG [-h] (--foo FOO | --bar [BAR])
3315+ '''
3316+ usage_when_not_required = '''\
3317+ usage: PROG [-h] [--foo FOO | --bar [BAR]]
3318+ '''
3319+ help = '''\
3320+
3321+ options:
3322+ -h, --help show this help message and exit
3323+ --foo FOO
3324+ --bar [BAR]
3325+ '''
3326+
3327+
3328+ class TestMutuallyExclusiveOptionalWithDefault (MEMixin , TestCase ):
3329+ def get_parser (self , required = None ):
3330+ parser = ErrorRaisingArgumentParser (prog = 'PROG' )
3331+ group = parser .add_mutually_exclusive_group (required = required )
3332+ group .add_argument ('--foo' )
3333+ group .add_argument ('--bar' , type = bool , default = True )
3334+ return parser
3335+
3336+ failures = [
3337+ '--foo X --bar Y' ,
3338+ '--foo X --bar=' ,
3339+ ]
3340+ successes = [
3341+ ('--foo X' , NS (foo = 'X' , bar = True )),
3342+ ('--bar X' , NS (foo = None , bar = True )),
3343+ ('--bar=' , NS (foo = None , bar = False )),
3344+ ]
3345+ successes_when_not_required = [
3346+ ('' , NS (foo = None , bar = True )),
3347+ ]
3348+ usage_when_required = '''\
3349+ usage: PROG [-h] (--foo FOO | --bar BAR)
3350+ '''
3351+ usage_when_not_required = '''\
3352+ usage: PROG [-h] [--foo FOO | --bar BAR]
3353+ '''
3354+ help = '''\
3355+
3356+ options:
3357+ -h, --help show this help message and exit
3358+ --foo FOO
3359+ --bar BAR
3360+ '''
3361+
3362+
3363+ class TestMutuallyExclusivePositionalWithDefault (MEMixin , TestCase ):
3364+ def get_parser (self , required = None ):
3365+ parser = ErrorRaisingArgumentParser (prog = 'PROG' )
3366+ group = parser .add_mutually_exclusive_group (required = required )
3367+ group .add_argument ('--foo' )
3368+ group .add_argument ('bar' , nargs = '?' , type = bool , default = True )
3369+ return parser
3370+
3371+ failures = [
3372+ '--foo X Y' ,
3373+ ]
3374+ successes = [
3375+ ('--foo X' , NS (foo = 'X' , bar = True )),
3376+ ('X' , NS (foo = None , bar = True )),
3377+ ]
3378+ successes_when_not_required = [
3379+ ('' , NS (foo = None , bar = True )),
3380+ ]
3381+ usage_when_required = '''\
3382+ usage: PROG [-h] (--foo FOO | bar)
3383+ '''
3384+ usage_when_not_required = '''\
3385+ usage: PROG [-h] [--foo FOO | bar]
3386+ '''
3387+ help = '''\
3388+
3389+ positional arguments:
3390+ bar
3391+
3392+ options:
3393+ -h, --help show this help message and exit
3394+ --foo FOO
3395+ '''
3396+
32883397# =================================================
32893398# Mutually exclusive group in parent parser tests
32903399# =================================================
0 commit comments