(self)
| 727 | |
| 728 | |
| 729 | def test_vectorcall(self): |
| 730 | # Test a bunch of different ways to call objects: |
| 731 | # 1. vectorcall using PyVectorcall_Call() |
| 732 | # (only for objects that support vectorcall directly) |
| 733 | # 2. normal call |
| 734 | # 3. vectorcall using PyObject_Vectorcall() |
| 735 | # 4. call as bound method |
| 736 | # 5. call using functools.partial |
| 737 | |
| 738 | # A list of (function, args, kwargs, result) calls to test |
| 739 | calls = [(len, (range(42),), {}, 42), |
| 740 | (list.append, ([], 0), {}, None), |
| 741 | ([].append, (0,), {}, None), |
| 742 | (sum, ([36],), {"start":6}, 42), |
| 743 | (testfunction, (42,), {}, 42), |
| 744 | (testfunction_kw, (42,), {"kw":None}, 42), |
| 745 | (_testcapi.MethodDescriptorBase(), (0,), {}, True), |
| 746 | (_testcapi.MethodDescriptorDerived(), (0,), {}, True), |
| 747 | (_testcapi.MethodDescriptor2(), (0,), {}, False)] |
| 748 | |
| 749 | from _testcapi import pyobject_vectorcall, pyvectorcall_call |
| 750 | from types import MethodType |
| 751 | from functools import partial |
| 752 | |
| 753 | def vectorcall(func, args, kwargs): |
| 754 | args = *args, *kwargs.values() |
| 755 | kwnames = tuple(kwargs) |
| 756 | return pyobject_vectorcall(func, args, kwnames) |
| 757 | |
| 758 | for (func, args, kwargs, expected) in calls: |
| 759 | with self.subTest(str(func)): |
| 760 | if not kwargs: |
| 761 | self.assertEqual(expected, pyvectorcall_call(func, args)) |
| 762 | self.assertEqual(expected, pyvectorcall_call(func, args, kwargs)) |
| 763 | |
| 764 | # Add derived classes (which do not support vectorcall directly, |
| 765 | # but do support all other ways of calling). |
| 766 | |
| 767 | class MethodDescriptorHeap(_testcapi.MethodDescriptorBase): |
| 768 | pass |
| 769 | |
| 770 | class MethodDescriptorOverridden(_testcapi.MethodDescriptorBase): |
| 771 | def __call__(self, n): |
| 772 | return 'new' |
| 773 | |
| 774 | class SuperBase: |
| 775 | def __call__(self, *args): |
| 776 | return super().__call__(*args) |
| 777 | |
| 778 | class MethodDescriptorSuper(SuperBase, _testcapi.MethodDescriptorBase): |
| 779 | def __call__(self, *args): |
| 780 | return super().__call__(*args) |
| 781 | |
| 782 | calls += [ |
| 783 | (dict.update, ({},), {"key":True}, None), |
| 784 | ({}.update, ({},), {"key":True}, None), |
| 785 | (MethodDescriptorHeap(), (0,), {}, True), |
| 786 | (MethodDescriptorOverridden(), (0,), {}, 'new'), |
nothing calls this directly
no test coverage detected