Skip to content

Commit 1312094

Browse files
authored
gh-116869: Test the limited C API in test_cext (#116995)
1 parent 0f27801 commit 1312094

File tree

3 files changed

+55
-30
lines changed

3 files changed

+55
-30
lines changed

Lib/test/test_cext/__init__.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,35 @@
2727
@support.requires_resource('cpu')
2828
class TestExt(unittest.TestCase):
2929
def test_build_c99(self):
30-
self.check_build('c99', '_test_c99_ext')
30+
self.check_build('_test_c99_ext', std='c99')
3131

3232
def test_build_c11(self):
33-
self.check_build('c11', '_test_c11_ext')
33+
self.check_build('_test_c11_ext', std='c11')
3434

35-
def check_build(self, clang_std, extension_name):
35+
def test_build_limited(self):
36+
self.check_build('_test_limited_ext', limited=True)
37+
38+
def test_build_limited_c11(self):
39+
self.check_build('_test_limited_c11_ext', limited=True, std='c11')
40+
41+
def check_build(self, extension_name, std=None, limited=False):
3642
venv_dir = 'env'
3743
with support.setup_venv_with_pip_setuptools_wheel(venv_dir) as python_exe:
38-
self._check_build(clang_std, extension_name, python_exe)
44+
self._check_build(extension_name, python_exe,
45+
std=std, limited=limited)
3946

40-
def _check_build(self, clang_std, extension_name, python_exe):
47+
def _check_build(self, extension_name, python_exe, std, limited):
4148
pkg_dir = 'pkg'
4249
os.mkdir(pkg_dir)
4350
shutil.copy(SETUP, os.path.join(pkg_dir, os.path.basename(SETUP)))
4451
shutil.copy(SOURCE, os.path.join(pkg_dir, os.path.basename(SOURCE)))
4552

4653
def run_cmd(operation, cmd):
4754
env = os.environ.copy()
48-
env['CPYTHON_TEST_STD'] = clang_std
55+
if std:
56+
env['CPYTHON_TEST_STD'] = std
57+
if limited:
58+
env['CPYTHON_TEST_LIMITED'] = '1'
4959
env['CPYTHON_TEST_EXT_NAME'] = extension_name
5060
if support.verbose:
5161
print('Run:', ' '.join(cmd))

Lib/test/test_cext/extension.c

+6-10
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,8 @@
66

77
#include "Python.h"
88

9-
#if defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L
10-
# define NAME _test_c2x_ext
11-
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
12-
# define NAME _test_c11_ext
13-
#else
14-
# define NAME _test_c99_ext
9+
#ifndef MODULE_NAME
10+
# error "MODULE_NAME macro must be defined"
1511
#endif
1612

1713
#define _STR(NAME) #NAME
@@ -25,11 +21,11 @@ PyDoc_STRVAR(_testcext_add_doc,
2521
static PyObject *
2622
_testcext_add(PyObject *Py_UNUSED(module), PyObject *args)
2723
{
28-
long i, j;
24+
long i, j, res;
2925
if (!PyArg_ParseTuple(args, "ll:foo", &i, &j)) {
3026
return NULL;
3127
}
32-
long res = i + j;
28+
res = i + j;
3329
return PyLong_FromLong(res);
3430
}
3531

@@ -59,7 +55,7 @@ PyDoc_STRVAR(_testcext_doc, "C test extension.");
5955

6056
static struct PyModuleDef _testcext_module = {
6157
PyModuleDef_HEAD_INIT, // m_base
62-
STR(NAME), // m_name
58+
STR(MODULE_NAME), // m_name
6359
_testcext_doc, // m_doc
6460
0, // m_size
6561
_testcext_methods, // m_methods
@@ -74,7 +70,7 @@ static struct PyModuleDef _testcext_module = {
7470
#define FUNC_NAME(NAME) _FUNC_NAME(NAME)
7571

7672
PyMODINIT_FUNC
77-
FUNC_NAME(NAME)(void)
73+
FUNC_NAME(MODULE_NAME)(void)
7874
{
7975
return PyModuleDef_Init(&_testcext_module);
8076
}

Lib/test/test_cext/setup.py

+33-14
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,43 @@
2727

2828

2929
def main():
30-
std = os.environ["CPYTHON_TEST_STD"]
31-
name = os.environ["CPYTHON_TEST_EXT_NAME"]
32-
cflags = [*CFLAGS, f'-std={std}']
33-
34-
# Remove existing -std options to only test ours
35-
cmd = (sysconfig.get_config_var('CC') or '')
36-
if cmd is not None:
37-
cmd = shlex.split(cmd)
38-
cmd = [arg for arg in cmd if not arg.startswith('-std=')]
39-
cmd = shlex.join(cmd)
40-
# CC env var overrides sysconfig CC variable in setuptools
41-
os.environ['CC'] = cmd
30+
std = os.environ.get("CPYTHON_TEST_STD", "")
31+
module_name = os.environ["CPYTHON_TEST_EXT_NAME"]
32+
limited = bool(os.environ.get("CPYTHON_TEST_LIMITED", ""))
33+
34+
cflags = list(CFLAGS)
35+
cflags.append(f'-DMODULE_NAME={module_name}')
36+
37+
if std:
38+
cflags.append(f'-std={std}')
39+
40+
# Remove existing -std options to only test ours
41+
cmd = (sysconfig.get_config_var('CC') or '')
42+
if cmd is not None:
43+
cmd = shlex.split(cmd)
44+
cmd = [arg for arg in cmd if not arg.startswith('-std=')]
45+
cmd = shlex.join(cmd)
46+
# CC env var overrides sysconfig CC variable in setuptools
47+
os.environ['CC'] = cmd
48+
49+
if limited:
50+
version = sys.hexversion
51+
cflags.append(f'-DPy_LIMITED_API={version:#x}')
52+
53+
for env_name in ('CC', 'CFLAGS'):
54+
if env_name in os.environ:
55+
print(f"{env_name} env var: {os.environ[env_name]!r}")
56+
else:
57+
print(f"{env_name} env var: <missing>")
58+
print(f"extra_compile_args: {cflags!r}")
4259

4360
ext = Extension(
44-
name,
61+
module_name,
4562
sources=[SOURCE],
4663
extra_compile_args=cflags)
47-
setup(name='internal' + name, version='0.0', ext_modules=[ext])
64+
setup(name=f'internal_{module_name}',
65+
version='0.0',
66+
ext_modules=[ext])
4867

4968

5069
if __name__ == "__main__":

0 commit comments

Comments
 (0)