bpo-29102: Add a unique ID to PyInterpreterState. (#1639) · python/cpython@e377416 (original) (raw)

1

1

`# Run the _testcapi module tests (tests for the Python/C API): by defn,

`

2

2

`# these are all functions testcapi exports whose name begins with 'test'.

`

3

3

``

``

4

`+

from collections import namedtuple

`

4

5

`import os

`

5

6

`import pickle

`

``

7

`+

import platform

`

6

8

`import random

`

7

9

`import re

`

8

10

`import subprocess

`

`@@ -384,12 +386,91 @@ def run_embedded_interpreter(self, *args):

`

384

386

`return out, err

`

385

387

``

386

388

`def test_subinterps(self):

`

387

``

`-

This is just a "don't crash" test

`

388

389

`out, err = self.run_embedded_interpreter("repeated_init_and_subinterpreters")

`

389

``

`-

if support.verbose:

`

390

``

`-

print()

`

391

``

`-

print(out)

`

392

``

`-

print(err)

`

``

390

`+

self.assertEqual(err, "")

`

``

391

+

``

392

`+

The output from _testembed looks like this:

`

``

393

`+

--- Pass 0 ---

`

``

394

`+

interp 0 <0x1cf9330>, thread state <0x1cf9700>: id(modules) = 139650431942728

`

``

395

`+

interp 1 <0x1d4f690>, thread state <0x1d35350>: id(modules) = 139650431165784

`

``

396

`+

interp 2 <0x1d5a690>, thread state <0x1d99ed0>: id(modules) = 139650413140368

`

``

397

`+

interp 3 <0x1d4f690>, thread state <0x1dc3340>: id(modules) = 139650412862200

`

``

398

`+

interp 0 <0x1cf9330>, thread state <0x1cf9700>: id(modules) = 139650431942728

`

``

399

`+

--- Pass 1 ---

`

``

400

`+

...

`

``

401

+

``

402

`+

interp_pat = (r"^interp (\d+) <(0x[\dA-F]+)>, "

`

``

403

`+

r"thread state <(0x[\dA-F]+)>: "

`

``

404

`+

r"id(modules) = ([\d]+)$")

`

``

405

`+

Interp = namedtuple("Interp", "id interp tstate modules")

`

``

406

+

``

407

`+

main = None

`

``

408

`+

lastmain = None

`

``

409

`+

numinner = None

`

``

410

`+

numloops = 0

`

``

411

`+

for line in out.splitlines():

`

``

412

`+

if line == "--- Pass {} ---".format(numloops):

`

``

413

`+

if numinner is not None:

`

``

414

`+

self.assertEqual(numinner, 5)

`

``

415

`+

if support.verbose:

`

``

416

`+

print(line)

`

``

417

`+

lastmain = main

`

``

418

`+

main = None

`

``

419

`+

mainid = 0

`

``

420

`+

numloops += 1

`

``

421

`+

numinner = 0

`

``

422

`+

continue

`

``

423

`+

numinner += 1

`

``

424

+

``

425

`+

self.assertLessEqual(numinner, 5)

`

``

426

`+

match = re.match(interp_pat, line)

`

``

427

`+

if match is None:

`

``

428

`+

self.assertRegex(line, interp_pat)

`

``

429

+

``

430

`+

The last line in the loop should be the same as the first.

`

``

431

`+

if numinner == 5:

`

``

432

`+

self.assertEqual(match.groups(), main)

`

``

433

`+

continue

`

``

434

+

``

435

`+

Parse the line from the loop. The first line is the main

`

``

436

`+

interpreter and the 3 afterward are subinterpreters.

`

``

437

`+

interp = Interp(*match.groups())

`

``

438

`+

if support.verbose:

`

``

439

`+

print(interp)

`

``

440

`+

if numinner == 1:

`

``

441

`+

main = interp

`

``

442

`+

id = str(mainid)

`

``

443

`+

else:

`

``

444

`+

subid = mainid + numinner - 1

`

``

445

`+

id = str(subid)

`

``

446

+

``

447

`+

Validate the loop line for each interpreter.

`

``

448

`+

self.assertEqual(interp.id, id)

`

``

449

`+

self.assertTrue(interp.interp)

`

``

450

`+

self.assertTrue(interp.tstate)

`

``

451

`+

self.assertTrue(interp.modules)

`

``

452

`+

if platform.system() == 'Windows':

`

``

453

`+

XXX Fix on Windows: something is going on with the

`

``

454

`+

pointers in Programs/_testembed.c. interp.interp

`

``

455

`+

is 0x0 and # interp.modules is the same between

`

``

456

`+

interpreters.

`

``

457

`+

continue

`

``

458

`+

if interp is main:

`

``

459

`+

if lastmain is not None:

`

``

460

`+

A new main interpreter may have the same interp

`

``

461

`+

and/or tstate pointer as an earlier finalized/

`

``

462

`+

destroyed one. So we do not check interp or

`

``

463

`+

tstate here.

`

``

464

`+

self.assertNotEqual(interp.modules, lastmain.modules)

`

``

465

`+

else:

`

``

466

`+

A new subinterpreter may have the same

`

``

467

`+

PyInterpreterState pointer as a previous one if

`

``

468

`+

the earlier one has already been destroyed. So

`

``

469

`+

we compare with the main interpreter. The same

`

``

470

`+

applies to tstate.

`

``

471

`+

self.assertNotEqual(interp.interp, main.interp)

`

``

472

`+

self.assertNotEqual(interp.tstate, main.tstate)

`

``

473

`+

self.assertNotEqual(interp.modules, main.modules)

`

393

474

``

394

475

`@staticmethod

`

395

476

`def _get_default_pipe_encoding():

`