Skip to content

gh-116869: Test the limited C API in test_cext #116995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions Lib/test/test_cext/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,35 @@
@support.requires_resource('cpu')
class TestExt(unittest.TestCase):
def test_build_c99(self):
self.check_build('c99', '_test_c99_ext')
self.check_build('_test_c99_ext', std='c99')

def test_build_c11(self):
self.check_build('c11', '_test_c11_ext')
self.check_build('_test_c11_ext', std='c11')

def check_build(self, clang_std, extension_name):
def test_build_limited(self):
self.check_build('_test_limited_ext', limited=True)

def test_build_limited_c11(self):
self.check_build('_test_limited_c11_ext', limited=True, std='c11')

def check_build(self, extension_name, std=None, limited=False):
venv_dir = 'env'
with support.setup_venv_with_pip_setuptools_wheel(venv_dir) as python_exe:
self._check_build(clang_std, extension_name, python_exe)
self._check_build(extension_name, python_exe,
std=std, limited=limited)

def _check_build(self, clang_std, extension_name, python_exe):
def _check_build(self, extension_name, python_exe, std, limited):
pkg_dir = 'pkg'
os.mkdir(pkg_dir)
shutil.copy(SETUP, os.path.join(pkg_dir, os.path.basename(SETUP)))
shutil.copy(SOURCE, os.path.join(pkg_dir, os.path.basename(SOURCE)))

def run_cmd(operation, cmd):
env = os.environ.copy()
env['CPYTHON_TEST_STD'] = clang_std
if std:
env['CPYTHON_TEST_STD'] = std
if limited:
env['CPYTHON_TEST_LIMITED'] = '1'
env['CPYTHON_TEST_EXT_NAME'] = extension_name
if support.verbose:
print('Run:', ' '.join(cmd))
Expand Down
16 changes: 6 additions & 10 deletions Lib/test/test_cext/extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,8 @@

#include "Python.h"

#if defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L
# define NAME _test_c2x_ext
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
# define NAME _test_c11_ext
#else
# define NAME _test_c99_ext
#ifndef MODULE_NAME
# error "MODULE_NAME macro must be defined"
#endif

#define _STR(NAME) #NAME
Expand All @@ -25,11 +21,11 @@ PyDoc_STRVAR(_testcext_add_doc,
static PyObject *
_testcext_add(PyObject *Py_UNUSED(module), PyObject *args)
{
long i, j;
long i, j, res;
if (!PyArg_ParseTuple(args, "ll:foo", &i, &j)) {
return NULL;
}
long res = i + j;
res = i + j;
return PyLong_FromLong(res);
}

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

static struct PyModuleDef _testcext_module = {
PyModuleDef_HEAD_INIT, // m_base
STR(NAME), // m_name
STR(MODULE_NAME), // m_name
_testcext_doc, // m_doc
0, // m_size
_testcext_methods, // m_methods
Expand All @@ -74,7 +70,7 @@ static struct PyModuleDef _testcext_module = {
#define FUNC_NAME(NAME) _FUNC_NAME(NAME)

PyMODINIT_FUNC
FUNC_NAME(NAME)(void)
FUNC_NAME(MODULE_NAME)(void)
{
return PyModuleDef_Init(&_testcext_module);
}
47 changes: 33 additions & 14 deletions Lib/test/test_cext/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,43 @@


def main():
std = os.environ["CPYTHON_TEST_STD"]
name = os.environ["CPYTHON_TEST_EXT_NAME"]
cflags = [*CFLAGS, f'-std={std}']

# Remove existing -std options to only test ours
cmd = (sysconfig.get_config_var('CC') or '')
if cmd is not None:
cmd = shlex.split(cmd)
cmd = [arg for arg in cmd if not arg.startswith('-std=')]
cmd = shlex.join(cmd)
# CC env var overrides sysconfig CC variable in setuptools
os.environ['CC'] = cmd
std = os.environ.get("CPYTHON_TEST_STD", "")
module_name = os.environ["CPYTHON_TEST_EXT_NAME"]
limited = bool(os.environ.get("CPYTHON_TEST_LIMITED", ""))

cflags = list(CFLAGS)
cflags.append(f'-DMODULE_NAME={module_name}')

if std:
cflags.append(f'-std={std}')

# Remove existing -std options to only test ours
cmd = (sysconfig.get_config_var('CC') or '')
if cmd is not None:
cmd = shlex.split(cmd)
cmd = [arg for arg in cmd if not arg.startswith('-std=')]
cmd = shlex.join(cmd)
# CC env var overrides sysconfig CC variable in setuptools
os.environ['CC'] = cmd

if limited:
version = sys.hexversion
cflags.append(f'-DPy_LIMITED_API={version:#x}')

for env_name in ('CC', 'CFLAGS'):
if env_name in os.environ:
print(f"{env_name} env var: {os.environ[env_name]!r}")
else:
print(f"{env_name} env var: <missing>")
print(f"extra_compile_args: {cflags!r}")

ext = Extension(
name,
module_name,
sources=[SOURCE],
extra_compile_args=cflags)
setup(name='internal' + name, version='0.0', ext_modules=[ext])
setup(name=f'internal_{module_name}',
version='0.0',
ext_modules=[ext])


if __name__ == "__main__":
Expand Down