@@ -95,14 +95,15 @@ def test_add_class_without_nesting(parser):
9595 parser .add_class_arguments (Class3 )
9696
9797 assert "Class3" in parser .groups
98- for key in "c3_a0 c3_a1 c3_a2 c3_a3 c3_a4 c3_a5 c3_a6 c3_a7 c3_a8 c1_a2 c1_a4 c1_a5" .split ():
98+ for key in "c3_a0 c3_a1 c3_a2 c3_a3 c3_a4 c3_a5 c3_a6 c3_a7 c3_a8 c1_a2 c1_a3 c1_a4 c1_a5" .split ():
9999 assert _find_action (parser , key ) is not None , f"{ key } should be in parser but is not"
100- for key in ["c2_a0" , "c1_a1" , "c1_a3" , " c0_a0" ]:
100+ for key in ["c2_a0" , "c1_a1" , "c0_a0" ]:
101101 assert _find_action (parser , key ) is None , f"{ key } should not be in parser but is"
102102
103103 cfg = parser .parse_args (["--c3_a0=0" , "--c3_a3=true" , "--c3_a4=a" ], with_meta = False )
104104 assert cfg .as_dict () == {
105105 "c1_a2" : 2.0 ,
106+ "c1_a3" : None ,
106107 "c1_a4" : 4 ,
107108 "c1_a5" : "five" ,
108109 "c3_a0" : 0 ,
@@ -136,12 +137,12 @@ def test_add_class_nested_as_group_false(parser):
136137 added_args = parser .add_class_arguments (Class3 , "g" , as_group = False )
137138
138139 assert "g" not in parser .groups
139- assert 12 == len (added_args )
140+ assert 13 == len (added_args )
140141 assert all (a .startswith ("g." ) for a in added_args )
141142
142- for key in "c3_a0 c3_a1 c3_a2 c3_a3 c3_a4 c3_a5 c3_a6 c3_a7 c3_a8 c1_a2 c1_a4 c1_a5" .split ():
143+ for key in "c3_a0 c3_a1 c3_a2 c3_a3 c3_a4 c3_a5 c3_a6 c3_a7 c3_a8 c1_a2 c1_a3 c1_a4 c1_a5" .split ():
143144 assert _find_action (parser , f"g.{ key } " ) is not None , f"{ key } should be in parser but is not"
144- for key in ["c2_a0" , "c1_a1" , "c1_a3" , " c0_a0" ]:
145+ for key in ["c2_a0" , "c1_a1" , "c0_a0" ]:
145146 assert _find_action (parser , f"g.{ key } " ) is None , f"{ key } should not be in parser but is"
146147
147148 defaults = parser .get_defaults ()
@@ -218,13 +219,13 @@ def test_add_class_nested_with_and_without_parameters(parser):
218219 assert isinstance (init .group .second , NestedWithoutParams )
219220
220221
221- class NoValidParams :
222- def __init__ (self , a0 = None ):
222+ class SkippedUnderscoreParam :
223+ def __init__ (self , _a0 = None ):
223224 pass
224225
225226
226- def test_add_class_without_valid_parameters (parser ):
227- assert [] == parser .add_class_arguments (NoValidParams )
227+ def test_add_class_skipped_underscore_parameter (parser ):
228+ assert [] == parser .add_class_arguments (SkippedUnderscoreParam )
228229
229230
230231class WithNew :
@@ -437,18 +438,17 @@ def test_add_class_unmatched_default_type(parser):
437438
438439
439440class WithMethods :
440- def normal_method (self , a1 = "1" , a2 : float = 2.0 , a3 : bool = False , a4 = None ):
441+ def normal_method (self , a1 = "1" , a2 : float = 2.0 , a3 : bool = False ):
441442 """normal_method short description
442443
443444 Args:
444445 a1: a1 description
445446 a2: a2 description
446- a4: a4 description
447447 """
448448 return a1
449449
450450 @staticmethod
451- def static_method (a1 : str , a2 : float = 2.0 , a3 = None ):
451+ def static_method (a1 : str , a2 : float = 2.0 , _a3 = None ):
452452 return a1
453453
454454
@@ -472,8 +472,7 @@ def test_add_method_normal_and_static(parser):
472472
473473 for key in ["m.a1" , "m.a2" , "m.a3" , "s.a1" , "s.a2" ]:
474474 assert _find_action (parser , key ) is not None , f"{ key } should be in parser but is not"
475- for key in ["m.a4" , "s.a3" ]:
476- assert _find_action (parser , key ) is None , f"{ key } should not be in parser but is"
475+ assert _find_action (parser , "s._a3" ) is None , "s._a3 should not be in parser but is"
477476
478477 cfg = parser .parse_args (["--m.a1=x" , "--s.a1=y" ], with_meta = False ).as_dict ()
479478 assert cfg == {"m" : {"a1" : "x" , "a2" : 2.0 , "a3" : False }, "s" : {"a1" : "y" , "a2" : 2.0 }}
@@ -526,17 +525,16 @@ def test_add_function_arguments(parser):
526525
527526 assert "func" in parser .groups
528527
529- for key in ["a1" , "a2" , "a3" ]:
528+ for key in ["a1" , "a2" , "a3" , "a4" ]:
530529 assert _find_action (parser , key ) is not None , f"{ key } should be in parser but is not"
531- assert _find_action (parser , "a4" ) is None , "a4 should not be in parser but is"
532530
533531 cfg = parser .parse_args (["--a1=x" ], with_meta = False ).as_dict ()
534- assert cfg == {"a1" : "x" , "a2" : 2.0 , "a3" : False }
532+ assert cfg == {"a1" : "x" , "a2" : 2.0 , "a3" : False , "a4" : None }
535533 assert "x" == func (** cfg )
536534
537535 if docstring_parser_support :
538536 assert "func short description" == parser .groups ["func" ].title
539- for key in ["a1" , "a2" ]:
537+ for key in ["a1" , "a2" , "a4" ]:
540538 assert f"{ key } description" == _find_action (parser , key ).help
541539
542540
@@ -604,6 +602,16 @@ def test_add_function_fail_untyped_false(parser):
604602 assert Namespace (a1 = None , a2 = None ) == parser .parse_args ([])
605603
606604
605+ def func_untyped_optional (a1 : str , a2 = None ):
606+ return a1
607+
608+
609+ def test_add_function_fail_untyped_true_untyped_optional (parser ):
610+ added_args = parser .add_function_arguments (func_untyped_optional , fail_untyped = True )
611+ assert ["a1" , "a2" ] == added_args
612+ assert Namespace (a1 = "x" , a2 = None ) == parser .parse_args (["--a1=x" ])
613+
614+
607615def func_config (a1 = "1" , a2 : float = 2.0 , a3 : bool = False ):
608616 return a1
609617
@@ -616,10 +624,10 @@ def test_add_function_group_config(parser, tmp_cwd):
616624 cfg_path .write_text (json_or_yaml_dump ({"a1" : "one" , "a3" : True }))
617625
618626 cfg = parser .parse_args ([f"--func={ cfg_path } " ])
619- assert cfg .func == Namespace (a1 = "one" , a2 = 2.0 , a3 = True )
627+ assert cfg .func == Namespace (a1 = "one" , a2 = 2.0 , a3 = True , a4 = None )
620628
621629 cfg = parser .parse_args (['--func={"a1": "ONE"}' ])
622- assert cfg .func == Namespace (a1 = "ONE" , a2 = 2.0 , a3 = False )
630+ assert cfg .func == Namespace (a1 = "ONE" , a2 = 2.0 , a3 = False , a4 = None )
623631
624632 with pytest .raises (ArgumentError ) as ctx :
625633 parser .parse_args (['--func="""' ])
@@ -638,7 +646,7 @@ def test_add_function_group_config_within_config(parser, tmp_cwd):
638646
639647 cfg = parser .parse_args ([f"--cfg={ cfg_path } " ])
640648 assert str (cfg .func .__path__ ) == str (subcfg_path )
641- assert strip_meta (cfg .func ) == Namespace (a1 = "one" , a2 = 2.0 , a3 = True )
649+ assert strip_meta (cfg .func ) == Namespace (a1 = "one" , a2 = 2.0 , a3 = True , a4 = None )
642650
643651
644652def func_param_conflict (p1 : int , cfg : dict ):
0 commit comments