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

`}

`