Commit 7975b0a4 authored by 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.
parent 3104c156
......@@ -80,6 +80,9 @@ Bookkeeping functions:
.. versionadded:: 2.1
.. versionchanged:: 2.6
State values produced in Python 2.6 cannot be loaded into earlier versions.
.. function:: setstate(state)
......
......@@ -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):
"""Initialize an instance.
......@@ -120,9 +120,20 @@ class Random(_random.Random):
def setstate(self, state):
"""Restore internal state from object returned by getstate()."""
version = state[0]
if version == 2:
if version == 3:
version, internalstate, self.gauss_next = state
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:
raise ValueError("state with version %s passed to "
"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):
restoredseq = [newgen.random() for i in xrange(10)]
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):
gen = random.WichmannHill()
......
......@@ -395,6 +395,7 @@ Marc-Andre Lemburg
Mark Levinson
William Lewis
Robert van Liere
Shawn Ligocki
Martin Ligr
Christopher Lindblad
Eric Lindvall
......
......@@ -308,6 +308,11 @@ Core and builtins
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
both the msvccompiler and cygwincompiler.
......
......@@ -319,12 +319,12 @@ random_getstate(RandomObject *self)
if (state == NULL)
return NULL;
for (i=0; i<N ; i++) {
element = PyInt_FromLong((long)(self->state[i]));
element = PyLong_FromUnsignedLong(self->state[i]);
if (element == NULL)
goto Fail;
PyTuple_SET_ITEM(state, i, element);
}
element = PyInt_FromLong((long)(self->index));
element = PyLong_FromLong((long)(self->index));
if (element == NULL)
goto Fail;
PyTuple_SET_ITEM(state, i, element);
......@@ -339,7 +339,8 @@ static PyObject *
random_setstate(RandomObject *self, PyObject *state)
{
int i;
long element;
unsigned long element;
long index;
if (!PyTuple_Check(state)) {
PyErr_SetString(PyExc_TypeError,
......@@ -353,16 +354,16 @@ random_setstate(RandomObject *self, PyObject *state)
}
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())
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));
if (element == -1 && PyErr_Occurred())
index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
if (index == -1 && PyErr_Occurred())
return NULL;
self->index = (int)element;
self->index = (int)index;
Py_INCREF(Py_None);
return Py_None;
......
......@@ -933,6 +933,7 @@ def add_files(db):
lib.add_file("empty.vbs")
lib.glob("*.uue")
lib.glob("*.pem")
lib.glob("*.pck")
lib.add_file("readme.txt", src="README")
if dir=='decimaltestdata':
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