8000 gh-95991: Add some infrastructure for testing Limited API in _testcap… · python/cpython@0f2b469 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0f2b469

Browse files
authored
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.)
1 parent 7276ca2 commit 0f2b469

File tree

7 files changed

+64
-23
lines changed

7 files changed

+64
-23
lines changed

Doc/library/test.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,12 @@ The :mod:`test.support` module defines the following functions:
794794
Decorator for only running the test if :data:`HAVE_DOCSTRINGS`.
795795

796796

797+
.. decorator:: requires_limited_api
798+
799+
Decorator for only running the test if :ref:`Limited C API <stable>`
800+
is available.
801+
802+
797803
.. decorator:: cpython_only
798804

799805
Decorator for tests only applicable to CPython.

Lib/test/support/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"anticipate_failure", "load_package_tests", "detect_api_mismatch",
4747
"check__all__", "skip_if_buggy_ucrt_strfptime",
4848
"check_disallow_instantiation", "check_sanitizer", "skip_if_sanitizer",
49+
"requires_limited_api",
4950
# sys
5051
"is_jython", "is_android", "is_emscripten", "is_wasi",
5152
"check_impl_detail", "unix_shell", "setswitchinterval",
@@ -1069,6 +1070,15 @@ def refcount_test(test):
10691070
return no_tracing(cpython_only(test))
10701071

10711072

1073+
def requires_limited_api(test):
1074+
try:
1075+
import _testcapi
1076+
except ImportError:
1077+
return unittest.skip('needs _testcapi module')(test)
1078+
return unittest.skipUnless(
1079+
_testcapi.LIMITED_API_AVAILABLE, 'needs Limited API support')(test)
1080+
1081+
10721082
def _filter_suite(suite, pred):
10731083
"""Recursively filter test cases in a suite based on a predicate."""
10741084
newtests = []

Lib/test/test_call.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import unittest
2-
from test.support import cpython_only
2+
from test.support import cpython_only, requires_limited_api
33
try:
44
import _testcapi
55
except ImportError:
@@ -760,9 +760,7 @@ def __call__(self, *args):
760760
self.assertEqual(expected, meth(*args1, **kwargs))
761761
self.assertEqual(expected, wrapped(*args, **kwargs))
762762

763-
@unittest.skipIf(
764-
hasattr(sys, 'getobjects'),
765-
"Limited API is not compatible with Py_TRACE_REFS")
763+
@requires_limited_api
766764
def test_vectorcall_limited(self):
767765
from _testcapi import pyobject_vectorcall
768766
obj = _testcapi.LimitedVectorCallClass()

Modules/_testcapi/parts.h

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,36 @@
1-
#include "Python.h"
1+
#ifndef Py_TESTCAPI_PARTS_H
2+
#define Py_TESTCAPI_PARTS_H
3+
4+
#include "pyconfig.h" // for Py_TRACE_REFS
5+
6+
// Figure out if Limited API is available for this build. If it isn't we won't
7+
// build tests for it.
8+
// Currently, only Py_TRACE_REFS disables Limited API.
9+
#ifdef Py_TRACE_REFS
10+
#undef LIMITED_API_AVAILABLE
11+
#else
12+
#define LIMITED_API_AVAILABLE 1
13+
#endif
214

3-
/* Always enable assertions */
15+
// Always enable assertions
416
#undef NDEBUG
517

18+
#if !defined(LIMITED_API_AVAILABLE) && defined(Py_LIMITED_API)
19+
// Limited API being unavailable means that with Py_LIMITED_API defined
20+
// we can't even include Python.h.
21+
// Do nothing; the .c file that defined Py_LIMITED_API should also do nothing.
22+
23+
#else
24+
25+
#include "Python.h"
26+
627
int _PyTestCapi_Init_Vectorcall(PyObject *module);
7-
int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
828
int _PyTestCapi_Init_Heaptype(PyObject *module);
929
int _PyTestCapi_Init_Unicode(PyObject *module);
30+
31+
#ifdef LIMITED_API_AVAILABLE
32+
int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
33+
#endif // LIMITED_API_AVAILABLE
34+
35+
#endif
36+
#endif // Py_TESTCAPI_PARTS_H

Modules/_testcapi/vectorcall_limited.c

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,8 @@
1-
#include "pyconfig.h" // Py_TRACE_REFS
2-
3-
#ifdef Py_TRACE_REFS
4-
5-
// Py_TRACE_REFS is incompatible with Limited API
1+
#define Py_LIMITED_API 0x030c0000 // 3.12
62
#include "parts.h"
7-
int
8-
_PyTestCapi_Init_VectorcallLimited(PyObject *m) {
9-
return 0;
10-
}
113

12-
#else
4+
#ifdef LIMITED_API_AVAILABLE
135

14-
#define Py_LIMITED_API 0x030c0000 // 3.12
15-
#include "parts.h"
166
#include "structmember.h" // PyMemberDef
177

188
/* Test Vectorcall in the limited API */
@@ -89,4 +79,4 @@ _PyTestCapi_Init_VectorcallLimited(PyObject *m) {
8979
return 0;
9080
}
9181

92-
#endif // Py_TRACE_REFS
82+
#endif // LIMITED_API_AVAILABLE

Modules/_testcapimodule.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6544,16 +6544,22 @@ PyInit__testcapi(void)
65446544
if (_PyTestCapi_Init_Vectorcall(m) < 0) {
65456545
return NULL;
65466546
}
6547-
if (_PyTestCapi_Init_VectorcallLimited(m) < 0) {
6548-
return NULL;
6549-
}
65506547
if (_PyTestCapi_Init_Heaptype(m) < 0) {
65516548
return NULL;
65526549
}
65536550
if (_PyTestCapi_Init_Unicode(m) < 0) {
65546551
return NULL;
65556552
}
65566553

6554+
#ifndef LIMITED_API_AVAILABLE
6555+
PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_False);
6556+
#else
6557+
PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_True);
6558+
if (_PyTestCapi_Init_VectorcallLimited(m) < 0) {
6559+
return NULL;
6560+
}
6561+
#endif
6562+
65576563
PyState_AddModule(m, &_testcapimodule);
65586564
return m;
65596565
}

PCbuild/_testcapi.vcxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@
107107
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
108108
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
109109
</ProjectReference>
110+
<ProjectReference Include="python3dll.vcxproj">
111+
<Project>{885d4898-d08d-4091-9c40-c700cfe3fc5a}</Project>
112+
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
113+
</ProjectReference>
110114
</ItemGroup>
111115
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
112116
<ImportGroup Label="ExtensionTargets">

0 commit comments

Comments
 (0)
0