50
50
51
51
from .testutils import subprocess_pickle_echo
52
52
from .testutils import assert_run_python_script
53
+ from .testutils import subprocess_worker
53
54
54
55
55
56
_TEST_GLOBAL_VARIABLE = "default_value"
@@ -2121,6 +2122,12 @@ def test_pickle_dynamic_typevar(self):
2121
2122
for attr in attr_list :
2122
2123
assert getattr (T , attr ) == getattr (depickled_T , attr )
2123
2124
2125
+ def test_pickle_dynamic_typevar_memoization (self ):
2126
+ T = typing .TypeVar ('T' )
2127
+ depickled_T1 , depickled_T2 = pickle_depickle ((T , T ),
2128
+ protocol = self .protocol )
2129
+ assert depickled_T1 is depickled_T2
2130
+
2124
2131
def test_pickle_importable_typevar (self ):
2125
2132
from .mypkg import T
2126
2133
T1 = pickle_depickle (T , protocol = self .protocol )
@@ -2130,6 +2137,61 @@ def test_pickle_importable_typevar(self):
2130
2137
from typing import AnyStr
2131
2138
assert AnyStr is pickle_depickle (AnyStr , protocol = self .protocol )
2132
2139
2140
+ @unittest .skipIf (sys .version_info < (3 , 7 ),
2141
+ "Pickling generics not supported below py37" )
2142
+ def test_generic_type (self ):
2143
+ T = typing .TypeVar ('T' )
2144
+
2145
+ class C (typing .Generic [T ]):
2146
+ pass
2147
+
2148
+ assert pickle_depickle (C , protocol = self .protocol ) is C
2149
+ assert pickle_depickle (C [int ], protocol = self .protocol ) is C [int ]
2150
+
2151
+ with subprocess_worker (protocol = self .protocol ) as worker :
2152
+
2153
+ def check_generic (generic , origin , type_value ):
2154
+ assert generic .__origin__ is origin
2155
+ assert len (generic .__args__ ) == 1
2156
+ assert generic .__args__ [0 ] is type_value
2157
+
2158
+ assert len (origin .__orig_bases__ ) == 1
2159
+ ob = origin .__orig_bases__ [0 ]
2160
+ assert ob .__origin__ is typing .Generic
2161
+ assert len (ob .__parameters__ ) == 1
2162
+
2163
+ return "ok"
2164
+
2165
+ assert check_generic (C [int ], C , int ) == "ok"
2166
+ assert worker .run (check_generic , C [int ], C , int ) == "ok"
2167
+
2168
+ @unittest .skipIf (sys .version_info < (3 , 7 ),
2169
+ "Pickling type hints not supported below py37" )
2170
+ def test_locally_defined_class_with_type_hints (self ):
2171
+ with subprocess_worker (protocol = self .protocol ) as worker :
2172
+ for type_ in _all_types_to_test ():
2173
+ # The type annotation syntax causes a SyntaxError on Python 3.5
2174
+ code = textwrap .dedent ("""\
2175
+ class MyClass:
2176
+ attribute: type_
2177
+
2178
+ def method(self, arg: type_) -> type_:
2179
+ return arg
2180
+ """ )
2181
+ ns = {"type_" : type_ }
2182
+ exec (code , ns )
2183
+ MyClass = ns ["MyClass" ]
2184
+
2185
+ def check_annotations (obj , expected_type ):
2186
+ assert obj .__annotations__ ["attribute" ] is expected_type
2187
+ assert obj .method .__annotations__ ["arg" ] is expected_type
2188
+ assert obj .method .__annotations__ ["return" ] is expected_type
2189
+ return "ok"
2190
+
2191
+ obj = MyClass ()
2192
+ assert check_annotations (obj , type_ ) == "ok"
2193
+ assert worker .run (check_annotations , obj , type_ ) == "ok"
2194
+
2133
2195
2134
2196
class Protocol2CloudPickleTest (CloudPickleTest ):
2135
2197
@@ -2161,5 +2223,28 @@ def test_lookup_module_and_qualname_stdlib_typevar():
2161
2223
assert name == 'AnyStr'
2162
2224
2163
2225
2226
+ def _all_types_to_test ():
2227
+ T = typing .TypeVar ('T' )
2228
+
2229
+ class C (typing .Generic [T ]):
2230
+ pass
2231
+
2232
+ return [
2233
+ C , C [int ],
2234
+ T , typing .Any , typing .NoReturn , typing .Optional ,
2235
+ typing .Generic , typing .Union , typing .ClassVar ,
2236
+ typing .Optional [int ],
2237
+ typing .Generic [T ],
2238
+ typing .Callable [[int ], typing .Any ],
2239
+ typing .Callable [..., typing .Any ],
2240
+ typing .Callable [[], typing .Any ],
2241
+ typing .Tuple [int , ...],
2242
+ typing .Tuple [int , C [int ]],
2243
+ typing .ClassVar [C [int ]],
2244
+ typing .List [int ],
2245
+ typing .Dict [int , str ],
2246
+ ]
2247
+
2248
+
2164
2249
if __name__ == '__main__' :
2165
2250
unittest .main ()
0 commit comments