self.assertRaises(ValueError, self.gen.setstate, (1, None, None))
def test_setstate_middle_arg(self):
+ start_state = self.gen.getstate()
# Wrong type, s/b tuple
self.assertRaises(TypeError, self.gen.setstate, (2, None, None))
# Wrong length, s/b 625
self.gen.setstate((2, (1,)*624+(625,), None))
with self.assertRaises((ValueError, OverflowError)):
self.gen.setstate((2, (1,)*624+(-1,), None))
+ # Failed calls to setstate() should not have changed the state.
+ bits100 = self.gen.getrandbits(100)
+ self.gen.setstate(start_state)
+ self.assertEqual(self.gen.getrandbits(100), bits100)
# Little trick to make "tuple(x % (2**32) for x in internalstate)"
# raise ValueError. I cannot think of a simple way to achieve this, so
Library
-------
+- bpo-29960: Preserve generator state when _random.Random.setstate()
+ raises an exception. Patch by Bryan Olson.
+
- bpo-30414: multiprocessing.Queue._feed background running
thread do not break from main loop on exception.
int i;
unsigned long element;
long index;
+ uint32_t new_state[N];
if (!PyTuple_Check(state)) {
PyErr_SetString(PyExc_TypeError,
element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i));
if (element == (unsigned long)-1 && PyErr_Occurred())
return NULL;
- self->state[i] = (uint32_t)element;
+ new_state[i] = (uint32_t)element;
}
index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
return NULL;
}
self->index = (int)index;
+ for (i = 0; i < N; i++)
+ self->state[i] = new_state[i];
Py_INCREF(Py_None);
return Py_None;