Skip to content

Commit 2e00441

Browse files
committed
refactor test_extending to use meson
1 parent dac0135 commit 2e00441

File tree

1 file changed

+69
-27
lines changed

1 file changed

+69
-27
lines changed

numpy/random/tests/test_extending.py

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import importlib
12
import os
3+
import pathlib
24
import pytest
35
import shutil
46
import subprocess
57
import sys
8+
import textwrap
69
import warnings
710

811
import numpy as np
@@ -39,54 +42,93 @@
3942
# other fixes in the 0.29 series that are needed even for earlier
4043
# Python versions.
4144
# Note: keep in sync with the one in pyproject.toml
42-
required_version = '0.29.30'
45+
required_version = '0.29.35'
4346
if _pep440.parse(cython_version) < _pep440.Version(required_version):
4447
# too old or wrong cython, skip the test
4548
cython = None
4649

4750

48-
@pytest.mark.skipif(sys.version_info >= (3, 12),
49-
reason="numpy.distutils not supported anymore")
5051
@pytest.mark.skipif(IS_WASM, reason="Can't start subprocess")
5152
@pytest.mark.skipif(cython is None, reason="requires cython")
5253
@pytest.mark.slow
5354
def test_cython(tmp_path):
54-
from numpy.distutils.misc_util import exec_mod_from_location
55+
import glob
56+
# build the examples in a temporary directory
5557
srcdir = os.path.join(os.path.dirname(__file__), '..')
5658
shutil.copytree(srcdir, tmp_path / 'random')
57-
# build the examples and "install" them into a temporary directory
5859
build_dir = tmp_path / 'random' / '_examples' / 'cython'
59-
subprocess.check_call([sys.executable, 'setup.py', 'build', 'install',
60-
'--prefix', str(tmp_path / 'installdir'),
61-
'--single-version-externally-managed',
62-
'--record', str(tmp_path/ 'tmp_install_log.txt'),
63-
],
64-
cwd=str(build_dir),
65-
)
60+
# We don't want a wheel build, so do the steps in a controlled way
61+
# The meson.build file is not copied as part of the build, so generate it
62+
with open(build_dir / "meson.build", "wt", encoding="utf-8") as fid:
63+
fid.write(textwrap.dedent("""\
64+
project('random-build-examples', 'c', 'cpp', 'cython')
65+
66+
# https://mesonbuild.com/Python-module.html
67+
py_mod = import('python')
68+
py3 = py_mod.find_installation(pure: false)
69+
py3_dep = py3.dependency()
70+
71+
py_mod = import('python')
72+
py = py_mod.find_installation(pure: false)
73+
cc = meson.get_compiler('c')
74+
cy = meson.get_compiler('cython')
75+
76+
if not cy.version().version_compare('>=0.29.35')
77+
error('tests requires Cython >= 0.29.35')
78+
endif
79+
80+
_numpy_abs = run_command(py3,
81+
['-c', 'import os; os.chdir(".."); import numpy; print(os.path.abspath(numpy.get_include() + "../../.."))'],
82+
check: true
83+
).stdout().strip()
84+
85+
npymath_path = _numpy_abs / 'core' / 'lib'
86+
npy_include_path = _numpy_abs / 'core' / 'include'
87+
npyrandom_path = _numpy_abs / 'random' / 'lib'
88+
npymath_lib = cc.find_library('npymath', dirs: npymath_path)
89+
npyrandom_lib = cc.find_library('npyrandom', dirs: npyrandom_path)
90+
91+
py.extension_module(
92+
'extending_distributions',
93+
'extending_distributions.pyx',
94+
install: false,
95+
include_directories: [npy_include_path],
96+
dependencies: [npyrandom_lib, npymath_lib],
97+
)
98+
py.extension_module(
99+
'extending',
100+
'extending.pyx',
101+
install: false,
102+
include_directories: [npy_include_path],
103+
dependencies: [npyrandom_lib, npymath_lib],
104+
)
105+
"""))
106+
target_dir = build_dir / "build"
107+
os.makedirs(target_dir, exist_ok=True)
108+
subprocess.check_call(["meson", "setup", str(build_dir)], cwd=target_dir)
109+
subprocess.check_call(["meson", "compile"], cwd=target_dir)
110+
66111
# gh-16162: make sure numpy's __init__.pxd was used for cython
67112
# not really part of this test, but it is a convenient place to check
68-
with open(build_dir / 'extending.c') as fid:
113+
114+
g = glob.glob(str(target_dir / "*" / "extending.pyx.c"))
115+
with open(g[0]) as fid:
69116
txt_to_find = 'NumPy API declarations from "numpy/__init__'
70117
for i, line in enumerate(fid):
71118
if txt_to_find in line:
72119
break
73120
else:
74121
assert False, ("Could not find '{}' in C file, "
75122
"wrong pxd used".format(txt_to_find))
76-
# get the path to the so's
77-
so1 = so2 = None
78-
with open(tmp_path /'tmp_install_log.txt') as fid:
79-
for line in fid:
80-
if 'extending.' in line:
81-
so1 = line.strip()
82-
if 'extending_distributions' in line:
83-
so2 = line.strip()
84-
assert so1 is not None
85-
assert so2 is not None
86-
# import the so's without adding the directory to sys.path
87-
exec_mod_from_location('extending', so1)
88-
extending_distributions = exec_mod_from_location(
89-
'extending_distributions', so2)
123+
# import without adding the directory to sys.path
124+
so1 = sorted(glob.glob(str(target_dir / "extending.*")))[0]
125+
so2 = sorted(glob.glob(str(target_dir / "extending_distributions.*")))[0]
126+
spec1 = importlib.util.spec_from_file_location("extending", so1)
127+
spec2 = importlib.util.spec_from_file_location("extending_distributions", so2)
128+
extending = importlib.util.module_from_spec(spec1)
129+
spec1.loader.exec_module(extending)
130+
extending_distributions = importlib.util.module_from_spec(spec2)
131+
spec2.loader.exec_module(extending_distributions)
90132
# actually test the cython c-extension
91133
from numpy.random import PCG64
92134
values = extending_distributions.uniforms_ex(PCG64(0), 10, 'd')

0 commit comments

Comments
 (0)