diff -r a62072cf50a2 Lib/random.py --- a/Lib/random.py Wed Jan 22 12:26:01 2014 +0100 +++ b/Lib/random.py Wed Jan 22 16:48:04 2014 +0200 @@ -81,6 +81,9 @@ VERSION = 3 # used by getstate/setstate + def __new__(cls, *args, **kwargs): + return super().__new__(cls, 0) + def __init__(self, x=None): """Initialize an instance. diff -r a62072cf50a2 Modules/_randommodule.c --- a/Modules/_randommodule.c Wed Jan 22 12:26:01 2014 +0100 +++ b/Modules/_randommodule.c Wed Jan 22 16:48:04 2014 +0200 @@ -66,6 +66,12 @@ /* ---------------------------------------------------------------*/ +/*[clinic input] +module _random +class _random.Random +[clinic start generated code]*/ +/*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ + #include "Python.h" #include /* for seeding to current time */ @@ -203,8 +209,45 @@ * Twister download. */ +/*[clinic input] +_random.Random.seed as random_seed + + self: self(type="RandomObject *") + seed: object = NULL + / + +Defaults to current time. +[clinic start generated code]*/ + +PyDoc_STRVAR(random_seed__doc__, +"seed(seed=None)\n" +"Defaults to current time."); + +#define RANDOM_SEED_METHODDEF \ + {"seed", (PyCFunction)random_seed, METH_VARARGS, random_seed__doc__}, + static PyObject * -random_seed(RandomObject *self, PyObject *args) +random_seed_impl(RandomObject *self, PyObject *seed); + +static PyObject * +random_seed(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *seed = NULL; + + if (!PyArg_UnpackTuple(args, "seed", + 0, 1, + &seed)) + goto exit; + return_value = random_seed_impl((RandomObject *)self, seed); + +exit: + return return_value; +} + +static PyObject * +random_seed_impl(RandomObject *self, PyObject *seed) +/*[clinic end generated code: checksum=ad6323ea8c7a69263eba2e3e57078c6487d176cf]*/ { PyObject *result = NULL; /* guilty until proved innocent */ PyObject *n = NULL; @@ -212,12 +255,8 @@ unsigned char *key_as_bytes = NULL; size_t bits, keyused, i; int res; - PyObject *arg = NULL; - if (!PyArg_UnpackTuple(args, "seed", 0, 1, &arg)) - return NULL; - - if (arg == NULL || arg == Py_None) { + if (seed == NULL || seed == Py_None) { time_t now; time(&now); @@ -226,13 +265,13 @@ return Py_None; } /* This algorithm relies on the number being unsigned. - * So: if the arg is a PyLong, use its absolute value. + * So: if the seed is a PyLong, use its absolute value. * Otherwise use its hash value, cast to unsigned. */ - if (PyLong_Check(arg)) - n = PyNumber_Absolute(arg); + if (PyLong_Check(seed)) + n = PyNumber_Absolute(seed); else { - Py_hash_t hash = PyObject_Hash(arg); + Py_hash_t hash = PyObject_Hash(seed); if (hash == -1) goto Done; n = PyLong_FromSize_t((size_t)hash); @@ -346,17 +385,51 @@ return Py_None; } +/*[clinic input] +_random.Random.getrandbits as random_getrandbits + + self: self(type="RandomObject *") + k: int + / + +Generates an int with k random bits. +[clinic start generated code]*/ + +PyDoc_STRVAR(random_getrandbits__doc__, +"getrandbits(k)\n" +"Generates an int with k random bits."); + +#define RANDOM_GETRANDBITS_METHODDEF \ + {"getrandbits", (PyCFunction)random_getrandbits, METH_VARARGS, random_getrandbits__doc__}, + static PyObject * -random_getrandbits(RandomObject *self, PyObject *args) +random_getrandbits_impl(RandomObject *self, int k); + +static PyObject * +random_getrandbits(PyObject *self, PyObject *args) { - int k, i, bytes; + PyObject *return_value = NULL; + int k; + + if (!PyArg_ParseTuple(args, + "i:getrandbits", + &k)) + goto exit; + return_value = random_getrandbits_impl((RandomObject *)self, k); + +exit: + return return_value; +} + +static PyObject * +random_getrandbits_impl(RandomObject *self, int k) +/*[clinic end generated code: checksum=a49ae8af01fec25454f82eecff3916b7348aa252]*/ +{ + int i, bytes; unsigned long r; unsigned char *bytearray; PyObject *result; - if (!PyArg_ParseTuple(args, "i:getrandbits", &k)) - return NULL; - if (k <= 0) { PyErr_SetString(PyExc_ValueError, "number of bits must be greater than zero"); @@ -390,19 +463,52 @@ return result; } +/*[clinic input] +@classmethod +_random.Random.__new__ as random_new + + seed: object = NULL + / + +Create a random number generator with its own internal state. +[clinic start generated code]*/ + +PyDoc_STRVAR(random_new__doc__, +"Random(seed=None)\n" +"Create a random number generator with its own internal state."); + static PyObject * -random_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +random_new_impl(PyTypeObject *type, PyObject *seed); + +static PyObject * +random_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + PyObject *seed = NULL; + + if (!_PyArg_NoKeywords("__new__", kwargs)) + goto exit; + if (!PyArg_UnpackTuple(args, "__new__", + 0, 1, + &seed)) + goto exit; + return_value = random_new_impl(type, seed); + +exit: + return return_value; +} + +static PyObject * +random_new_impl(PyTypeObject *type, PyObject *seed) +/*[clinic end generated code: checksum=a6f92676beedf1af8f4cc3aff018afe17aa9954a]*/ { RandomObject *self; PyObject *tmp; - if (type == &Random_Type && !_PyArg_NoKeywords("Random()", kwds)) - return NULL; - self = (RandomObject *)type->tp_alloc(type, 0); if (self == NULL) return NULL; - tmp = random_seed(self, args); + tmp = random_seed_impl(self, seed); if (tmp == NULL) { Py_DECREF(self); return NULL; @@ -414,21 +520,15 @@ static PyMethodDef random_methods[] = { {"random", (PyCFunction)random_random, METH_NOARGS, PyDoc_STR("random() -> x in the interval [0, 1).")}, - {"seed", (PyCFunction)random_seed, METH_VARARGS, - PyDoc_STR("seed([n]) -> None. Defaults to current time.")}, + RANDOM_SEED_METHODDEF {"getstate", (PyCFunction)random_getstate, METH_NOARGS, PyDoc_STR("getstate() -> tuple containing the current state.")}, {"setstate", (PyCFunction)random_setstate, METH_O, PyDoc_STR("setstate(state) -> None. Restores generator state.")}, - {"getrandbits", (PyCFunction)random_getrandbits, METH_VARARGS, - PyDoc_STR("getrandbits(k) -> x. Generates an int with " - "k random bits.")}, + RANDOM_GETRANDBITS_METHODDEF {NULL, NULL} /* sentinel */ }; -PyDoc_STRVAR(random_doc, -"Random() -> create a random number generator with its own internal state."); - static PyTypeObject Random_Type = { PyVarObject_HEAD_INIT(NULL, 0) "_random.Random", /*tp_name*/ @@ -450,8 +550,9 @@ PyObject_GenericGetAttr, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - random_doc, /*tp_doc*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + /*tp_flags*/ + random_new__doc__, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/