Kaydet (Commit) 6b449f4f authored tarafından Martin v. Löwis's avatar Martin v. Löwis

Issue #1727780: Support loading pickles of random.Random objects created

on 32-bit systems on 64-bit systems, and vice versa. As a consequence
of the change, Random pickles created by Python 2.6 cannot be loaded
in Python 2.5.
üst 2ec7415d
...@@ -80,6 +80,9 @@ Bookkeeping functions: ...@@ -80,6 +80,9 @@ Bookkeeping functions:
.. versionadded:: 2.1 .. versionadded:: 2.1
.. versionchanged:: 2.6
State values produced in Python 2.6 cannot be loaded into earlier versions.
.. function:: setstate(state) .. function:: setstate(state)
......
...@@ -83,7 +83,7 @@ class Random(_random.Random): ...@@ -83,7 +83,7 @@ class Random(_random.Random):
""" """
VERSION = 2 # used by getstate/setstate VERSION = 3 # used by getstate/setstate
def __init__(self, x=None): def __init__(self, x=None):
"""Initialize an instance. """Initialize an instance.
...@@ -120,9 +120,20 @@ class Random(_random.Random): ...@@ -120,9 +120,20 @@ class Random(_random.Random):
def setstate(self, state): def setstate(self, state):
"""Restore internal state from object returned by getstate().""" """Restore internal state from object returned by getstate()."""
version = state[0] version = state[0]
if version == 2: if version == 3:
version, internalstate, self.gauss_next = state version, internalstate, self.gauss_next = state
super(Random, self).setstate(internalstate) super(Random, self).setstate(internalstate)
elif version == 2:
version, internalstate, self.gauss_next = state
# In version 2, the state was saved as signed ints, which causes
# inconsistencies between 32/64-bit systems. The state is
# really unsigned 32-bit ints, so we convert negative ints from
# version 2 to positive longs for version 3.
try:
internalstate = tuple( long(x) % (2**32) for x in internalstate )
except ValueError, e:
raise TypeError, e
super(Random, self).setstate(internalstate)
else: else:
raise ValueError("state with version %s passed to " raise ValueError("state with version %s passed to "
"Random.setstate() of version %s" % "Random.setstate() of version %s" %
......
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
...@@ -140,6 +140,19 @@ class TestBasicOps(unittest.TestCase): ...@@ -140,6 +140,19 @@ class TestBasicOps(unittest.TestCase):
restoredseq = [newgen.random() for i in xrange(10)] restoredseq = [newgen.random() for i in xrange(10)]
self.assertEqual(origseq, restoredseq) self.assertEqual(origseq, restoredseq)
def test_bug_1727780(self):
# verify that version-2-pickles can be loaded
# fine, whether they are created on 32-bit or 64-bit
# platforms, and that version-3-pickles load fine.
files = [("randv2_32.pck", 780),
("randv2_64.pck", 866),
("randv3.pck", 343)]
for file, value in files:
f = open(test_support.findfile(file),"rb")
r = pickle.load(f)
f.close()
self.assertEqual(r.randrange(1000), value)
class WichmannHill_TestBasicOps(TestBasicOps): class WichmannHill_TestBasicOps(TestBasicOps):
gen = random.WichmannHill() gen = random.WichmannHill()
......
...@@ -395,6 +395,7 @@ Marc-Andre Lemburg ...@@ -395,6 +395,7 @@ Marc-Andre Lemburg
Mark Levinson Mark Levinson
William Lewis William Lewis
Robert van Liere Robert van Liere
Shawn Ligocki
Martin Ligr Martin Ligr
Christopher Lindblad Christopher Lindblad
Eric Lindvall Eric Lindvall
......
...@@ -308,6 +308,11 @@ Core and builtins ...@@ -308,6 +308,11 @@ Core and builtins
Library Library
------- -------
- Issue #1727780: Support loading pickles of random.Random objects created
on 32-bit systems on 64-bit systems, and vice versa. As a consequence
of the change, Random pickles created by Python 2.6 cannot be loaded
in Python 2.5.
- Issue #1455: The distutils package now supports VS 2005 and VS 2008 for - Issue #1455: The distutils package now supports VS 2005 and VS 2008 for
both the msvccompiler and cygwincompiler. both the msvccompiler and cygwincompiler.
......
...@@ -319,12 +319,12 @@ random_getstate(RandomObject *self) ...@@ -319,12 +319,12 @@ random_getstate(RandomObject *self)
if (state == NULL) if (state == NULL)
return NULL; return NULL;
for (i=0; i<N ; i++) { for (i=0; i<N ; i++) {
element = PyInt_FromLong((long)(self->state[i])); element = PyLong_FromUnsignedLong(self->state[i]);
if (element == NULL) if (element == NULL)
goto Fail; goto Fail;
PyTuple_SET_ITEM(state, i, element); PyTuple_SET_ITEM(state, i, element);
} }
element = PyInt_FromLong((long)(self->index)); element = PyLong_FromLong((long)(self->index));
if (element == NULL) if (element == NULL)
goto Fail; goto Fail;
PyTuple_SET_ITEM(state, i, element); PyTuple_SET_ITEM(state, i, element);
...@@ -339,7 +339,8 @@ static PyObject * ...@@ -339,7 +339,8 @@ static PyObject *
random_setstate(RandomObject *self, PyObject *state) random_setstate(RandomObject *self, PyObject *state)
{ {
int i; int i;
long element; unsigned long element;
long index;
if (!PyTuple_Check(state)) { if (!PyTuple_Check(state)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
...@@ -353,16 +354,16 @@ random_setstate(RandomObject *self, PyObject *state) ...@@ -353,16 +354,16 @@ random_setstate(RandomObject *self, PyObject *state)
} }
for (i=0; i<N ; i++) { for (i=0; i<N ; i++) {
element = PyInt_AsLong(PyTuple_GET_ITEM(state, i)); element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i));
if (element == -1 && PyErr_Occurred()) if (element == -1 && PyErr_Occurred())
return NULL; return NULL;
self->state[i] = (unsigned long)element; self->state[i] = element & 0xffffffffUL; /* Make sure we get sane state */
} }
element = PyInt_AsLong(PyTuple_GET_ITEM(state, i)); index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
if (element == -1 && PyErr_Occurred()) if (index == -1 && PyErr_Occurred())
return NULL; return NULL;
self->index = (int)element; self->index = (int)index;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
......
...@@ -933,6 +933,7 @@ def add_files(db): ...@@ -933,6 +933,7 @@ def add_files(db):
lib.add_file("empty.vbs") lib.add_file("empty.vbs")
lib.glob("*.uue") lib.glob("*.uue")
lib.glob("*.pem") lib.glob("*.pem")
lib.glob("*.pck")
lib.add_file("readme.txt", src="README") lib.add_file("readme.txt", src="README")
if dir=='decimaltestdata': if dir=='decimaltestdata':
lib.glob("*.decTest") lib.glob("*.decTest")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment