PageRenderTime 38ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/lib-python/2.7/test/test_xpickle.py

https://bitbucket.org/dac_io/pypy
Python | 260 lines | 225 code | 13 blank | 22 comment | 1 complexity | 9c773cbcd12d11ec7c4514d901b4f45f MD5 | raw file
  1. # test_pickle dumps and loads pickles via pickle.py.
  2. # test_cpickle does the same, but via the cPickle module.
  3. # This test covers the other two cases, making pickles with one module and
  4. # loading them via the other. It also tests backwards compatibility with
  5. # previous version of Python by bouncing pickled objects through Python 2.4
  6. # and Python 2.5 running this file.
  7. import cPickle
  8. import os
  9. import os.path
  10. import pickle
  11. import subprocess
  12. import sys
  13. import types
  14. import unittest
  15. from test import test_support
  16. # Most distro-supplied Pythons don't include the tests
  17. # or test support files, and some don't include a way to get these back even if
  18. # you're will to install extra packages (like Ubuntu). Doing things like this
  19. # "provides" a pickletester module for older versions of Python that may be
  20. # installed without it. Note that one other design for this involves messing
  21. # with sys.path, which is less precise.
  22. mod_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
  23. "pickletester.py"))
  24. pickletester = types.ModuleType("test.pickletester")
  25. exec compile(open(mod_path).read(), mod_path, 'exec') in pickletester.__dict__
  26. AbstractPickleTests = pickletester.AbstractPickleTests
  27. if pickletester.__name__ in sys.modules:
  28. raise RuntimeError("Did not expect to find test.pickletester loaded")
  29. sys.modules[pickletester.__name__] = pickletester
  30. class DumpCPickle_LoadPickle(AbstractPickleTests):
  31. error = KeyError
  32. def dumps(self, arg, proto=0, fast=False):
  33. # Ignore fast
  34. return cPickle.dumps(arg, proto)
  35. def loads(self, buf):
  36. # Ignore fast
  37. return pickle.loads(buf)
  38. class DumpPickle_LoadCPickle(AbstractPickleTests):
  39. error = cPickle.BadPickleGet
  40. def dumps(self, arg, proto=0, fast=False):
  41. # Ignore fast
  42. return pickle.dumps(arg, proto)
  43. def loads(self, buf):
  44. # Ignore fast
  45. return cPickle.loads(buf)
  46. def have_python_version(name):
  47. """Check whether the given name is a valid Python binary and has
  48. test.test_support.
  49. This respects your PATH.
  50. Args:
  51. name: short string name of a Python binary such as "python2.4".
  52. Returns:
  53. True if the name is valid, False otherwise.
  54. """
  55. return os.system(name + " -c 'import test.test_support'") == 0
  56. class AbstractCompatTests(AbstractPickleTests):
  57. module = None
  58. python = None
  59. error = None
  60. def setUp(self):
  61. self.assertTrue(self.python)
  62. self.assertTrue(self.module)
  63. self.assertTrue(self.error)
  64. def send_to_worker(self, python, obj, proto):
  65. """Bounce a pickled object through another version of Python.
  66. This will pickle the object, send it to a child process where it will be
  67. unpickled, then repickled and sent back to the parent process.
  68. Args:
  69. python: the name of the Python binary to start.
  70. obj: object to pickle.
  71. proto: pickle protocol number to use.
  72. Returns:
  73. The pickled data received from the child process.
  74. """
  75. # Prevent the subprocess from picking up invalid .pyc files.
  76. target = __file__
  77. if target[-1] in ("c", "o"):
  78. target = target[:-1]
  79. data = self.module.dumps((proto, obj), proto)
  80. worker = subprocess.Popen([python, target, "worker"],
  81. stdin=subprocess.PIPE,
  82. stdout=subprocess.PIPE,
  83. stderr=subprocess.PIPE)
  84. stdout, stderr = worker.communicate(data)
  85. if worker.returncode != 0:
  86. raise RuntimeError(stderr)
  87. return stdout
  88. def dumps(self, arg, proto=0, fast=False):
  89. return self.send_to_worker(self.python, arg, proto)
  90. def loads(self, input):
  91. return self.module.loads(input)
  92. # These tests are disabled because they require some special setup
  93. # on the worker that's hard to keep in sync.
  94. def test_global_ext1(self):
  95. pass
  96. def test_global_ext2(self):
  97. pass
  98. def test_global_ext4(self):
  99. pass
  100. # This is a cut-down version of pickletester's test_float. Backwards
  101. # compatibility for the values in for_bin_protos was explicitly broken in
  102. # r68903 to fix a bug.
  103. def test_float(self):
  104. for_bin_protos = [4.94e-324, 1e-310]
  105. neg_for_bin_protos = [-x for x in for_bin_protos]
  106. test_values = [0.0, 7e-308, 6.626e-34, 0.1, 0.5,
  107. 3.14, 263.44582062374053, 6.022e23, 1e30]
  108. test_proto0_values = test_values + [-x for x in test_values]
  109. test_values = test_proto0_values + for_bin_protos + neg_for_bin_protos
  110. for value in test_proto0_values:
  111. pickle = self.dumps(value, 0)
  112. got = self.loads(pickle)
  113. self.assertEqual(value, got)
  114. for proto in pickletester.protocols[1:]:
  115. for value in test_values:
  116. pickle = self.dumps(value, proto)
  117. got = self.loads(pickle)
  118. self.assertEqual(value, got)
  119. # Backwards compatibility was explicitly broken in r67934 to fix a bug.
  120. def test_unicode_high_plane(self):
  121. pass
  122. if test_support.have_unicode:
  123. # This is a cut-down version of pickletester's test_unicode. Backwards
  124. # compatibility was explicitly broken in r67934 to fix a bug.
  125. def test_unicode(self):
  126. endcases = [u'', u'<\\u>', u'<\\\u1234>', u'<\n>', u'<\\>']
  127. for proto in pickletester.protocols:
  128. for u in endcases:
  129. p = self.dumps(u, proto)
  130. u2 = self.loads(p)
  131. self.assertEqual(u2, u)
  132. def run_compat_test(python_name):
  133. return (test_support.is_resource_enabled("xpickle") and
  134. have_python_version(python_name))
  135. # Test backwards compatibility with Python 2.4.
  136. if not run_compat_test("python2.4"):
  137. class CPicklePython24Compat(unittest.TestCase):
  138. pass
  139. else:
  140. class CPicklePython24Compat(AbstractCompatTests):
  141. module = cPickle
  142. python = "python2.4"
  143. error = cPickle.BadPickleGet
  144. # Disable these tests for Python 2.4. Making them pass would require
  145. # nontrivially monkeypatching the pickletester module in the worker.
  146. def test_reduce_calls_base(self):
  147. pass
  148. def test_reduce_ex_calls_base(self):
  149. pass
  150. class PicklePython24Compat(CPicklePython24Compat):
  151. module = pickle
  152. error = KeyError
  153. # Test backwards compatibility with Python 2.5.
  154. if not run_compat_test("python2.5"):
  155. class CPicklePython25Compat(unittest.TestCase):
  156. pass
  157. else:
  158. class CPicklePython25Compat(AbstractCompatTests):
  159. module = cPickle
  160. python = "python2.5"
  161. error = cPickle.BadPickleGet
  162. class PicklePython25Compat(CPicklePython25Compat):
  163. module = pickle
  164. error = KeyError
  165. # Test backwards compatibility with Python 2.6.
  166. if not run_compat_test("python2.6"):
  167. class CPicklePython26Compat(unittest.TestCase):
  168. pass
  169. else:
  170. class CPicklePython26Compat(AbstractCompatTests):
  171. module = cPickle
  172. python = "python2.6"
  173. error = cPickle.BadPickleGet
  174. class PicklePython26Compat(CPicklePython26Compat):
  175. module = pickle
  176. error = KeyError
  177. def worker_main(in_stream, out_stream):
  178. message = cPickle.load(in_stream)
  179. protocol, obj = message
  180. cPickle.dump(obj, out_stream, protocol)
  181. def test_main():
  182. if not test_support.is_resource_enabled("xpickle"):
  183. print >>sys.stderr, "test_xpickle -- skipping backwards compat tests."
  184. print >>sys.stderr, "Use 'regrtest.py -u xpickle' to run them."
  185. sys.stderr.flush()
  186. test_support.run_unittest(
  187. DumpCPickle_LoadPickle,
  188. DumpPickle_LoadCPickle,
  189. CPicklePython24Compat,
  190. CPicklePython25Compat,
  191. CPicklePython26Compat,
  192. PicklePython24Compat,
  193. PicklePython25Compat,
  194. PicklePython26Compat,
  195. )
  196. if __name__ == "__main__":
  197. if "worker" in sys.argv:
  198. worker_main(sys.stdin, sys.stdout)
  199. else:
  200. test_main()