Skip to content
This repository has been archived by the owner on Sep 14, 2018. It is now read-only.

Commit

Permalink
Fix #278, #581, #577, #580
Browse files Browse the repository at this point in the history
test_random is still not passing though
  • Loading branch information
slide committed Oct 23, 2016
1 parent bd98ae7 commit 0de18cd
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 8 deletions.
Expand Up @@ -3,6 +3,7 @@
import time
import pickle
import warnings
import sys
from math import log, exp, pi, fsum, sin
from functools import reduce
from test import test_support
Expand Down Expand Up @@ -147,6 +148,7 @@ def test_pickling(self):
restoredseq = [newgen.random() for i in xrange(10)]
self.assertEqual(origseq, restoredseq)

@unittest.skipIf(sys.platform=='cli', 'CPython implementation pickles')
def test_bug_1727780(self):
# verify that version-2-pickles can be loaded
# fine, whether they are created on 32-bit or 64-bit
Expand Down Expand Up @@ -307,9 +309,11 @@ def test_randbelow_logic(self, _log=log, int=int):
class MersenneTwister_TestBasicOps(TestBasicOps):
gen = random.Random()

@unittest.skipIf(sys.platform=='cli', 'CPython implementation detail')
def test_setstate_first_arg(self):
self.assertRaises(ValueError, self.gen.setstate, (1, None, None))

@unittest.skipIf(sys.platform=='cli', 'CPython implementation detail')
def test_setstate_middle_arg(self):
# Wrong type, s/b tuple
self.assertRaises(TypeError, self.gen.setstate, (2, None, None))
Expand Down
73 changes: 67 additions & 6 deletions Languages/IronPython/IronPython.Modules/_random.cs
Expand Up @@ -17,13 +17,20 @@
using IronPython.Runtime;
using IronPython.Runtime.Operations;
using Microsoft.Scripting.Utils;
using System.Linq;

#if FEATURE_NUMERICS
using System.Numerics;
#else
using Microsoft.Scripting.Math;
#endif

#if FEATURE_SERIALIZATION
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
#endif

[assembly: PythonModule("_random", typeof(IronPython.Modules.PythonRandom))]
namespace IronPython.Modules {
public static class PythonRandom {
Expand Down Expand Up @@ -54,22 +61,47 @@ public class Random {
}

public object getstate() {
#if FEATURE_SERIALIZATION
MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
lock (this) {
formatter.Serialize(stream, _rnd);
}
byte[] buf = stream.GetBuffer();
int[] retarr = new int[buf.Length];

This comment has been minimized.

Copy link
@slozier

slozier Oct 23, 2016

Contributor

Couldn't you just do stream.GetBuffer().Cast<int>().Cast<object>().ToArray()?

for (int i = 0; i < buf.Length; i++) {
retarr[i] = buf[i];
}
return PythonTuple.MakeTuple(retarr.Cast<object>().ToArray());

#else
return _rnd;
#endif
}

public void jumpahead(int count) {
lock (this) {
_rnd.NextBytes(new byte[4096]);
}
}

public void jumpahead(double count) {
throw PythonOps.TypeError("jumpahead requires an integer, not 'float'");
public void jumpahead(BigInteger count) {
lock(this) {
_rnd.NextBytes(new byte[4096]);
}
}

public void jumpahead(object count) {
throw PythonOps.TypeError("jumpahead requires an integer, not '{0}'", PythonOps.GetPythonTypeName(count));
}

public object random() {
lock (this) {
return _rnd.NextDouble();
// this is pulled from _randommodule.c from CPython
uint a = (uint)_rnd.Next() >> 5;
uint b = (uint)_rnd.Next() >> 6;
double ret = (a*67108864.0+b)*(1.0/9007199254740992.0);
return ret;
}
}

Expand All @@ -87,6 +119,9 @@ public class Random {
if (s is int) {
newSeed = (int)s;
} else {
if (!PythonContext.IsHashable(s)) {
throw PythonOps.TypeError("unhashable type: '{0}'", PythonOps.GetPythonTypeName(s));
}
newSeed = s.GetHashCode();
}

Expand All @@ -96,6 +131,31 @@ public class Random {
}

public void setstate(object state) {
#if FEATURE_SERIALIZATION
PythonTuple s = state as PythonTuple;
if(s == null) {
throw PythonOps.TypeError("state vector must be a tuple");
}

try {
object[] arr = s.ToArray();
byte[] b = new byte[arr.Length];
for (int i = 0; i < arr.Length; i++) {
if (arr[i] is int) {
b[i] = (byte)(int)(arr[i]);
} else {
throw PythonOps.TypeError("state vector of unexpected type: {0}", PythonOps.GetPythonTypeName(arr[i]));
}
}
MemoryStream stream = new MemoryStream(b);
IFormatter formatter = new BinaryFormatter();
lock (this) {
_rnd = (System.Random)formatter.Deserialize(stream);
}
} catch (SerializationException ex) {
throw PythonOps.SystemError("state vector invalid: {0}", ex.Message);
}
#else
System.Random random = state as System.Random;

lock (this) {
Expand All @@ -105,9 +165,10 @@ public class Random {
throw IronPython.Runtime.Operations.PythonOps.TypeError("setstate: argument must be value returned from getstate()");
}
}
}
#endif
}

#endregion
#endregion

This comment has been minimized.

Copy link
@slozier

slozier Oct 23, 2016

Contributor

Probably out of alignment with #region

}
}
}
8 changes: 7 additions & 1 deletion Languages/IronPython/IronPython/Lib/iptest/assert_util.py
Expand Up @@ -207,8 +207,14 @@ def AssertUnreachable(m = None):
def AreEqual(a, b):
Assert(a == b, "expected %r, but found %r" % (b, a))

def AreSame(a, b):
Assert(a is b, "objects are not the same and should be (%r and %r)" % (b, a))

def AreNotSame(a, b):
AssertFalse(a is b, "objects are the same and should not be (%r and %r)" % (b, a))

def AreNotEqual(a, b):
Assert(a <> b, "expected only one of the values to be %r" % a)
Assert(a <> b, "expected only one of the values to be %r" % (a, ))

def AssertContains(containing_string, substring):
Assert(substring in containing_string, "%s should be in %s" % (substring, containing_string))
Expand Down
14 changes: 13 additions & 1 deletion Languages/IronPython/Tests/regressions.py
Expand Up @@ -978,7 +978,19 @@ def __exit__(self, *args):
help(gh1435.someMethod4)
Assert('\n'.join(output), expected)


def test_gh278():
import _random
r = _random.Random()
s1 = r.getstate()
s2 = r.getstate()
AreNotSame(s1, s2)
AreEqual(s1, s2)

r.jumpahead(100)
s3 = r.getstate()
AreNotSame(s3, s1)
AreNotEqual(s3, s1)

#------------------------------------------------------------------------------
#--Main
run_test(__name__)

0 comments on commit 0de18cd

Please sign in to comment.