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