17
17
if isinstance (o , type )]
18
18
EXCEPTION_TYPES = [cls for cls in BUILTIN_TYPES
19
19
if issubclass (cls , BaseException )]
20
+ OTHER_TYPES = [o for n , o in vars (types ).items ()
21
+ if (isinstance (o , type ) and
22
+ n not in ('DynamicClassAttribute' , '_GeneratorWrapper' ))]
20
23
21
24
22
25
class _GetXIDataTests (unittest .TestCase ):
@@ -40,16 +43,42 @@ def iter_roundtrip_values(self, values, *, mode=None):
40
43
got = _testinternalcapi .restore_crossinterp_data (xid )
41
44
yield obj , got
42
45
43
- def assert_roundtrip_equal (self , values , * , mode = None ):
44
- for obj , got in self .iter_roundtrip_values (values , mode = mode ):
45
- self .assertEqual (got , obj )
46
- self .assertIs (type (got ), type (obj ))
47
-
48
46
def assert_roundtrip_identical (self , values , * , mode = None ):
49
47
for obj , got in self .iter_roundtrip_values (values , mode = mode ):
50
48
# XXX What about between interpreters?
51
49
self .assertIs (got , obj )
52
50
51
+ def assert_roundtrip_equal (self , values , * , mode = None , expecttype = None ):
52
+ for obj , got in self .iter_roundtrip_values (values , mode = mode ):
53
+ self .assertEqual (got , obj )
54
+ self .assertIs (type (got ),
55
+ type (obj ) if expecttype is None else expecttype )
56
+
57
+ # def assert_roundtrip_equal_not_identical(self, values, *,
58
+ # mode=None, expecttype=None):
59
+ # mode = self._resolve_mode(mode)
60
+ # for obj in values:
61
+ # cls = type(obj)
62
+ # with self.subTest(obj):
63
+ # got = self._get_roundtrip(obj, mode)
64
+ # self.assertIsNot(got, obj)
65
+ # self.assertIs(type(got), type(obj))
66
+ # self.assertEqual(got, obj)
67
+ # self.assertIs(type(got),
68
+ # cls if expecttype is None else expecttype)
69
+ #
70
+ # def assert_roundtrip_not_equal(self, values, *, mode=None, expecttype=None):
71
+ # mode = self._resolve_mode(mode)
72
+ # for obj in values:
73
+ # cls = type(obj)
74
+ # with self.subTest(obj):
75
+ # got = self._get_roundtrip(obj, mode)
76
+ # self.assertIsNot(got, obj)
77
+ # self.assertIs(type(got), type(obj))
78
+ # self.assertNotEqual(got, obj)
79
+ # self.assertIs(type(got),
80
+ # cls if expecttype is None else expecttype)
81
+
53
82
def assert_not_shareable (self , values , exctype = None , * , mode = None ):
54
83
mode = self ._resolve_mode (mode )
55
84
for obj in values :
@@ -66,6 +95,197 @@ def _resolve_mode(self, mode):
66
95
return mode
67
96
68
97
98
+ class MarshalTests (_GetXIDataTests ):
99
+
100
+ MODE = 'marshal'
101
+
<
10000
/td>
102
+ def test_simple_builtin_singletons (self ):
103
+ self .assert_roundtrip_identical ([
104
+ True ,
105
+ False ,
106
+ None ,
107
+ Ellipsis ,
108
+ ])
109
+ self .assert_not_shareable ([
110
+ NotImplemented ,
111
+ ])
112
+
113
+ def test_simple_builtin_objects (self ):
114
+ self .assert_roundtrip_equal ([
115
+ # int
116
+ * range (- 1 , 258 ),
117
+ sys .maxsize + 1 ,
118
+ sys .maxsize ,
119
+ - sys .maxsize - 1 ,
120
+ - sys .maxsize - 2 ,
121
+ 2 ** 1000 ,
122
+ # complex
123
+ 1 + 2j ,
124
+ # float
125
+ 0.0 ,
126
+ 1.1 ,
127
+ - 1.0 ,
128
+ 0.12345678 ,
129
+ - 0.12345678 ,
130
+ # bytes
131
+ * (i .to_bytes (2 , 'little' , signed = True )
132
+ for i in range (- 1 , 258 )),
133
+ b'hello world' ,
134
+ # str
135
+ 'hello world' ,
136
+ '你好世界' ,
137
+ '' ,
138
+ ])
139
+ self .assert_not_shareable ([
140
+ object (),
141
+ types .SimpleNamespace (),
142
+ ])
143
+
144
+ def test_bytearray (self ):
145
+ # bytearray is special because it unmarshals to bytes, not bytearray.
146
+ self .assert_roundtrip_equal ([
147
+ bytearray (),
148
+ bytearray (b'hello world' ),
149
+ ], expecttype = bytes )
150
+
151
+ def test_compound_immutable_builtin_objects (self ):
152
+ self .assert_roundtrip_equal ([
153
+ # tuple
154
+ (),
155
+ (1 ,),
156
+ ("hello" , "world" ),
157
+ (1 , True , "hello" ),
158
+ # frozenset
159
+ frozenset ([1 , 2 , 3 ]),
160
+ ])
161
+ # nested
162
+ self .assert_roundtrip_equal ([
163
+ # tuple
164
+ ((1 ,),),
165
+ ((1 , 2 ), (3 , 4 )),
166
+ ((1 , 2 ), (3 , 4 ), (5 , 6 )),
167
+ # frozenset
168
+ frozenset ([frozenset ([1 ]), frozenset ([2 ]), frozenset ([3 ])]),
169
+ ])
170
+
171
+ def test_compound_mutable_builtin_objects (self ):
172
+ self .assert_roundtrip_equal ([
173
+ # list
174
+ [],
175
+ [1 , 2 , 3 ],
176
+ # dict
177
+ {},
178
+ {1 : 7 , 2 : 8 , 3 : 9 },
179
+ # set
180
+ set (),
181
+ {1 , 2 , 3 },
182
+ ])
183
+ # nested
184
+ self .assert_roundtrip_equal ([
185
+ [[1 ], [2 ], [3 ]],
186
+ {1 : {'a' : True }, 2 : {'b' : False }},
187
+ {(1 , 2 , 3 ,)},
188
+ ])
189
+
190
+ def test_compound_builtin_objects_with_bad_items (self ):
191
+ bogus = object ()
192
+ self .assert_not_shareable ([
193
+ (bogus ,),
194
+ frozenset ([bogus ]),
195
+ [bogus ],
196
+ {bogus : True },
197
+ {True : bogus },
198
+ {bogus },
199
+ ])
200
+
201
+ def test_builtin_code (self ):
202
+ self .assert_roundtrip_equal ([
203
+ * (f .__code__ for f in defs .FUNCTIONS ),
204
+ * (f .__code__ for f in defs .FUNCTION_LIKE ),
205
+ ])
206
+
207
+ def test_builtin_type (self ):
208
+ shareable = [
209
+ StopIteration ,
210
+ ]
211
+ types = [
212
+ * BUILTIN_TYPES ,
213
+ * OTHER_TYPES ,
214
+ ]
215
+ self .assert_not_shareable (cls for cls in types
216
+ if cls not in shareable )
217
+ self .assert_roundtrip_identical (cls for cls in types
218
+ if cls in shareable )
219
+
220
+ def test_builtin_function (self ):
221
+ functions = [
222
+ len ,
223
+ sys .is_finalizing ,
224
+ sys .exit ,
225
+ _testinternalcapi .get_crossinterp_data ,
226
+ ]
227
+ for func in functions :
228
+ assert type (func ) is types .BuiltinFunctionType , func
229
+
230
+ self .assert_not_shareable (functions )
231
+
232
+ def test_builtin_exception (self ):
233
+ msg = 'error!'
234
+ try :
235
+ raise Exception
236
+ except Exception as exc :
237
+ caught = exc
238
+ special = {
239
+ BaseExceptionGroup : (msg , [caught ]),
240
+ ExceptionGroup : (msg , [caught ]),
241
+ # UnicodeError: (None, msg, None, None, None),
242
+ UnicodeEncodeError : ('utf-8' , '' , 1 , 3 , msg ),
243
+ UnicodeDecodeError : ('utf-8' , b'' , 1 , 3 , msg ),
244
+ UnicodeTranslateError : ('' , 1 , 3 , msg ),
245
+ }
246
+ exceptions = []
247
+ for cls in EXCEPTION_TYPES :
248
+ args = special .get (cls ) or (msg ,)
249
+ exceptions .append (cls (* args ))
250
+
251
+ self .assert_not_shareable (exceptions )
252
+ # Note that StopIteration (the type) can be marshalled,
253
+ # but its instances cannot.
254
+
255
+ def test_module (self ):
256
+ assert type (sys ) is types .ModuleType , type (sys )
257
+ assert type (defs ) is types .ModuleType , type (defs )
258
+ assert type (unittest ) is types .ModuleType , type (defs )
259
+
260
+ assert 'emptymod' not in sys .modules
261
+ with import_helper .ready_to_import ('emptymod' , '' ):
262
+ import emptymod
263
+
264
+ self .assert_not_shareable ([
265
+ sys ,
266
+ defs ,
267
+ unittest ,
268
+ emptymod ,
269
+ ])
270
+
271
+ def test_user_class (self ):
272
+ self .assert_not_shareable (defs .TOP_CLASSES )
273
+
274
+ instances = []
275
+ for cls , args in defs .TOP_CLASSES .items ():
276
+ instances .append (cls (* args ))
277
+ self .assert_not_shareable (instances )
278
+
279
+ def test_user_function (self ):
280
+ self .assert_not_shareable (defs .TOP_FUNCTIONS )
281
+
282
+ def test_user_exception (self ):
283
+ self .assert_not_shareable ([
284
+ defs .MimimalError ('error!' ),
285
+ defs .RichError ('error!' , 42 ),
286
+ ])
287
+
288
+
69
289
class ShareableTypeTests (_GetXIDataTests ):
70
290
71
291
MODE = 'xidata'
@@ -184,6 +404,7 @@ def test_builtin_function(self):
184
404
185
405
def test_function_like (self ):
186
406
self .assert_not_shareable (defs .FUNCTION_LIKE )
407
+ self .assert_not_shareable (defs .FUNCTION_LIKE_APPLIED )
187
408
188
409
def test_builtin_wrapper (self ):
189
410
_wrappers = {
@@ -243,9 +464,7 @@ def test_class(self):
243
464
def test_builtin_type (self ):
244
465
self .assert_not_shareable ([
245
466
* BUILTIN_TYPES ,
246
- * (o for n , o in vars (types ).items ()
247
- if (isinstance (o , type ) and
248
- n not in ('DynamicClassAttribute' , '_GeneratorWrapper' ))),
467
+ * OTHER_TYPES ,
249
468
])
250
469
251
470
def test_exception (self ):
0 commit comments