blob: 36970fefe06ca45f73540a09d35f3845eb0ef74f [file] [log] [blame]
Serhiy Storchakabfe18242015-03-31 13:12:37 +03001from _compat_pickle import (IMPORT_MAPPING, REVERSE_IMPORT_MAPPING,
2 NAME_MAPPING, REVERSE_NAME_MAPPING)
3import builtins
Jeremy Hyltonbe467e52000-09-15 15:14:51 +00004import pickle
Guido van Rossumcfe5f202007-05-08 21:26:54 +00005import io
Antoine Pitrou8d3c2902012-03-04 18:31:48 +01006import collections
Serhiy Storchaka5bbd2312014-12-16 19:39:08 +02007import struct
8import sys
Tim Peters47a6b132003-01-28 22:34:11 +00009
Serhiy Storchaka5bbd2312014-12-16 19:39:08 +020010import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +000011from test import support
Jeremy Hylton66426532001-10-15 21:38:56 +000012
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030013from test.pickletester import AbstractUnpickleTests
Tim Peters47a6b132003-01-28 22:34:11 +000014from test.pickletester import AbstractPickleTests
Tim Peters47a6b132003-01-28 22:34:11 +000015from test.pickletester import AbstractPickleModuleTests
16from test.pickletester import AbstractPersistentPicklerTests
Serhiy Storchakadec25af2016-07-17 11:24:17 +030017from test.pickletester import AbstractIdentityPersistentPicklerTests
Collin Winter771d8342009-04-16 03:18:06 +000018from test.pickletester import AbstractPicklerUnpicklerObjectTests
Antoine Pitrou8d3c2902012-03-04 18:31:48 +010019from test.pickletester import AbstractDispatchTableTests
Antoine Pitrou82be19f2011-08-29 23:09:33 +020020from test.pickletester import BigmemPickleTests
Tim Peters47a6b132003-01-28 22:34:11 +000021
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000022try:
23 import _pickle
24 has_c_implementation = True
25except ImportError:
26 has_c_implementation = False
Jeremy Hylton66426532001-10-15 21:38:56 +000027
Guido van Rossum98297ee2007-11-06 21:34:58 +000028
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000029class PickleTests(AbstractPickleModuleTests):
30 pass
Guido van Rossum5d9113d2003-01-29 17:58:45 +000031
Tim Peterse0c446b2001-10-18 21:57:37 +000032
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030033class PyUnpicklerTests(AbstractUnpickleTests):
34
35 unpickler = pickle._Unpickler
Serhiy Storchakae9b30742015-11-23 15:17:43 +020036 bad_stack_errors = (IndexError,)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020037 truncated_errors = (pickle.UnpicklingError, EOFError,
38 AttributeError, ValueError,
39 struct.error, IndexError, ImportError)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030040
41 def loads(self, buf, **kwds):
42 f = io.BytesIO(buf)
43 u = self.unpickler(f, **kwds)
44 return u.load()
45
46
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000047class PyPicklerTests(AbstractPickleTests):
Jeremy Hylton66426532001-10-15 21:38:56 +000048
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000049 pickler = pickle._Pickler
50 unpickler = pickle._Unpickler
Jeremy Hylton66426532001-10-15 21:38:56 +000051
Guido van Rossumf4169812008-03-17 22:56:06 +000052 def dumps(self, arg, proto=None):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000053 f = io.BytesIO()
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000054 p = self.pickler(f, proto)
Jeremy Hylton66426532001-10-15 21:38:56 +000055 p.dump(arg)
56 f.seek(0)
Guido van Rossumcfe5f202007-05-08 21:26:54 +000057 return bytes(f.read())
Jeremy Hylton66426532001-10-15 21:38:56 +000058
Alexander Belopolskyec8f0df2011-02-24 20:34:38 +000059 def loads(self, buf, **kwds):
Guido van Rossumcfe5f202007-05-08 21:26:54 +000060 f = io.BytesIO(buf)
Alexander Belopolskyec8f0df2011-02-24 20:34:38 +000061 u = self.unpickler(f, **kwds)
Jeremy Hylton66426532001-10-15 21:38:56 +000062 return u.load()
63
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000064
Serhiy Storchakac6b54b42015-09-29 15:33:24 +030065class InMemoryPickleTests(AbstractPickleTests, AbstractUnpickleTests,
66 BigmemPickleTests):
Antoine Pitrouea99c5c2010-09-09 18:33:21 +000067
68 pickler = pickle._Pickler
69 unpickler = pickle._Unpickler
Serhiy Storchakae9b30742015-11-23 15:17:43 +020070 bad_stack_errors = (pickle.UnpicklingError, IndexError)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +020071 truncated_errors = (pickle.UnpicklingError, EOFError,
72 AttributeError, ValueError,
73 struct.error, IndexError, ImportError)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +000074
Antoine Pitrou82be19f2011-08-29 23:09:33 +020075 def dumps(self, arg, protocol=None):
76 return pickle.dumps(arg, protocol)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +000077
Alexander Belopolskyec8f0df2011-02-24 20:34:38 +000078 def loads(self, buf, **kwds):
79 return pickle.loads(buf, **kwds)
Antoine Pitrouea99c5c2010-09-09 18:33:21 +000080
81
Serhiy Storchakadec25af2016-07-17 11:24:17 +030082class PersistentPicklerUnpicklerMixin(object):
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000083
Guido van Rossumf4169812008-03-17 22:56:06 +000084 def dumps(self, arg, proto=None):
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000085 class PersPickler(self.pickler):
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000086 def persistent_id(subself, obj):
87 return self.persistent_id(obj)
Guido van Rossumcfe5f202007-05-08 21:26:54 +000088 f = io.BytesIO()
Guido van Rossum9d32bb12003-01-28 03:51:53 +000089 p = PersPickler(f, proto)
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000090 p.dump(arg)
Serhiy Storchakadec25af2016-07-17 11:24:17 +030091 return f.getvalue()
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000092
Alexander Belopolskyec8f0df2011-02-24 20:34:38 +000093 def loads(self, buf, **kwds):
Alexandre Vassalottica2d6102008-06-12 18:26:05 +000094 class PersUnpickler(self.unpickler):
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000095 def persistent_load(subself, obj):
96 return self.persistent_load(obj)
Guido van Rossumcfe5f202007-05-08 21:26:54 +000097 f = io.BytesIO(buf)
Alexander Belopolskyec8f0df2011-02-24 20:34:38 +000098 u = PersUnpickler(f, **kwds)
Jeremy Hylton5e0f4e72002-11-13 22:01:27 +000099 return u.load()
100
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000101
Serhiy Storchakadec25af2016-07-17 11:24:17 +0300102class PyPersPicklerTests(AbstractPersistentPicklerTests,
103 PersistentPicklerUnpicklerMixin):
104
105 pickler = pickle._Pickler
106 unpickler = pickle._Unpickler
107
108
109class PyIdPersPicklerTests(AbstractIdentityPersistentPicklerTests,
110 PersistentPicklerUnpicklerMixin):
111
112 pickler = pickle._Pickler
113 unpickler = pickle._Unpickler
114
115
Collin Winter771d8342009-04-16 03:18:06 +0000116class PyPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests):
117
118 pickler_class = pickle._Pickler
119 unpickler_class = pickle._Unpickler
120
121
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100122class PyDispatchTableTests(AbstractDispatchTableTests):
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -0800123
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100124 pickler_class = pickle._Pickler
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -0800125
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100126 def get_dispatch_table(self):
127 return pickle.dispatch_table.copy()
128
129
130class PyChainDispatchTableTests(AbstractDispatchTableTests):
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -0800131
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100132 pickler_class = pickle._Pickler
Alexandre Vassalottid05c9ff2013-12-07 01:09:27 -0800133
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100134 def get_dispatch_table(self):
135 return collections.ChainMap({}, pickle.dispatch_table)
136
137
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000138if has_c_implementation:
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300139 class CUnpicklerTests(PyUnpicklerTests):
140 unpickler = _pickle.Unpickler
Serhiy Storchakae9b30742015-11-23 15:17:43 +0200141 bad_stack_errors = (pickle.UnpicklingError,)
Serhiy Storchaka7279bef2015-11-29 13:12:10 +0200142 truncated_errors = (pickle.UnpicklingError, EOFError,
143 AttributeError, ValueError)
Serhiy Storchakac6b54b42015-09-29 15:33:24 +0300144
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000145 class CPicklerTests(PyPicklerTests):
146 pickler = _pickle.Pickler
147 unpickler = _pickle.Unpickler
148
149 class CPersPicklerTests(PyPersPicklerTests):
150 pickler = _pickle.Pickler
151 unpickler = _pickle.Unpickler
152
Serhiy Storchakadec25af2016-07-17 11:24:17 +0300153 class CIdPersPicklerTests(PyIdPersPicklerTests):
154 pickler = _pickle.Pickler
155 unpickler = _pickle.Unpickler
156
Collin Winter771d8342009-04-16 03:18:06 +0000157 class CDumpPickle_LoadPickle(PyPicklerTests):
158 pickler = _pickle.Pickler
159 unpickler = pickle._Unpickler
160
161 class DumpPickle_CLoadPickle(PyPicklerTests):
162 pickler = pickle._Pickler
163 unpickler = _pickle.Unpickler
164
165 class CPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests):
166 pickler_class = _pickle.Pickler
167 unpickler_class = _pickle.Unpickler
168
Christian Heimesa24b4d22013-07-01 15:17:45 +0200169 def test_issue18339(self):
170 unpickler = self.unpickler_class(io.BytesIO())
Christian Heimes21782482013-07-01 23:00:13 +0200171 with self.assertRaises(TypeError):
172 unpickler.memo = object
Christian Heimesa24b4d22013-07-01 15:17:45 +0200173 # used to cause a segfault
Christian Heimes21782482013-07-01 23:00:13 +0200174 with self.assertRaises(ValueError):
175 unpickler.memo = {-1: None}
Christian Heimesa24b4d22013-07-01 15:17:45 +0200176 unpickler.memo = {1: None}
177
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100178 class CDispatchTableTests(AbstractDispatchTableTests):
179 pickler_class = pickle.Pickler
180 def get_dispatch_table(self):
181 return pickle.dispatch_table.copy()
182
183 class CChainDispatchTableTests(AbstractDispatchTableTests):
184 pickler_class = pickle.Pickler
185 def get_dispatch_table(self):
186 return collections.ChainMap({}, pickle.dispatch_table)
187
Serhiy Storchaka5bbd2312014-12-16 19:39:08 +0200188 @support.cpython_only
189 class SizeofTests(unittest.TestCase):
190 check_sizeof = support.check_sizeof
191
192 def test_pickler(self):
193 basesize = support.calcobjsize('5P2n3i2n3iP')
194 p = _pickle.Pickler(io.BytesIO())
195 self.assertEqual(object.__sizeof__(p), basesize)
196 MT_size = struct.calcsize('3nP0n')
197 ME_size = struct.calcsize('Pn0P')
198 check = self.check_sizeof
199 check(p, basesize +
200 MT_size + 8 * ME_size + # Minimal memo table size.
201 sys.getsizeof(b'x'*4096)) # Minimal write buffer size.
202 for i in range(6):
203 p.dump(chr(i))
204 check(p, basesize +
205 MT_size + 32 * ME_size + # Size of memo table required to
206 # save references to 6 objects.
207 0) # Write buffer is cleared after every dump().
208
209 def test_unpickler(self):
210 basesize = support.calcobjsize('2Pn2P 2P2n2i5P 2P3n6P2n2i')
211 unpickler = _pickle.Unpickler
212 P = struct.calcsize('P') # Size of memo table entry.
213 n = struct.calcsize('n') # Size of mark table entry.
214 check = self.check_sizeof
215 for encoding in 'ASCII', 'UTF-16', 'latin-1':
216 for errors in 'strict', 'replace':
217 u = unpickler(io.BytesIO(),
218 encoding=encoding, errors=errors)
219 self.assertEqual(object.__sizeof__(u), basesize)
220 check(u, basesize +
221 32 * P + # Minimal memo table size.
222 len(encoding) + 1 + len(errors) + 1)
223
224 stdsize = basesize + len('ASCII') + 1 + len('strict') + 1
225 def check_unpickler(data, memo_size, marks_size):
226 dump = pickle.dumps(data)
227 u = unpickler(io.BytesIO(dump),
228 encoding='ASCII', errors='strict')
229 u.load()
230 check(u, stdsize + memo_size * P + marks_size * n)
231
232 check_unpickler(0, 32, 0)
233 # 20 is minimal non-empty mark stack size.
234 check_unpickler([0] * 100, 32, 20)
235 # 128 is memo table size required to save references to 100 objects.
236 check_unpickler([chr(i) for i in range(100)], 128, 20)
237 def recurse(deep):
238 data = 0
239 for i in range(deep):
240 data = [data, data]
241 return data
242 check_unpickler(recurse(0), 32, 0)
243 check_unpickler(recurse(1), 32, 20)
244 check_unpickler(recurse(20), 32, 58)
245 check_unpickler(recurse(50), 64, 58)
246 check_unpickler(recurse(100), 128, 134)
247
248 u = unpickler(io.BytesIO(pickle.dumps('a', 0)),
249 encoding='ASCII', errors='strict')
250 u.load()
251 check(u, stdsize + 32 * P + 2 + 1)
252
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000253
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300254ALT_IMPORT_MAPPING = {
255 ('_elementtree', 'xml.etree.ElementTree'),
256 ('cPickle', 'pickle'),
Serhiy Storchaka5c1d9d22016-01-18 22:33:44 +0200257 ('StringIO', 'io'),
258 ('cStringIO', 'io'),
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300259}
260
261ALT_NAME_MAPPING = {
262 ('__builtin__', 'basestring', 'builtins', 'str'),
263 ('exceptions', 'StandardError', 'builtins', 'Exception'),
264 ('UserDict', 'UserDict', 'collections', 'UserDict'),
265 ('socket', '_socketobject', 'socket', 'SocketType'),
266}
267
268def mapping(module, name):
269 if (module, name) in NAME_MAPPING:
270 module, name = NAME_MAPPING[(module, name)]
271 elif module in IMPORT_MAPPING:
272 module = IMPORT_MAPPING[module]
273 return module, name
274
275def reverse_mapping(module, name):
276 if (module, name) in REVERSE_NAME_MAPPING:
277 module, name = REVERSE_NAME_MAPPING[(module, name)]
278 elif module in REVERSE_IMPORT_MAPPING:
279 module = REVERSE_IMPORT_MAPPING[module]
280 return module, name
281
282def getmodule(module):
283 try:
284 return sys.modules[module]
285 except KeyError:
Serhiy Storchakab9100e52015-03-31 16:49:26 +0300286 try:
287 __import__(module)
288 except AttributeError as exc:
289 if support.verbose:
290 print("Can't import module %r: %s" % (module, exc))
291 raise ImportError
292 except ImportError as exc:
293 if support.verbose:
294 print(exc)
295 raise
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300296 return sys.modules[module]
297
298def getattribute(module, name):
299 obj = getmodule(module)
300 for n in name.split('.'):
301 obj = getattr(obj, n)
302 return obj
303
304def get_exceptions(mod):
305 for name in dir(mod):
306 attr = getattr(mod, name)
307 if isinstance(attr, type) and issubclass(attr, BaseException):
308 yield name, attr
309
310class CompatPickleTests(unittest.TestCase):
311 def test_import(self):
312 modules = set(IMPORT_MAPPING.values())
313 modules |= set(REVERSE_IMPORT_MAPPING)
314 modules |= {module for module, name in REVERSE_NAME_MAPPING}
315 modules |= {module for module, name in NAME_MAPPING.values()}
316 for module in modules:
317 try:
318 getmodule(module)
Serhiy Storchakab9100e52015-03-31 16:49:26 +0300319 except ImportError:
320 pass
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300321
322 def test_import_mapping(self):
323 for module3, module2 in REVERSE_IMPORT_MAPPING.items():
324 with self.subTest((module3, module2)):
325 try:
326 getmodule(module3)
Serhiy Storchakab9100e52015-03-31 16:49:26 +0300327 except ImportError:
328 pass
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300329 if module3[:1] != '_':
330 self.assertIn(module2, IMPORT_MAPPING)
331 self.assertEqual(IMPORT_MAPPING[module2], module3)
332
333 def test_name_mapping(self):
334 for (module3, name3), (module2, name2) in REVERSE_NAME_MAPPING.items():
335 with self.subTest(((module3, name3), (module2, name2))):
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300336 if (module2, name2) == ('exceptions', 'OSError'):
Serhiy Storchakab9100e52015-03-31 16:49:26 +0300337 attr = getattribute(module3, name3)
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300338 self.assertTrue(issubclass(attr, OSError))
339 else:
340 module, name = mapping(module2, name2)
341 if module3[:1] != '_':
342 self.assertEqual((module, name), (module3, name3))
Serhiy Storchakab9100e52015-03-31 16:49:26 +0300343 try:
344 attr = getattribute(module3, name3)
345 except ImportError:
346 pass
347 else:
348 self.assertEqual(getattribute(module, name), attr)
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300349
350 def test_reverse_import_mapping(self):
351 for module2, module3 in IMPORT_MAPPING.items():
352 with self.subTest((module2, module3)):
353 try:
354 getmodule(module3)
355 except ImportError as exc:
356 if support.verbose:
357 print(exc)
358 if ((module2, module3) not in ALT_IMPORT_MAPPING and
359 REVERSE_IMPORT_MAPPING.get(module3, None) != module2):
360 for (m3, n3), (m2, n2) in REVERSE_NAME_MAPPING.items():
361 if (module3, module2) == (m3, m2):
362 break
363 else:
364 self.fail('No reverse mapping from %r to %r' %
365 (module3, module2))
366 module = REVERSE_IMPORT_MAPPING.get(module3, module3)
367 module = IMPORT_MAPPING.get(module, module)
368 self.assertEqual(module, module3)
369
370 def test_reverse_name_mapping(self):
371 for (module2, name2), (module3, name3) in NAME_MAPPING.items():
372 with self.subTest(((module2, name2), (module3, name3))):
Serhiy Storchakab9100e52015-03-31 16:49:26 +0300373 try:
374 attr = getattribute(module3, name3)
375 except ImportError:
376 pass
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300377 module, name = reverse_mapping(module3, name3)
378 if (module2, name2, module3, name3) not in ALT_NAME_MAPPING:
379 self.assertEqual((module, name), (module2, name2))
380 module, name = mapping(module, name)
381 self.assertEqual((module, name), (module3, name3))
382
383 def test_exceptions(self):
384 self.assertEqual(mapping('exceptions', 'StandardError'),
385 ('builtins', 'Exception'))
386 self.assertEqual(mapping('exceptions', 'Exception'),
387 ('builtins', 'Exception'))
388 self.assertEqual(reverse_mapping('builtins', 'Exception'),
389 ('exceptions', 'Exception'))
390 self.assertEqual(mapping('exceptions', 'OSError'),
391 ('builtins', 'OSError'))
392 self.assertEqual(reverse_mapping('builtins', 'OSError'),
393 ('exceptions', 'OSError'))
394
395 for name, exc in get_exceptions(builtins):
396 with self.subTest(name):
Yury Selivanov75445082015-05-11 22:57:16 -0400397 if exc in (BlockingIOError,
398 ResourceWarning,
Yury Selivanovf488fb42015-07-03 01:04:23 -0400399 StopAsyncIteration,
400 RecursionError):
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300401 continue
402 if exc is not OSError and issubclass(exc, OSError):
403 self.assertEqual(reverse_mapping('builtins', name),
404 ('exceptions', 'OSError'))
405 else:
406 self.assertEqual(reverse_mapping('builtins', name),
407 ('exceptions', name))
408 self.assertEqual(mapping('exceptions', name),
409 ('builtins', name))
410
Serhiy Storchaka7b2cfc42015-10-10 20:10:07 +0300411 def test_multiprocessing_exceptions(self):
412 module = support.import_module('multiprocessing.context')
413 for name, exc in get_exceptions(module):
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300414 with self.subTest(name):
415 self.assertEqual(reverse_mapping('multiprocessing.context', name),
416 ('multiprocessing', name))
417 self.assertEqual(mapping('multiprocessing', name),
418 ('multiprocessing.context', name))
419
420
Fred Drake694ed092001-12-19 16:42:15 +0000421def test_main():
Serhiy Storchakadec25af2016-07-17 11:24:17 +0300422 tests = [PickleTests, PyUnpicklerTests, PyPicklerTests,
423 PyPersPicklerTests, PyIdPersPicklerTests,
Serhiy Storchakabfe18242015-03-31 13:12:37 +0300424 PyDispatchTableTests, PyChainDispatchTableTests,
425 CompatPickleTests]
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000426 if has_c_implementation:
Serhiy Storchakadec25af2016-07-17 11:24:17 +0300427 tests.extend([CUnpicklerTests, CPicklerTests,
428 CPersPicklerTests, CIdPersPicklerTests,
Collin Winter771d8342009-04-16 03:18:06 +0000429 CDumpPickle_LoadPickle, DumpPickle_CLoadPickle,
430 PyPicklerUnpicklerObjectTests,
Antoine Pitrouea99c5c2010-09-09 18:33:21 +0000431 CPicklerUnpicklerObjectTests,
Antoine Pitrou8d3c2902012-03-04 18:31:48 +0100432 CDispatchTableTests, CChainDispatchTableTests,
Serhiy Storchaka5bbd2312014-12-16 19:39:08 +0200433 InMemoryPickleTests, SizeofTests])
Alexandre Vassalottica2d6102008-06-12 18:26:05 +0000434 support.run_unittest(*tests)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000435 support.run_doctest(pickle)
Fred Drake694ed092001-12-19 16:42:15 +0000436
Jeremy Hylton66426532001-10-15 21:38:56 +0000437if __name__ == "__main__":
Fred Drake694ed092001-12-19 16:42:15 +0000438 test_main()