bpo-37191: Move TestPEP590 from test_capi to test_call (GH-13892) · python/cpython@740a84d (original) (raw)

`@@ -27,18 +27,11 @@

`

27

27

`# Were we compiled --with-pydebug or with #define Py_DEBUG?

`

28

28

`Py_DEBUG = hasattr(sys, 'gettotalrefcount')

`

29

29

``

30

``

`-

Py_TPFLAGS_HAVE_VECTORCALL = 1 << 11

`

31

``

`-

Py_TPFLAGS_METHOD_DESCRIPTOR = 1 << 17

`

32

``

-

33

30

``

34

31

`def testfunction(self):

`

35

32

`"""some doc"""

`

36

33

`return self

`

37

34

``

38

``

`-

def testfunction_kw(self, *, kw):

`

39

``

`-

"""some doc"""

`

40

``

`-

return self

`

41

``

-

42

35

``

43

36

`class InstanceMethod:

`

44

37

`id = _testcapi.instancemethod(id)

`

`@@ -471,114 +464,6 @@ def test_pendingcalls_non_threaded(self):

`

471

464

`self.pendingcalls_wait(l, n)

`

472

465

``

473

466

``

474

``

`-

class TestPEP590(unittest.TestCase):

`

475

``

-

476

``

`-

def test_method_descriptor_flag(self):

`

477

``

`-

import functools

`

478

``

`-

cached = functools.lru_cache(1)(testfunction)

`

479

``

-

480

``

`-

self.assertFalse(type(repr).flags & Py_TPFLAGS_METHOD_DESCRIPTOR)

`

481

``

`-

self.assertTrue(type(list.append).flags & Py_TPFLAGS_METHOD_DESCRIPTOR)

`

482

``

`-

self.assertTrue(type(list.add).flags & Py_TPFLAGS_METHOD_DESCRIPTOR)

`

483

``

`-

self.assertTrue(type(testfunction).flags & Py_TPFLAGS_METHOD_DESCRIPTOR)

`

484

``

`-

self.assertTrue(type(cached).flags & Py_TPFLAGS_METHOD_DESCRIPTOR)

`

485

``

-

486

``

`-

self.assertTrue(_testcapi.MethodDescriptorBase.flags & Py_TPFLAGS_METHOD_DESCRIPTOR)

`

487

``

`-

self.assertTrue(_testcapi.MethodDescriptorDerived.flags & Py_TPFLAGS_METHOD_DESCRIPTOR)

`

488

``

`-

self.assertFalse(_testcapi.MethodDescriptorNopGet.flags & Py_TPFLAGS_METHOD_DESCRIPTOR)

`

489

``

-

490

``

`-

Heap type should not inherit Py_TPFLAGS_METHOD_DESCRIPTOR

`

491

``

`-

class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):

`

492

``

`-

pass

`

493

``

`-

self.assertFalse(MethodDescriptorHeap.flags & Py_TPFLAGS_METHOD_DESCRIPTOR)

`

494

``

-

495

``

`-

def test_vectorcall_flag(self):

`

496

``

`-

self.assertTrue(_testcapi.MethodDescriptorBase.flags & Py_TPFLAGS_HAVE_VECTORCALL)

`

497

``

`-

self.assertTrue(_testcapi.MethodDescriptorDerived.flags & Py_TPFLAGS_HAVE_VECTORCALL)

`

498

``

`-

self.assertFalse(_testcapi.MethodDescriptorNopGet.flags & Py_TPFLAGS_HAVE_VECTORCALL)

`

499

``

`-

self.assertTrue(_testcapi.MethodDescriptor2.flags & Py_TPFLAGS_HAVE_VECTORCALL)

`

500

``

-

501

``

`-

Heap type should not inherit Py_TPFLAGS_HAVE_VECTORCALL

`

502

``

`-

class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):

`

503

``

`-

pass

`

504

``

`-

self.assertFalse(MethodDescriptorHeap.flags & Py_TPFLAGS_HAVE_VECTORCALL)

`

505

``

-

506

``

`-

def test_vectorcall_override(self):

`

507

``

`-

Check that tp_call can correctly override vectorcall.

`

508

``

`-

MethodDescriptorNopGet implements tp_call but it inherits from

`

509

``

`-

MethodDescriptorBase, which implements vectorcall. Since

`

510

``

`-

MethodDescriptorNopGet returns the args tuple when called, we check

`

511

``

`-

additionally that no new tuple is created for this call.

`

512

``

`-

args = tuple(range(5))

`

513

``

`-

f = _testcapi.MethodDescriptorNopGet()

`

514

``

`-

self.assertIs(f(*args), args)

`

515

``

-

516

``

`-

def test_vectorcall(self):

`

517

``

`-

Test a bunch of different ways to call objects:

`

518

``

`-

1. vectorcall using PyVectorcall_Call()

`

519

``

`-

(only for objects that support vectorcall directly)

`

520

``

`-

2. normal call

`

521

``

`-

3. vectorcall using _PyObject_Vectorcall()

`

522

``

`-

4. call as bound method

`

523

``

`-

5. call using functools.partial

`

524

``

-

525

``

`-

A list of (function, args, kwargs, result) calls to test

`

526

``

`-

calls = [(len, (range(42),), {}, 42),

`

527

``

`-

(list.append, ([], 0), {}, None),

`

528

``

`-

([].append, (0,), {}, None),

`

529

``

`-

(sum, ([36],), {"start":6}, 42),

`

530

``

`-

(testfunction, (42,), {}, 42),

`

531

``

`-

(testfunction_kw, (42,), {"kw":None}, 42),

`

532

``

`-

(_testcapi.MethodDescriptorBase(), (0,), {}, True),

`

533

``

`-

(_testcapi.MethodDescriptorDerived(), (0,), {}, True),

`

534

``

`-

(_testcapi.MethodDescriptor2(), (0,), {}, False)]

`

535

``

-

536

``

`-

from _testcapi import pyobject_vectorcall, pyvectorcall_call

`

537

``

`-

from types import MethodType

`

538

``

`-

from functools import partial

`

539

``

-

540

``

`-

def vectorcall(func, args, kwargs):

`

541

``

`-

args = *args, *kwargs.values()

`

542

``

`-

kwnames = tuple(kwargs)

`

543

``

`-

return pyobject_vectorcall(func, args, kwnames)

`

544

``

-

545

``

`-

for (func, args, kwargs, expected) in calls:

`

546

``

`-

with self.subTest(str(func)):

`

547

``

`-

if not kwargs:

`

548

``

`-

self.assertEqual(expected, pyvectorcall_call(func, args))

`

549

``

`-

self.assertEqual(expected, pyvectorcall_call(func, args, kwargs))

`

550

``

-

551

``

`-

Add derived classes (which do not support vectorcall directly,

`

552

``

`-

but do support all other ways of calling).

`

553

``

-

554

``

`-

class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):

`

555

``

`-

pass

`

556

``

-

557

``

`-

class MethodDescriptorOverridden(_testcapi.MethodDescriptorBase):

`

558

``

`-

def call(self, n):

`

559

``

`-

return 'new'

`

560

``

-

561

``

`-

calls += [

`

562

``

`-

(MethodDescriptorHeap(), (0,), {}, True),

`

563

``

`-

(MethodDescriptorOverridden(), (0,), {}, 'new'),

`

564

``

`-

]

`

565

``

-

566

``

`-

for (func, args, kwargs, expected) in calls:

`

567

``

`-

with self.subTest(str(func)):

`

568

``

`-

args1 = args[1:]

`

569

``

`-

meth = MethodType(func, args[0])

`

570

``

`-

wrapped = partial(func)

`

571

``

`-

if not kwargs:

`

572

``

`-

self.assertEqual(expected, func(*args))

`

573

``

`-

self.assertEqual(expected, pyobject_vectorcall(func, args, None))

`

574

``

`-

self.assertEqual(expected, meth(*args1))

`

575

``

`-

self.assertEqual(expected, wrapped(*args))

`

576

``

`-

self.assertEqual(expected, func(*args, **kwargs))

`

577

``

`-

self.assertEqual(expected, vectorcall(func, args, kwargs))

`

578

``

`-

self.assertEqual(expected, meth(*args1, **kwargs))

`

579

``

`-

self.assertEqual(expected, wrapped(*args, **kwargs))

`

580

``

-

581

``

-

582

467

`class SubinterpreterTest(unittest.TestCase):

`

583

468

``

584

469

`def test_subinterps(self):

`