8
8
import inspect
9
9
import builtins
10
10
import unittest
11
+ from textwrap import dedent
11
12
from unittest .mock import Mock
12
13
from typing import ClassVar , Any , List , Union , Tuple , Dict , Generic , TypeVar , Optional
13
14
from typing import get_type_hints
@@ -561,17 +562,17 @@ class C:
561
562
self .assertEqual (len (the_fields ), 3 )
562
563
563
564
self .assertEqual (the_fields [0 ].name , 'x' )
564
- self .assertEqual (the_fields [0 ].type , int )
565
+ self .assertEqual (the_fields [0 ].type , ' int' )
565
566
self .assertFalse (hasattr (C , 'x' ))
566
567
self .assertTrue (the_fields [0 ].init )
567
568
self .assertTrue (the_fields [0 ].repr )
568
569
self .assertEqual (the_fields [1 ].name , 'y' )
569
- self .assertEqual (the_fields [1 ].type , str )
570
+ self .assertEqual (the_fields [1 ].type , ' str' )
570
571
self .assertIsNone (getattr (C , 'y' ))
571
572
self .assertFalse (the_fields [1 ].init )
572
573
self .assertTrue (the_fields [1 ].repr )
573
574
self .assertEqual (the_fields [2 ].name , 'z' )
574
- self .assertEqual (the_fields [2 ].type , str )
575
+ self .assertEqual (the_fields [2 ].type , ' str' )
575
576
self .assertFalse (hasattr (C , 'z' ))
576
577
self .assertTrue (the_fields [2 ].init )
577
578
self .assertFalse (the_fields [2 ].repr )
@@ -757,11 +758,11 @@ class F:
757
758
def validate_class (cls ):
758
759
# First, check __annotations__, even though they're not
759
760
# function annotations.
760
- self .assertEqual (cls .__annotations__ ['i' ], int )
761
- self .assertEqual (cls .__annotations__ ['j' ], str )
762
- self .assertEqual (cls .__annotations__ ['k' ], F )
763
- self .assertEqual (cls .__annotations__ ['l' ], float )
764
- self .assertEqual (cls .__annotations__ ['z' ], complex )
761
+ self .assertEqual (cls .__annotations__ ['i' ], ' int' )
762
+ self .assertEqual (cls .__annotations__ ['j' ], ' str' )
763
+ self .assertEqual (cls .__annotations__ ['k' ], 'F' )
764
+ self .assertEqual (cls .__annotations__ ['l' ], ' float' )
765
+ self .assertEqual (cls .__annotations__ ['z' ], ' complex' )
765
766
766
767
# Verify __init__.
767
768
@@ -776,22 +777,22 @@ def validate_class(cls):
776
777
self .assertEqual (param .name , 'self' )
777
778
param = next (params )
778
779
self .assertEqual (param .name , 'i' )
779
- self .assertIs (param .annotation , int )
780
+ self .assertIs (param .annotation , ' int' )
780
781
self .assertEqual (param .default , inspect .Parameter .empty )
781
782
self .assertEqual (param .kind , inspect .Parameter .POSITIONAL_OR_KEYWORD )
782
783
param = next (params )
783
784
self .assertEqual (param .name , 'j' )
784
- self .assertIs (param .annotation , str )
785
+ self .assertIs (param .annotation , ' str' )
785
786
self .assertEqual (param .default , inspect .Parameter .empty )
786
787
self .assertEqual (param .kind , inspect .Parameter .POSITIONAL_OR_KEYWORD )
787
788
param = next (params )
788
789
self .assertEqual (param .name , 'k' )
789
- self .assertIs (param .annotation , F )
790
+ self .assertIs (param .annotation , 'F' )
790
791
# Don't test for the default, since it's set to MISSING.
791
792
self .assertEqual (param .kind , inspect .Parameter .POSITIONAL_OR_KEYWORD )
792
793
param = next (params )
793
794
self .assertEqual (param .name , 'l' )
794
- self .assertIs (param .annotation , float )
795
+ self .assertIs (param .annotation , ' float' )
795
796
# Don't test for the default, since it's set to MISSING.
796
797
self .assertEqual (param .kind , inspect .Parameter .POSITIONAL_OR_KEYWORD )
797
798
self .assertRaises (StopIteration , next , params )
@@ -1997,15 +1998,15 @@ def test_docstring_one_field(self):
1997
1998
class C :
1998
1999
x : int
1999
2000
2000
- self .assertDocStrEqual (C .__doc__ , "C(x:int)" )
2001
+ self .assertDocStrEqual (C .__doc__ , "C(x:' int' )" )
2001
2002
2002
2003
def test_docstring_two_fields (self ):
2003
2004
@dataclass
2004
2005
class C :
2005
2006
x : int
2006
2007
y : int
2007
2008
2008
- self .assertDocStrEqual (C .__doc__ , "C(x:int, y:int)" )
2009
+ self .assertDocStrEqual (C .__doc__ , "C(x:' int' , y:' int' )" )
2009
2010
2010
2011
def test_docstring_three_fields (self ):
2011
2012
@dataclass
@@ -2014,49 +2015,49 @@ class C:
2014
2015
y : int
2015
2016
z : str
2016
2017
2017
- self .assertDocStrEqual (C .__doc__ , "C(x:int, y:int, z:str)" )
2018
+ self .assertDocStrEqual (C .__doc__ , "C(x:' int' , y:' int' , z:' str' )" )
2018
2019
2019
2020
def test_docstring_one_field_with_default (self ):
2020
2021
@dataclass
2021
2022
class C :
2022
2023
x : int = 3
2023
2024
2024
- self .assertDocStrEqual (C .__doc__ , "C(x:int=3)" )
2025
+ self .assertDocStrEqual (C .__doc__ , "C(x:' int' =3)" )
2025
2026
2026
2027
def test_docstring_one_field_with_default_none (self ):
2027
2028
@dataclass
2028
2029
class C :
2029
2030
x : Union [int , type (None )] = None
2030
2031
2031
- self .assertDocStrEqual (C .__doc__ , "C(x:Optional [int] =None)" )
2032
+ self .assertDocStrEqual (C .__doc__ , "C(x:'Union [int, type(None)]' =None)" )
2032
2033
2033
2034
def test_docstring_list_field (self ):
2034
2035
@dataclass
2035
2036
class C :
2036
2037
x : List [int ]
2037
2038
2038
- self .assertDocStrEqual (C .__doc__ , "C(x:List[int])" )
2039
+ self .assertDocStrEqual (C .__doc__ , "C(x:' List[int]' )" )
2039
2040
2040
2041
def test_docstring_list_field_with_default_factory (self ):
2041
2042
@dataclass
2042
2043
class C :
2043
2044
x : List [int ] = field (default_factory = list )
2044
2045
2045
- self .assertDocStrEqual (C .__doc__ , "C(x:List[int]=<factory>)" )
2046
+ self .assertDocStrEqual (C .__doc__ , "C(x:' List[int]' =<factory>)" )
2046
2047
2047
2048
def test_docstring_deque_field (self ):
2048
2049
@dataclass
2049
2050
class C :
2050
2051
x : deque
2051
2052
2052
- self .assertDocStrEqual (C .__doc__ , "C(x:collections. deque)" )
2053
+ self .assertDocStrEqual (C .__doc__ , "C(x:' deque' )" )
2053
2054
2054
2055
def test_docstring_deque_field_with_default_factory (self ):
2055
2056
@dataclass
2056
2057
class C :
2057
2058
x : deque = field (default_factory = deque )
2058
2059
2059
- self .assertDocStrEqual (C .__doc__ , "C(x:collections. deque=<factory>)" )
2060
+ self .assertDocStrEqual (C .__doc__ , "C(x:' deque' =<factory>)" )
2060
2061
2061
2062
2062
2063
class TestInit (unittest .TestCase ):
@@ -2805,13 +2806,10 @@ class C:
2805
2806
2806
2807
class TestStringAnnotations (unittest .TestCase ):
2807
2808
def test_classvar (self ):
2808
- # Some expressions recognized as ClassVar really aren't. But
2809
- # if you're using string annotations, it's not an exact
2810
- # science.
2811
2809
# These tests assume that both "import typing" and "from
2812
2810
# typing import *" have been run in this file.
2813
2811
for typestr in ('ClassVar[int]' ,
2814
- 'ClassVar [int]'
2812
+ 'ClassVar [int]' ,
2815
2813
' ClassVar [int]' ,
2816
2814
'ClassVar' ,
2817
2815
' ClassVar ' ,
@@ -2822,17 +2820,9 @@ def test_classvar(self):
2822
2820
'typing. ClassVar[str]' ,
2823
2821
'typing.ClassVar [str]' ,
2824
2822
'typing.ClassVar [ str]' ,
2825
-
2826
- # Not syntactically valid, but these will
2827
- # be treated as ClassVars.
2828
- 'typing.ClassVar.[int]' ,
2829
- 'typing.ClassVar+' ,
2830
2823
):
2831
2824
with self .subTest (typestr = typestr ):
2832
- @dataclass
2833
- class C :
2834
- x : typestr
2835
-
2825
+ C = dataclass (type ("C" , (), {"__annotations__" : {"x" : typestr }}))
2836
2826
# x is a ClassVar, so C() takes no args.
2837
2827
C ()
2838
2828
@@ -2853,9 +2843,7 @@ def test_isnt_classvar(self):
2853
2843
'typingxClassVar[str]' ,
2854
2844
):
2855
2845
with self .subTest (typestr = typestr ):
2856
- @dataclass
2857
- class C :
2858
- x : typestr
2846
+ C = dataclass (type ("C" , (), {"__annotations__" : {"x" : typestr }}))
2859
2847
2860
2848
# x is not a ClassVar, so C() takes one arg.
2861
2849
self .assertEqual (C (10 ).x , 10 )
@@ -2882,9 +2870,8 @@ def test_initvar(self):
2882
2870
'dataclasses.InitVar+' ,
2883
2871
):
2884
2872
with self .subTest (typestr = typestr ):
2885
- @dataclass
2886
- class C :
2887
- x : typestr
2873
+ C = dataclass (type ("C" , (), {"__annotations__" : {"x" : typestr }}))
2874
+
2888
2875
2889
2876
# x is an InitVar, so doesn't create a member.
2890
2877
with self .assertRaisesRegex (AttributeError ,
@@ -2898,30 +2885,22 @@ def test_isnt_initvar(self):
2898
2885
'typing.xInitVar[int]' ,
2899
2886
):
2900
2887
with self .subTest (typestr = typestr ):
2901
- @dataclass
2902
- class C :
2903
- x : typestr
2888
+ C = dataclass (type ("C" , (), {"__annotations__" : {"x" : typestr }}))
2904
2889
2905
2890
# x is not an InitVar, so there will be a member x.
2906
2891
self .assertEqual (C (10 ).x , 10 )
2907
2892
2908
2893
def test_classvar_module_level_import (self ):
2909
2894
from test import dataclass_module_1
2910
- from test import dataclass_module_1_str
2911
2895
from test import dataclass_module_2
2912
- from test import dataclass_module_2_str
2913
2896
2914
- for m in (dataclass_module_1 , dataclass_module_1_str ,
2915
- dataclass_module_2 , dataclass_module_2_str ,
2916
- ):
2897
+ for m in (dataclass_module_1 ,
2898
+ dataclass_module_2 ):
2917
2899
with self .subTest (m = m ):
2918
2900
# There's a difference in how the ClassVars are
2919
2901
# interpreted when using string annotations or
2920
2902
# not. See the imported modules for details.
2921
- if m .USING_STRINGS :
2922
- c = m .CV (10 )
2923
- else :
2924
- c = m .CV ()
2903
+ c = m .CV (10 )
2925
2904
self .assertEqual (c .cv0 , 20 )
2926
2905
2927
2906
@@ -2937,14 +2916,9 @@ def test_classvar_module_level_import(self):
2937
2916
# not an instance field.
2938
2917
getattr (c , field_name )
2939
2918
2940
- if m .USING_STRINGS :
2941
- # iv4 is interpreted as a normal field.
2942
- self .assertIn ('not_iv4' , c .__dict__ )
2943
- self .assertEqual (c .not_iv4 , 4 )
2944
- else :
2945
- # iv4 is interpreted as an InitVar, so it
2946
- # won't exist on the instance.
2947
- self .assertNotIn ('not_iv4' , c .__dict__ )
2919
+ # iv4 is interpreted as a normal field.
2920
+ self .assertIn ('not_iv4' , c .__dict__ )
2921
+ self .assertEqual (c .not_iv4 , 4 )
2948
2922
2949
2923
def test_text_annotations (self ):
2950
2924
from test import dataclass_textanno
0 commit comments