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

Skip to content

Commit 368e434

Browse files
committed
gh-95991: Add some infrastructure for testing Limited API in _testcapi
- 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 4a7f5a5 commit 368e434

File tree

5 files changed

+55
-21
lines changed

5 files changed

+55
-21
lines changed

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.skipIf(True, 'needs _testcapi module')(test)
1078+
return unittest.skipIf(
1079+
not _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: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,39 @@
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
14+
15+
// Always enable assertions
16+
#undef NDEBUG
17+
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+
125
#include "Python.h"
226

327
/* Always enable assertions */
428
#undef NDEBUG
529

630
int _PyTestCapi_Init_Vectorcall(PyObject *module);
7-
int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
831
int _PyTestCapi_Init_Heaptype(PyObject *module);
932
int _PyTestCapi_Init_Unicode(PyObject *module);
33+
34+
#ifdef LIMITED_API_AVAILABLE
35+
int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
36+
#endif // LIMITED_API_AVAILABLE
37+
38+
#endif
39+
#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
}

0 commit comments

Comments
 (0)
0