@@ -63,7 +63,7 @@ def test_built_in_types():
6363
6464
6565def test_any ():
66- """typing.Any matches all sampled values, including primitives, collections, None, and type objects."""
66+ """typing.Any matches all sampled values, including primitives, collections, None, and type objects, even in strict mode ."""
6767 assert check (True , Any )
6868 assert check (False , Any )
6969 assert check (0 , Any )
@@ -76,6 +76,10 @@ def test_any():
7676 assert check (None , Any )
7777 assert check (str , Any )
7878 assert check (- 1000 , Any )
79+ assert check ([1 , 'two' , None ], Any , strict = True )
80+ assert check ((1 , 'two' , None ), Any , strict = True )
81+ assert check (str , Any , strict = True )
82+ assert check (None , Any , strict = True )
7983
8084
8185@pytest .mark .skipif (sys .version_info > (3 , 13 ), reason = "Before Python 3.14, you couldn't just use Union as an annotation." )
@@ -192,6 +196,23 @@ def test_optional(tuple_type, list_type, make_optional):
192196 assert check ((1 , 2 , 3 ), make_optional (tuple_type ))
193197
194198
199+ def test_optional_with_parameterized_collections_in_strict_mode (make_optional , subscribable_list_type , subscribable_tuple_type ):
200+ """
201+ Strict Optional checks pass strict validation through to parameterized collections.
202+
203+ None still matches, but present list and tuple values must satisfy their inner annotations.
204+ """
205+ assert check (None , make_optional (subscribable_list_type [int ]), strict = True )
206+ assert check ([1 , 2 , 3 ], make_optional (subscribable_list_type [int ]), strict = True )
207+ assert not check (['1' , '2' , '3' ], make_optional (subscribable_list_type [int ]), strict = True )
208+ assert not check ((1 , 2 , 3 ), make_optional (subscribable_list_type [int ]), strict = True )
209+
210+ assert check (None , make_optional (subscribable_tuple_type [int , str ]), strict = True )
211+ assert check ((1 , 'kek' ), make_optional (subscribable_tuple_type [int , str ]), strict = True )
212+ assert not check ((1 , 2 ), make_optional (subscribable_tuple_type [int , str ]), strict = True )
213+ assert not check ([1 , 'kek' ], make_optional (subscribable_tuple_type [int , str ]), strict = True )
214+
215+
195216def test_optional_union (make_union , make_optional , tuple_type ):
196217 """
197218 Optional unions accept None or any inner union member across typing and PEP 604 spellings.
@@ -342,12 +363,15 @@ def test_dict_without_arguments(dict_type, addictional_parameters):
342363
343364
344365def test_content_of_list_not_in_strict_mode_is_not_checking (subscribable_list_type ):
345- """Non-strict List[int]/list[int] checks accept any list regardless of element contents."""
366+ """Non-strict List[int]/list[int] checks accept any list regardless of element contents, but still reject non-lists ."""
346367 assert check ([], subscribable_list_type [int ])
347368 assert check (['lol' , 'kek' ], subscribable_list_type [int ])
348369 assert check ([1.0 , 2.0 ], subscribable_list_type [int ])
349370 assert check ([None , None ], subscribable_list_type [int ])
350371 assert check ([None , 'kek' , 1 , 1.0 ], subscribable_list_type [int ])
372+ assert not check ((), subscribable_list_type [int ])
373+ assert not check ((1 , 2 , 3 ), subscribable_list_type [int ])
374+ assert not check ('kek' , subscribable_list_type [int ])
351375
352376
353377def test_content_of_tuple_not_in_strict_mode_is_not_checking (subscribable_tuple_type ):
@@ -360,23 +384,29 @@ def test_content_of_tuple_not_in_strict_mode_is_not_checking(subscribable_tuple_
360384
361385
362386def test_content_of_dict_not_in_strict_mode_is_not_checking (subscribable_dict_type ):
363- """Non-strict Dict[int, int]/dict[int, int] validation accepts any dict regardless of key and value types ."""
387+ """Non-strict Dict[int, int]/dict[int, int] validation accepts any dict regardless of contents, but still rejects non-dicts ."""
364388 assert check ({}, subscribable_dict_type [int , int ])
365389 assert check ({1 : 'kek' }, subscribable_dict_type [int , int ])
366390 assert check ({'lol' : 'kek' }, subscribable_dict_type [int , int ])
367391 assert check ({'lol' : 1 }, subscribable_dict_type [int , int ])
368392 assert check ({1.0 : 1 }, subscribable_dict_type [int , int ])
393+ assert not check ([], subscribable_dict_type [int , int ])
394+ assert not check ([(1 , 2 )], subscribable_dict_type [int , int ])
395+ assert not check ('{1: 1}' , subscribable_dict_type [int , int ])
369396
370397
371398@pytest .mark .skipif (sys .version_info < (3 , 9 ), reason = 'Subscribing to objects became available in Python 3.9' )
372399def test_content_of_set_not_in_strict_mode_is_not_checking ():
373- """Non-strict set[int] validation checks only the set origin and ignores element types ."""
400+ """Non-strict set[int] validation accepts any set regardless of element contents, but still rejects non-sets ."""
374401 assert check (set (), set [int ])
375402 assert check (set (['lol' , 'kek' ]), set [int ])
376403 assert check (set ([1 , 'kek' ]), set [int ])
377404 assert check (set ([1 , None ]), set [int ])
378405 assert check (set ([None , None ]), set [int ])
379406 assert check (set (['1' , '2' ]), set [int ])
407+ assert not check ([], set [int ])
408+ assert not check (('1' , '2' ), set [int ])
409+ assert not check ('kek' , set [int ])
380410
381411
382412def test_try_to_pass_not_type_object_as_type ():
@@ -415,9 +445,10 @@ def test_sequence():
415445
416446@pytest .mark .skipif (sys .version_info < (3 , 9 ), reason = 'Subscribing to objects became available in Python 3.9' )
417447def test_sequence_is_not_checking_content ():
418- """Sequence[str] checks only the sequence origin, so integer lists and tuples still pass."""
448+ """Sequence[str] checks only the sequence origin, so integer lists and tuples pass while non-sequence containers fail ."""
419449 assert check ((1 , 2 , 3 ), Sequence [str ])
420450 assert check ([1 , 2 , 3 ], Sequence [str ])
451+ assert not check ({1 , 2 , 3 }, Sequence [str ])
421452
422453
423454def test_list_with_values_in_strict_mode (subscribable_list_type , make_union ):
@@ -569,6 +600,8 @@ def test_pass_mocks_when_its_off(strict_mode, list_type):
569600 assert not check (MagicMock (), list_type , strict = strict_mode , pass_mocks = False )
570601
571602 assert check (Mock (), Mock , strict = strict_mode , pass_mocks = False )
603+ assert check (MagicMock (), Mock , strict = strict_mode , pass_mocks = False )
604+ assert not check (Mock (), MagicMock , strict = strict_mode , pass_mocks = False )
572605 assert check (MagicMock (), MagicMock , strict = strict_mode , pass_mocks = False )
573606
574607
0 commit comments