@@ -74,7 +74,7 @@ def test_duplicate_commands():
7474class MyConfigDataclass :
7575 my_first_arg : Path = field (metadata = {"help" : "Some help for arg1." })
7676 arg : str = field (default = "value1" , metadata = {"help" : "Some help for arg1." })
77- opt_arg : str | None = field (default = None , metadata = {"help" : "Some help for arg1." })
77+ opt_arg : Optional [ str ] = field (default = None , metadata = {"help" : "Some help for arg1." })
7878 opt_arg_bool : bool | None = field (
7979 default = False ,
8080 metadata = {
@@ -88,6 +88,10 @@ def test_is_type_optional():
8888 assert is_type_optional (Optional [str ])
8989 assert not is_type_optional (str )
9090 assert is_type_optional (Union [Path | None , str ])
91+ # Test modern union syntax (Python 3.10+)
92+ assert is_type_optional (Path | None )
93+ assert is_type_optional (str | None )
94+ assert not is_type_optional (Path | str ) # Union without None should not be optional
9195 assert not is_type_optional (Union [Path , str ])
9296
9397
@@ -138,6 +142,45 @@ def test_register_optional_path_arguments():
138142 }
139143
140144
145+ @dataclass
146+ class ClassWithModernUnionTypes :
147+ """Test class with various modern union syntax optional fields."""
148+
149+ required_path : Path = field (metadata = {"help" : "Required path." })
150+ optional_path : Path | None = field (default = None , metadata = {"help" : "Optional path." })
151+ optional_str : str | None = field (default = None , metadata = {"help" : "Optional string." })
152+ optional_int : int | None = field (default = None , metadata = {"help" : "Optional integer." })
153+ optional_bool : bool | None = field (default = None , metadata = {"help" : "Optional boolean." })
154+
155+
156+ def test_register_modern_union_optional_arguments ():
157+ """Test that modern union syntax (T | None) works correctly."""
158+ parser = ArgumentParser ()
159+ register_arguments_for_config_dataclass (parser , ClassWithModernUnionTypes )
160+
161+ # Test with all arguments provided
162+ args = parser .parse_args (
163+ ["--required-path" , "required/path" , "--optional-path" , "optional/path" , "--optional-str" , "test_string" , "--optional-int" , "42" , "--optional-bool" , "true" ]
164+ )
165+ assert vars (args ) == {
166+ "required_path" : Path ("required/path" ),
167+ "optional_path" : Path ("optional/path" ),
168+ "optional_str" : "test_string" ,
169+ "optional_int" : 42 ,
170+ "optional_bool" : True ,
171+ }
172+
173+ # Test with only required arguments
174+ args = parser .parse_args (["--required-path" , "required/path" ])
175+ assert vars (args ) == {
176+ "required_path" : Path ("required/path" ),
177+ "optional_path" : None ,
178+ "optional_str" : None ,
179+ "optional_int" : None ,
180+ "optional_bool" : None ,
181+ }
182+
183+
141184@dataclass
142185class ClassWithListArgument :
143186 my_paths : list [Path ] = field (metadata = {"help" : "List of paths" })
0 commit comments