@@ -1647,65 +1647,71 @@ def test_final_forward_ref(self):
16471647
16481648 def test_annotation_and_optional_default (self ):
16491649 annotation = Annotated [Union [int , None ], "data" ]
1650- optional_annotation = Optional [annotation ]
16511650 NoneAlias = None
1651+ StrAlias = str
1652+ T_default = TypeVar ("T_default" , default = None )
1653+ Ts = TypeVarTuple ("Ts" )
16521654
16531655 cases = {
1654- # (annotation, skip_as_str): expected_type_hints
1655- # Should skip_as_str if contains a ForwardRef.
1656- ((), True ): {},
1657- (int , True ): {"x" : int },
1658- ("int" , True ): {"x" : int },
1659- (Optional [int ], False ): {"x" : Optional [int ]},
1660- (optional_annotation , False ): {"x" : optional_annotation },
1661- (annotation , False ): {"x" : annotation },
1662- (Union [annotation , T ], True ): {"x" : Union [annotation , T ]},
1663- ("Union[Annotated[Union[int, None], 'data'], T]" , True ): {
1664- "x" : Union [annotation , T ]
1665- },
1666- (Union [str , None , str ], False ): {"x" : Optional [str ]},
1667- (Union [str , None , "str" ], True ): {"x" : Optional [str ]},
1668- (Union [str , "str" ], True ): {"x" : str },
1669- (List ["str" ], True ): {"x" : List [str ]},
1670- (Optional [List [str ]], False ): {"x" : Optional [List [str ]]},
1671- (Unpack [Tuple [int , None ]], False ): {"x" : Unpack [Tuple [int , None ]]},
1672- (Union [str , "Union[int, None]" ], True ): {"x" : Union [str , int , None ]},
1673- (NoneAlias , True ): {"x" : type (None )},
1674- ("NoneAlias" , True ): {"x" : type (None )},
1675- (Union [str , "NoneAlias" ], True ): {"x" : Optional [str ]},
1656+ # annotation: expected_type_hints
1657+ Annotated [None , "none" ] : Annotated [None , "none" ],
1658+ annotation : annotation ,
1659+ Optional [int ] : Optional [int ],
1660+ Optional [List [str ]] : Optional [List [str ]],
1661+ Optional [annotation ] : Optional [annotation ],
1662+ Union [str , None , str ] : Optional [str ],
1663+ Unpack [Tuple [int , None ]]: Unpack [Tuple [int , None ]],
1664+ # Note: A starred *Ts will use typing.Unpack in 3.11+ see Issue #485
1665+ Unpack [Ts ] : Unpack [Ts ],
16761666 }
1677- if sys .version_info >= (3 , 10 ): # cannot construct UnionTypes
1678- cases_3_10 = {
1679- ("str | NoneAlias" , True ) : {"x" : str | None },
1680- (str | None , False ) : {"x" : Optional [str ]},
1681- }
1682- cases .update (cases_3_10 )
1683- for ((annot , skip_as_str ), expected ), none_default , as_str , wrap_optional in itertools .product (
1667+ # contains a ForwardRef, TypeVar(~prefix) or no expression
1668+ do_not_stringify_cases = {
1669+ () : {},
1670+ int : int ,
1671+ "int" : int ,
1672+ None : type (None ),
1673+ "NoneAlias" : type (None ),
1674+ List ["str" ] : List [str ],
1675+ Union [str , "str" ] : str ,
1676+ Union [str , None , "str" ] : Optional [str ],
1677+ Union [str , "NoneAlias" , "StrAlias" ]: Optional [str ],
1678+ Union [str , "Union[None, StrAlias]" ]: Optional [str ],
1679+ Union ["annotation" , T_default ] : Union [annotation , T_default ],
1680+ Annotated ["annotation" , "nested" ] : Annotated [Union [int , None ], "data" , "nested" ],
1681+ }
1682+ if TYPING_3_10_0 : # cannot construct UnionTypes
1683+ do_not_stringify_cases ["str | NoneAlias | StrAlias" ] = str | None
1684+ cases [str | None ] = Optional [str ]
1685+ cases .update (do_not_stringify_cases )
1686+ for (annot , expected ), none_default , as_str , wrap_optional in itertools .product (
16841687 cases .items (), (False , True ), (False , True ), (False , True )
16851688 ):
16861689 # Special case:
16871690 skip_reason = None
1688- if sys .version_info [:2 ] == (3 , 10 ) and annot == "str | NoneAlias" and none_default :
1689- # Optional[str | None] -> Optional[str] not UnionType
1691+ annot_unchanged = annot
1692+ if sys .version_info [:2 ] == (3 , 10 ) and annot == "str | NoneAlias | StrAlias" and none_default :
1693+ # different repr here as Optional[str | None] -> Optional[str] not a UnionType
16901694 skip_reason = "UnionType not preserved in 3.10"
16911695 if wrap_optional :
1692- if annot == ():
1696+ if annot_unchanged == ():
16931697 continue
16941698 annot = Optional [annot ]
1695- expected = {"x" : Optional [expected ['x' ]]}
1699+ expected = {"x" : Optional [expected ]}
1700+ else :
1701+ expected = {"x" : expected } if annot_unchanged != () else {}
16961702 if as_str :
1697- if skip_as_str or annot == ():
1703+ if annot_unchanged in do_not_stringify_cases or annot_unchanged == ():
16981704 continue
16991705 annot = str (annot )
17001706 with self .subTest (
17011707 annotation = annot ,
17021708 as_str = as_str ,
1709+ wrap_optional = wrap_optional ,
17031710 none_default = none_default ,
17041711 expected_type_hints = expected ,
1705- wrap_optional = wrap_optional ,
17061712 ):
17071713 # Create function to check
1708- if annot == ():
1714+ if annot_unchanged == ():
17091715 if none_default :
17101716 def func (x = None ): pass
17111717 else :
@@ -1715,9 +1721,12 @@ def func(x: annot = None): pass
17151721 else :
17161722 def func (x : annot ): pass
17171723 type_hints = get_type_hints (func , globals (), locals (), include_extras = True )
1724+ # Equality
17181725 self .assertEqual (type_hints , expected )
1726+ # Hash
17191727 for k in type_hints .keys ():
17201728 self .assertEqual (hash (type_hints [k ]), hash (expected [k ]))
1729+ # Repr
17211730 with self .subTest ("Check str and repr" ):
17221731 if skip_reason == "UnionType not preserved in 3.10" :
17231732 self .skipTest (skip_reason )
0 commit comments