bpo-38075: Port _randommodule.c to PEP-384 (GH-15798) · python/cpython@04f0bbf (original) (raw)
`@@ -79,15 +79,23 @@
`
79
79
`#define UPPER_MASK 0x80000000U /* most significant w-r bits */
`
80
80
`#define LOWER_MASK 0x7fffffffU /* least significant r bits */
`
81
81
``
``
82
`+
typedef struct {
`
``
83
`+
PyObject *Random_Type;
`
``
84
`+
PyObject *Long___abs__;
`
``
85
`+
} _randomstate;
`
``
86
+
``
87
`+
#define _randomstate(o) ((_randomstate *)PyModule_GetState(o))
`
``
88
+
``
89
`+
static struct PyModuleDef _randommodule;
`
``
90
+
``
91
`+
#define _randomstate_global _randomstate(PyState_FindModule(&_randommodule))
`
``
92
+
82
93
`typedef struct {
`
83
94
`PyObject_HEAD
`
84
95
`int index;
`
85
96
`uint32_t state[N];
`
86
97
`} RandomObject;
`
87
98
``
88
``
`-
static PyTypeObject Random_Type;
`
89
``
-
90
``
`-
#define RandomObject_Check(v) (Py_TYPE(v) == &Random_Type)
`
91
99
``
92
100
`#include "clinic/_randommodule.c.h"
`
93
101
``
`@@ -256,6 +264,7 @@ random_seed(RandomObject *self, PyObject *arg)
`
256
264
`uint32_t *key = NULL;
`
257
265
`size_t bits, keyused;
`
258
266
`int res;
`
``
267
`+
PyObject *args[1];
`
259
268
``
260
269
`if (arg == NULL || arg == Py_None) {
`
261
270
`if (random_seed_urandom(self) < 0) {
`
`@@ -272,10 +281,14 @@ random_seed(RandomObject *self, PyObject *arg)
`
272
281
` * So: if the arg is a PyLong, use its absolute value.
`
273
282
` * Otherwise use its hash value, cast to unsigned.
`
274
283
` */
`
275
``
`-
if (PyLong_Check(arg)) {
`
``
284
`+
if (PyLong_CheckExact(arg)) {
`
``
285
`+
n = PyNumber_Absolute(arg);
`
``
286
`+
} else if (PyLong_Check(arg)) {
`
276
287
`/* Calling int.abs() prevents calling arg.abs(), which might
`
277
288
` return an invalid value. See issue #31478. */
`
278
``
`-
n = PyLong_Type.tp_as_number->nb_absolute(arg);
`
``
289
`+
args[0] = arg;
`
``
290
`+
n = PyObject_Vectorcall(randomstate_global->Long___abs, args, 0,
`
``
291
`+
NULL);
`
279
292
` }
`
280
293
`else {
`
281
294
`Py_hash_t hash = PyObject_Hash(arg);
`
`@@ -500,10 +513,12 @@ random_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
`
500
513
`RandomObject *self;
`
501
514
`PyObject *tmp;
`
502
515
``
503
``
`-
if (type == &Random_Type && !_PyArg_NoKeywords("Random", kwds))
`
``
516
`+
if (type == (PyTypeObject*)_randomstate_global->Random_Type &&
`
``
517
`+
!_PyArg_NoKeywords("Random()", kwds)) {
`
504
518
`return NULL;
`
``
519
`+
}
`
505
520
``
506
``
`-
self = (RandomObject *)type->tp_alloc(type, 0);
`
``
521
`+
self = (RandomObject *)PyType_GenericAlloc(type, 0);
`
507
522
`if (self == NULL)
`
508
523
`return NULL;
`
509
524
`tmp = random_seed(self, args);
`
`@@ -527,77 +542,97 @@ static PyMethodDef random_methods[] = {
`
527
542
`PyDoc_STRVAR(random_doc,
`
528
543
`"Random() -> create a random number generator with its own internal state.");
`
529
544
``
530
``
`-
static PyTypeObject Random_Type = {
`
531
``
`-
PyVarObject_HEAD_INIT(NULL, 0)
`
532
``
`-
"_random.Random", /tp_name/
`
533
``
`-
sizeof(RandomObject), /tp_basicsize/
`
534
``
`-
0, /tp_itemsize/
`
535
``
`-
/* methods */
`
536
``
`-
0, /tp_dealloc/
`
537
``
`-
0, /tp_vectorcall_offset/
`
538
``
`-
0, /tp_getattr/
`
539
``
`-
0, /tp_setattr/
`
540
``
`-
0, /tp_as_async/
`
541
``
`-
0, /tp_repr/
`
542
``
`-
0, /tp_as_number/
`
543
``
`-
0, /tp_as_sequence/
`
544
``
`-
0, /tp_as_mapping/
`
545
``
`-
0, /tp_hash/
`
546
``
`-
0, /tp_call/
`
547
``
`-
0, /tp_str/
`
548
``
`-
PyObject_GenericGetAttr, /tp_getattro/
`
549
``
`-
0, /tp_setattro/
`
550
``
`-
0, /tp_as_buffer/
`
551
``
`-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /tp_flags/
`
552
``
`-
random_doc, /tp_doc/
`
553
``
`-
0, /tp_traverse/
`
554
``
`-
0, /tp_clear/
`
555
``
`-
0, /tp_richcompare/
`
556
``
`-
0, /tp_weaklistoffset/
`
557
``
`-
0, /tp_iter/
`
558
``
`-
0, /tp_iternext/
`
559
``
`-
random_methods, /tp_methods/
`
560
``
`-
0, /tp_members/
`
561
``
`-
0, /tp_getset/
`
562
``
`-
0, /tp_base/
`
563
``
`-
0, /tp_dict/
`
564
``
`-
0, /tp_descr_get/
`
565
``
`-
0, /tp_descr_set/
`
566
``
`-
0, /tp_dictoffset/
`
567
``
`-
0, /tp_init/
`
568
``
`-
0, /tp_alloc/
`
569
``
`-
random_new, /tp_new/
`
570
``
`-
PyObject_Free, /tp_free/
`
571
``
`-
0, /tp_is_gc/
`
``
545
`+
static PyType_Slot Random_Type_slots[] = {
`
``
546
`+
{Py_tp_doc, random_doc},
`
``
547
`+
{Py_tp_methods, random_methods},
`
``
548
`+
{Py_tp_new, random_new},
`
``
549
`+
{Py_tp_free, PyObject_Free},
`
``
550
`+
{0, 0},
`
``
551
`+
};
`
``
552
+
``
553
`+
static PyType_Spec Random_Type_spec = {
`
``
554
`+
"_random.Random",
`
``
555
`+
sizeof(RandomObject),
`
``
556
`+
0,
`
``
557
`+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
`
``
558
`+
Random_Type_slots
`
572
559
`};
`
573
560
``
574
561
`PyDoc_STRVAR(module_doc,
`
575
562
`"Module implements the Mersenne Twister random number generator.");
`
576
563
``
``
564
`+
static int
`
``
565
`+
_random_traverse(PyObject *module, visitproc visit, void *arg)
`
``
566
`+
{
`
``
567
`+
Py_VISIT(_randomstate(module)->Random_Type);
`
``
568
`+
return 0;
`
``
569
`+
}
`
``
570
+
``
571
`+
static int
`
``
572
`+
_random_clear(PyObject *module)
`
``
573
`+
{
`
``
574
`+
Py_CLEAR(_randomstate(module)->Random_Type);
`
``
575
`+
return 0;
`
``
576
`+
}
`
``
577
+
``
578
`+
static void
`
``
579
`+
_random_free(void *module)
`
``
580
`+
{
`
``
581
`+
_random_clear((PyObject *)module);
`
``
582
`+
}
`
577
583
``
578
584
`static struct PyModuleDef _randommodule = {
`
579
585
`PyModuleDef_HEAD_INIT,
`
580
586
`"_random",
`
581
587
`module_doc,
`
582
``
`-
-1,
`
583
``
`-
NULL,
`
``
588
`+
sizeof(_randomstate),
`
584
589
`NULL,
`
585
590
`NULL,
`
586
``
`-
NULL,
`
587
``
`-
NULL
`
``
591
`+
_random_traverse,
`
``
592
`+
_random_clear,
`
``
593
`+
_random_free,
`
588
594
`};
`
589
595
``
590
596
`PyMODINIT_FUNC
`
591
597
`PyInit__random(void)
`
592
598
`{
`
593
599
`PyObject *m;
`
594
600
``
595
``
`-
if (PyType_Ready(&Random_Type) < 0)
`
``
601
`+
PyObject *Random_Type = PyType_FromSpec(&Random_Type_spec);
`
``
602
`+
if (Random_Type == NULL) {
`
596
603
`return NULL;
`
``
604
`+
}
`
``
605
+
597
606
`m = PyModule_Create(&_randommodule);
`
598
``
`-
if (m == NULL)
`
``
607
`+
if (m == NULL) {
`
``
608
`+
Py_DECREF(Random_Type);
`
599
609
`return NULL;
`
600
``
`-
Py_INCREF(&Random_Type);
`
601
``
`-
PyModule_AddObject(m, "Random", (PyObject *)&Random_Type);
`
``
610
`+
}
`
``
611
`+
_randomstate(m)->Random_Type = Random_Type;
`
``
612
+
``
613
`+
Py_INCREF(Random_Type);
`
``
614
`+
PyModule_AddObject(m, "Random", Random_Type);
`
``
615
+
``
616
`+
/* Look up and save int.abs, which is needed in random_seed(). */
`
``
617
`+
PyObject *longval = NULL, *longtype = NULL;
`
``
618
`+
longval = PyLong_FromLong(0);
`
``
619
`+
if (longval == NULL) goto fail;
`
``
620
+
``
621
`+
longtype = PyObject_Type(longval);
`
``
622
`+
if (longtype == NULL) goto fail;
`
``
623
+
``
624
`+
PyObject *abs = PyObject_GetAttrString(longtype, "abs");
`
``
625
`+
if (abs == NULL) goto fail;
`
``
626
+
``
627
`+
Py_DECREF(longtype);
`
``
628
`+
Py_DECREF(longval);
`
``
629
`+
randomstate(m)->Long___abs_ = abs;
`
``
630
+
602
631
`return m;
`
``
632
+
``
633
`+
fail:
`
``
634
`+
Py_XDECREF(longtype);
`
``
635
`+
Py_XDECREF(longval);
`
``
636
`+
Py_DECREF(m);
`
``
637
`+
return NULL;
`
603
638
`}
`