@@ -325,13 +325,21 @@ class TestBuildParser:
325325 ),
326326 pytest .param (_make_func (list [int ], name = "nums" ), {"option_strings" : [], "nargs" : "+" , "type" : int }, id = "list_int" ),
327327 pytest .param (_make_func (set [int ], name = "nums" ), {"option_strings" : [], "nargs" : "+" , "type" : int }, id = "set_int" ),
328+ pytest .param (
329+ _make_func (frozenset [int ], name = "nums" ),
330+ {"option_strings" : [], "nargs" : "+" , "type" : int },
331+ id = "frozenset_int" ,
332+ ),
328333 pytest .param (
329334 _make_func (tuple [int , int , int ], name = "triple" ),
330335 {"option_strings" : [], "nargs" : 3 , "type" : int },
331336 id = "tuple_fixed_triple" ,
332337 ),
333338 pytest .param (_make_func (list [str ], name = "files" ), {"option_strings" : [], "nargs" : "+" }, id = "list_positional" ),
334339 pytest .param (_make_func (set [str ], name = "tags" ), {"option_strings" : [], "nargs" : "+" }, id = "set_positional" ),
340+ pytest .param (
341+ _make_func (frozenset [str ], name = "tags" ), {"option_strings" : [], "nargs" : "+" }, id = "frozenset_positional"
342+ ),
335343 pytest .param (
336344 _make_func (tuple [int , ...], name = "values" ),
337345 {"option_strings" : [], "nargs" : "+" , "type" : int },
@@ -341,6 +349,7 @@ class TestBuildParser:
341349 _make_func (tuple [int , int ], name = "pair" ), {"option_strings" : [], "nargs" : 2 , "type" : int }, id = "tuple_fixed"
342350 ),
343351 pytest .param (_make_func (list , name = "items" ), {"option_strings" : [], "nargs" : "+" }, id = "bare_list" ),
352+ pytest .param (_make_func (frozenset , name = "items" ), {"option_strings" : [], "nargs" : "+" }, id = "bare_frozenset" ),
344353 pytest .param (_make_func (tuple , name = "items" ), {"option_strings" : [], "nargs" : "+" }, id = "bare_tuple" ),
345354 pytest .param (
346355 _make_func (Annotated [int | None , Argument ()], name = "val" ),
@@ -1469,6 +1478,8 @@ def test_optional_fixed_arity_positional_raises(self, annotation, resolve_kwargs
14691478 pytest .param (list [set [int ]], id = "list_of_set" ),
14701479 pytest .param (set [list [str ]], id = "set_of_list" ),
14711480 pytest .param (tuple [list [int ], ...], id = "tuple_of_list" ),
1481+ pytest .param (frozenset [list [int ]], id = "frozenset_of_list" ),
1482+ pytest .param (list [frozenset [int ]], id = "list_of_frozenset" ),
14721483 ],
14731484 )
14741485 def test_nested_collection_raises (self , annotation ) -> None :
@@ -1478,7 +1489,6 @@ def test_nested_collection_raises(self, annotation) -> None:
14781489 @pytest .mark .parametrize (
14791490 "annotation" ,
14801491 [
1481- pytest .param (frozenset [str ], id = "frozenset" ),
14821492 pytest .param (dict [str , int ], id = "dict" ),
14831493 ],
14841494 )
@@ -1737,34 +1747,29 @@ def test_non_list_passthrough(self) -> None:
17371747class TestCollectionRuntimeCast :
17381748 """End-to-end verify ``parse_args`` returns the declared container type, not a plain list."""
17391749
1740- def test_set_int_returns_set (self ) -> None :
1741- parser = build_parser_from_function (_make_func (set [int ], name = "nums" ))
1742- ns = parser .parse_args (["1" , "2" , "2" , "3" ])
1743- assert isinstance (ns .nums , set )
1744- assert ns .nums == {1 , 2 , 3 }
1745-
1746- def test_tuple_ellipsis_returns_tuple (self ) -> None :
1747- parser = build_parser_from_function (_make_func (tuple [int , ...], name = "values" ))
1748- ns = parser .parse_args (["1" , "2" , "3" ])
1749- assert isinstance (ns .values , tuple )
1750- assert ns .values == (1 , 2 , 3 )
1751-
1752- def test_tuple_fixed_returns_tuple (self ) -> None :
1753- parser = build_parser_from_function (_make_func (tuple [int , int ], name = "pair" ))
1754- ns = parser .parse_args (["5" , "10" ])
1755- assert isinstance (ns .pair , tuple )
1756- assert ns .pair == (5 , 10 )
1757-
1758- def test_list_bool_returns_list_of_bools (self ) -> None :
1759- parser = build_parser_from_function (_make_func (list [bool ], name = "flags" ))
1760- ns = parser .parse_args (["true" , "no" , "on" ])
1761- assert ns .flags == [True , False , True ]
1762-
1763- def test_tuple_paths_returns_tuple_of_paths (self ) -> None :
1764- parser = build_parser_from_function (_make_func (tuple [Path , Path ], name = "src_dst" ))
1765- ns = parser .parse_args (["/tmp/a" , "/tmp/b" ])
1766- assert isinstance (ns .src_dst , tuple )
1767- assert ns .src_dst == (Path ("/tmp/a" ), Path ("/tmp/b" ))
1750+ @pytest .mark .parametrize (
1751+ ("annotation" , "name" , "args" , "container" , "expected" ),
1752+ [
1753+ pytest .param (frozenset [int ], "nums" , ["1" , "2" , "2" , "3" ], frozenset , frozenset ({1 , 2 , 3 }), id = "frozenset_int" ),
1754+ pytest .param (set [int ], "nums" , ["1" , "2" , "2" , "3" ], set , {1 , 2 , 3 }, id = "set_int" ),
1755+ pytest .param (tuple [int , ...], "values" , ["1" , "2" , "3" ], tuple , (1 , 2 , 3 ), id = "tuple_ellipsis" ),
1756+ pytest .param (tuple [int , int ], "pair" , ["5" , "10" ], tuple , (5 , 10 ), id = "tuple_fixed" ),
1757+ pytest .param (list [bool ], "flags" , ["true" , "no" , "on" ], list , [True , False , True ], id = "list_bool" ),
1758+ pytest .param (
1759+ tuple [Path , Path ],
1760+ "src_dst" ,
1761+ ["/tmp/a" , "/tmp/b" ],
1762+ tuple ,
1763+ (Path ("/tmp/a" ), Path ("/tmp/b" )),
1764+ id = "tuple_paths" ,
1765+ ),
1766+ ],
1767+ )
1768+ def test_returns_declared_container (self , annotation , name , args , container , expected ) -> None :
1769+ parser = build_parser_from_function (_make_func (annotation , name = name ))
1770+ value = getattr (parser .parse_args (args ), name )
1771+ assert isinstance (value , container )
1772+ assert value == expected
17681773
17691774 def test_append_action_collects_values (self ) -> None :
17701775 parser = build_parser_from_function (_make_func (Annotated [list [str ], Option ("--tag" , action = "append" )], name = "tag" ))
0 commit comments