Skip to content

Commit cc0cd43

Browse files
authored
bpo-1635741: Port _random to multiphase initialization (GH-23359)
Signed-off-by: Christian Heimes <[email protected]>
1 parent 13b865f commit cc0cd43

File tree

2 files changed

+50
-45
lines changed

2 files changed

+50
-45
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Port _random extension module to multiphase initialization (:pep:`489`)

Modules/_randommodule.c

Lines changed: 49 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ get_random_state(PyObject *module)
9393

9494
static struct PyModuleDef _randommodule;
9595

96-
#define _randomstate_global get_random_state(PyState_FindModule(&_randommodule))
96+
#define _randomstate_type(type) \
97+
(get_random_state(_PyType_GetModuleByDef(type, &_randommodule)))
9798

9899
typedef struct {
99100
PyObject_HEAD
@@ -106,9 +107,9 @@ typedef struct {
106107

107108
/*[clinic input]
108109
module _random
109-
class _random.Random "RandomObject *" "&Random_Type"
110+
class _random.Random "RandomObject *" "_randomstate_type(type)->Random_Type"
110111
[clinic start generated code]*/
111-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f79898ae7847c321]*/
112+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=70a2c99619474983]*/
112113

113114
/* Random methods */
114115

@@ -290,7 +291,8 @@ random_seed(RandomObject *self, PyObject *arg)
290291
} else if (PyLong_Check(arg)) {
291292
/* Calling int.__abs__() prevents calling arg.__abs__(), which might
292293
return an invalid value. See issue #31478. */
293-
n = PyObject_CallOneArg(_randomstate_global->Long___abs__, arg);
294+
_randomstate *state = _randomstate_type(Py_TYPE(self));
295+
n = PyObject_CallOneArg(state->Long___abs__, arg);
294296
}
295297
else {
296298
Py_hash_t hash = PyObject_Hash(arg);
@@ -517,8 +519,9 @@ random_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
517519
{
518520
RandomObject *self;
519521
PyObject *tmp;
522+
_randomstate *state = _randomstate_type(type);
520523

521-
if (type == (PyTypeObject*)_randomstate_global->Random_Type &&
524+
if (type == (PyTypeObject*)state->Random_Type &&
522525
!_PyArg_NoKeywords("Random()", kwds)) {
523526
return NULL;
524527
}
@@ -567,6 +570,45 @@ static PyType_Spec Random_Type_spec = {
567570
PyDoc_STRVAR(module_doc,
568571
"Module implements the Mersenne Twister random number generator.");
569572

573+
static int
574+
_random_exec(PyObject *module)
575+
{
576+
_randomstate *state = get_random_state(module);
577+
578+
state->Random_Type = PyType_FromModuleAndSpec(
579+
module, &Random_Type_spec, NULL);
580+
if (state->Random_Type == NULL) {
581+
return -1;
582+
}
583+
if (PyModule_AddType(module, (PyTypeObject *)state->Random_Type) < 0) {
584+
return -1;
585+
}
586+
587+
/* Look up and save int.__abs__, which is needed in random_seed(). */
588+
PyObject *longval = longval = PyLong_FromLong(0);
589+
if (longval == NULL) {
590+
return -1;
591+
}
592+
593+
PyObject *longtype = PyObject_Type(longval);
594+
Py_DECREF(longval);
595+
if (longtype == NULL) {
596+
return -1;
597+
}
598+
599+
state->Long___abs__ = PyObject_GetAttrString(longtype, "__abs__");
600+
Py_DECREF(longtype);
601+
if (state->Long___abs__ == NULL) {
602+
return -1;
603+
}
604+
return 0;
605+
}
606+
607+
static PyModuleDef_Slot _random_slots[] = {
608+
{Py_mod_exec, _random_exec},
609+
{0, NULL}
610+
};
611+
570612
static int
571613
_random_traverse(PyObject *module, visitproc visit, void *arg)
572614
{
@@ -594,7 +636,7 @@ static struct PyModuleDef _randommodule = {
594636
module_doc,
595637
sizeof(_randomstate),
596638
NULL,
597-
NULL,
639+
_random_slots,
598640
_random_traverse,
599641
_random_clear,
600642
_random_free,
@@ -603,43 +645,5 @@ static struct PyModuleDef _randommodule = {
603645
PyMODINIT_FUNC
604646
PyInit__random(void)
605647
{
606-
PyObject *m;
607-
608-
PyObject *Random_Type = PyType_FromSpec(&Random_Type_spec);
609-
if (Random_Type == NULL) {
610-
return NULL;
611-
}
612-
613-
m = PyModule_Create(&_randommodule);
614-
if (m == NULL) {
615-
Py_DECREF(Random_Type);
616-
return NULL;
617-
}
618-
get_random_state(m)->Random_Type = Random_Type;
619-
620-
Py_INCREF(Random_Type);
621-
PyModule_AddObject(m, "Random", Random_Type);
622-
623-
/* Look up and save int.__abs__, which is needed in random_seed(). */
624-
PyObject *longval = NULL, *longtype = NULL;
625-
longval = PyLong_FromLong(0);
626-
if (longval == NULL) goto fail;
627-
628-
longtype = PyObject_Type(longval);
629-
if (longtype == NULL) goto fail;
630-
631-
PyObject *abs = PyObject_GetAttrString(longtype, "__abs__");
632-
if (abs == NULL) goto fail;
633-
634-
Py_DECREF(longtype);
635-
Py_DECREF(longval);
636-
get_random_state(m)->Long___abs__ = abs;
637-
638-
return m;
639-
640-
fail:
641-
Py_XDECREF(longtype);
642-
Py_XDECREF(longval);
643-
Py_DECREF(m);
644-
return NULL;
648+
return PyModuleDef_Init(&_randommodule);
645649
}

0 commit comments

Comments
 (0)