mirror of
https://github.com/python/cpython
synced 2024-09-16 00:37:36 +00:00
gh-95991: Add some infrastructure for testing Limited API in _testcapi (GH-95992)
- Limited API needs to be enabled per source file - Some builds don't support Limited API, so Limited API tests must be skipped on those builds (currently this is `Py_TRACE_REFS`, but that may change.) - `Py_LIMITED_API` must be defined before `<Python.h>` is included. This puts the hoop-jumping in `testcapi/parts.h`, so individual test files can be relatively simple. (Currently that's only `vectorcall_limited.c`, imagine more.)
This commit is contained in:
parent
7276ca25f5
commit
0f2b469ce1
|
@ -794,6 +794,12 @@ The :mod:`test.support` module defines the following functions:
|
||||||
Decorator for only running the test if :data:`HAVE_DOCSTRINGS`.
|
Decorator for only running the test if :data:`HAVE_DOCSTRINGS`.
|
||||||
|
|
||||||
|
|
||||||
|
.. decorator:: requires_limited_api
|
||||||
|
|
||||||
|
Decorator for only running the test if :ref:`Limited C API <stable>`
|
||||||
|
is available.
|
||||||
|
|
||||||
|
|
||||||
.. decorator:: cpython_only
|
.. decorator:: cpython_only
|
||||||
|
|
||||||
Decorator for tests only applicable to CPython.
|
Decorator for tests only applicable to CPython.
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
"anticipate_failure", "load_package_tests", "detect_api_mismatch",
|
"anticipate_failure", "load_package_tests", "detect_api_mismatch",
|
||||||
"check__all__", "skip_if_buggy_ucrt_strfptime",
|
"check__all__", "skip_if_buggy_ucrt_strfptime",
|
||||||
"check_disallow_instantiation", "check_sanitizer", "skip_if_sanitizer",
|
"check_disallow_instantiation", "check_sanitizer", "skip_if_sanitizer",
|
||||||
|
"requires_limited_api",
|
||||||
# sys
|
# sys
|
||||||
"is_jython", "is_android", "is_emscripten", "is_wasi",
|
"is_jython", "is_android", "is_emscripten", "is_wasi",
|
||||||
"check_impl_detail", "unix_shell", "setswitchinterval",
|
"check_impl_detail", "unix_shell", "setswitchinterval",
|
||||||
|
@ -1069,6 +1070,15 @@ def refcount_test(test):
|
||||||
return no_tracing(cpython_only(test))
|
return no_tracing(cpython_only(test))
|
||||||
|
|
||||||
|
|
||||||
|
def requires_limited_api(test):
|
||||||
|
try:
|
||||||
|
import _testcapi
|
||||||
|
except ImportError:
|
||||||
|
return unittest.skip('needs _testcapi module')(test)
|
||||||
|
return unittest.skipUnless(
|
||||||
|
_testcapi.LIMITED_API_AVAILABLE, 'needs Limited API support')(test)
|
||||||
|
|
||||||
|
|
||||||
def _filter_suite(suite, pred):
|
def _filter_suite(suite, pred):
|
||||||
"""Recursively filter test cases in a suite based on a predicate."""
|
"""Recursively filter test cases in a suite based on a predicate."""
|
||||||
newtests = []
|
newtests = []
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import unittest
|
import unittest
|
||||||
from test.support import cpython_only
|
from test.support import cpython_only, requires_limited_api
|
||||||
try:
|
try:
|
||||||
import _testcapi
|
import _testcapi
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -760,9 +760,7 @@ def __call__(self, *args):
|
||||||
self.assertEqual(expected, meth(*args1, **kwargs))
|
self.assertEqual(expected, meth(*args1, **kwargs))
|
||||||
self.assertEqual(expected, wrapped(*args, **kwargs))
|
self.assertEqual(expected, wrapped(*args, **kwargs))
|
||||||
|
|
||||||
@unittest.skipIf(
|
@requires_limited_api
|
||||||
hasattr(sys, 'getobjects'),
|
|
||||||
"Limited API is not compatible with Py_TRACE_REFS")
|
|
||||||
def test_vectorcall_limited(self):
|
def test_vectorcall_limited(self):
|
||||||
from _testcapi import pyobject_vectorcall
|
from _testcapi import pyobject_vectorcall
|
||||||
obj = _testcapi.LimitedVectorCallClass()
|
obj = _testcapi.LimitedVectorCallClass()
|
||||||
|
|
|
@ -1,9 +1,36 @@
|
||||||
#include "Python.h"
|
#ifndef Py_TESTCAPI_PARTS_H
|
||||||
|
#define Py_TESTCAPI_PARTS_H
|
||||||
|
|
||||||
/* Always enable assertions */
|
#include "pyconfig.h" // for Py_TRACE_REFS
|
||||||
|
|
||||||
|
// Figure out if Limited API is available for this build. If it isn't we won't
|
||||||
|
// build tests for it.
|
||||||
|
// Currently, only Py_TRACE_REFS disables Limited API.
|
||||||
|
#ifdef Py_TRACE_REFS
|
||||||
|
#undef LIMITED_API_AVAILABLE
|
||||||
|
#else
|
||||||
|
#define LIMITED_API_AVAILABLE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Always enable assertions
|
||||||
#undef NDEBUG
|
#undef NDEBUG
|
||||||
|
|
||||||
|
#if !defined(LIMITED_API_AVAILABLE) && defined(Py_LIMITED_API)
|
||||||
|
// Limited API being unavailable means that with Py_LIMITED_API defined
|
||||||
|
// we can't even include Python.h.
|
||||||
|
// Do nothing; the .c file that defined Py_LIMITED_API should also do nothing.
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "Python.h"
|
||||||
|
|
||||||
int _PyTestCapi_Init_Vectorcall(PyObject *module);
|
int _PyTestCapi_Init_Vectorcall(PyObject *module);
|
||||||
int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
|
|
||||||
int _PyTestCapi_Init_Heaptype(PyObject *module);
|
int _PyTestCapi_Init_Heaptype(PyObject *module);
|
||||||
int _PyTestCapi_Init_Unicode(PyObject *module);
|
int _PyTestCapi_Init_Unicode(PyObject *module);
|
||||||
|
|
||||||
|
#ifdef LIMITED_API_AVAILABLE
|
||||||
|
int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
|
||||||
|
#endif // LIMITED_API_AVAILABLE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif // Py_TESTCAPI_PARTS_H
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
#include "pyconfig.h" // Py_TRACE_REFS
|
|
||||||
|
|
||||||
#ifdef Py_TRACE_REFS
|
|
||||||
|
|
||||||
// Py_TRACE_REFS is incompatible with Limited API
|
|
||||||
#include "parts.h"
|
|
||||||
int
|
|
||||||
_PyTestCapi_Init_VectorcallLimited(PyObject *m) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define Py_LIMITED_API 0x030c0000 // 3.12
|
#define Py_LIMITED_API 0x030c0000 // 3.12
|
||||||
#include "parts.h"
|
#include "parts.h"
|
||||||
|
|
||||||
|
#ifdef LIMITED_API_AVAILABLE
|
||||||
|
|
||||||
#include "structmember.h" // PyMemberDef
|
#include "structmember.h" // PyMemberDef
|
||||||
|
|
||||||
/* Test Vectorcall in the limited API */
|
/* Test Vectorcall in the limited API */
|
||||||
|
@ -89,4 +79,4 @@ _PyTestCapi_Init_VectorcallLimited(PyObject *m) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // Py_TRACE_REFS
|
#endif // LIMITED_API_AVAILABLE
|
||||||
|
|
|
@ -6544,9 +6544,6 @@ PyInit__testcapi(void)
|
||||||
if (_PyTestCapi_Init_Vectorcall(m) < 0) {
|
if (_PyTestCapi_Init_Vectorcall(m) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (_PyTestCapi_Init_VectorcallLimited(m) < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (_PyTestCapi_Init_Heaptype(m) < 0) {
|
if (_PyTestCapi_Init_Heaptype(m) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -6554,6 +6551,15 @@ PyInit__testcapi(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef LIMITED_API_AVAILABLE
|
||||||
|
PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_False);
|
||||||
|
#else
|
||||||
|
PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_True);
|
||||||
|
if (_PyTestCapi_Init_VectorcallLimited(m) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
PyState_AddModule(m, &_testcapimodule);
|
PyState_AddModule(m, &_testcapimodule);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,10 @@
|
||||||
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
|
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
|
||||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="python3dll.vcxproj">
|
||||||
|
<Project>{885d4898-d08d-4091-9c40-c700cfe3fc5a}</Project>
|
||||||
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
Loading…
Reference in a new issue