1717 if isinstance (o , type )]
1818EXCEPTION_TYPES = [cls for cls in BUILTIN_TYPES
1919 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' ))]
2023
2124
2225class _GetXIDataTests (unittest .TestCase ):
@@ -40,16 +43,42 @@ def iter_roundtrip_values(self, values, *, mode=None):
4043 got = _testinternalcapi .restore_crossinterp_data (xid )
4144 yield obj , got
4245
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-
4846 def assert_roundtrip_identical (self , values , * , mode = None ):
4947 for obj , got in self .iter_roundtrip_values (values , mode = mode ):
5048 # XXX What about between interpreters?
5149 self .assertIs (got , obj )
5250
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+
5382 def assert_not_shareable (self , values , exctype = None , * , mode = None ):
5483 mode = self ._resolve_mode (mode )
5584 for obj in values :
@@ -66,6 +95,197 @@ def _resolve_mode(self, mode):
6695 return mode
6796
6897
98+ class MarshalTests (_GetXIDataTests ):
99+
100+ MODE = 'marshal'
101+
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+
69289class ShareableTypeTests (_GetXIDataTests ):
70290
71291 MODE = 'xidata'
@@ -184,6 +404,7 @@ def test_builtin_function(self):
184404
185405 def test_function_like (self ):
186406 self .assert_not_shareable (defs .FUNCTION_LIKE )
407+ self .assert_not_shareable (defs .FUNCTION_LIKE_APPLIED )
187408
188409 def test_builtin_wrapper (self ):
189410 _wrappers = {
@@ -243,9 +464,7 @@ def test_class(self):
243464 def test_builtin_type (self ):
244465 self .assert_not_shareable ([
245466 * 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 ,
249468 ])
250469
251470 def test_exception (self ):
0 commit comments