Skip to content

Commit 308b348

Browse files
authored
Merge pull request numpy#24153 from mattip/cpp-random
BLD, TST: refactor test to use meson not setup.py, improve spin test -m ...
2 parents a6a9a9a + 43c32e6 commit 308b348

File tree

15 files changed

+148
-160
lines changed

15 files changed

+148
-160
lines changed

.github/workflows/build_test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ jobs:
9696
# for add-apt-repository
9797
sudo apt install software-properties-common -y
9898
sudo add-apt-repository ppa:deadsnakes/ppa -y
99-
sudo apt install python3.9-dev -y
99+
sudo apt install python3.9-dev ninja-build -y
100100
sudo ln -s /usr/bin/python3.9 /usr/bin/pythonx
101101
pythonx -m pip install --upgrade pip setuptools wheel
102102
pythonx -m pip install -r test_requirements.txt

.github/workflows/emscripten.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ jobs:
7171
pyodide venv .venv-pyodide
7272
source .venv-pyodide/bin/activate
7373
pip install dist/*.whl
74+
python -c "import sys; print(sys.platform)"
7475
pip install -r test_requirements.txt
7576
- name: Test
7677
run: |

.github/workflows/wheels.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ jobs:
192192
# TODO: Don't run test suite, and instead build wheels from sdist
193193
# Depends on pypa/cibuildwheel#1020
194194
python -m pip install dist/*.gz
195+
pip install ninja
195196
pip install -r test_requirements.txt
196197
cd .. # Can't import numpy within numpy src directory
197198
python -c "import numpy, sys; print(numpy.__version__); sys.exit(numpy.test() is False)"

.spin/cmds.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,17 @@ def test(ctx, pytest_args, markexpr, n_jobs, tests, verbose):
120120
spin test -- -k "geometric"
121121
spin test -- -k "geometric and not rgeometric"
122122
123+
By default, spin will run `-m 'not slow'`. To run the full test suite, use
124+
`spin -m full`
125+
123126
For more, see `pytest --help`.
124127
""" # noqa: E501
125128
if (not pytest_args) and (not tests):
126129
pytest_args = ('numpy',)
127130

128131
if '-m' not in pytest_args:
129-
pytest_args = ('-m', markexpr) + pytest_args
132+
if markexpr != "full":
133+
pytest_args = ('-m', markexpr) + pytest_args
130134

131135
if (n_jobs != "1") and ('-n' not in pytest_args):
132136
pytest_args = ('-n', str(n_jobs)) + pytest_args

azure-pipelines.yml

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -32,42 +32,6 @@ stages:
3232
- bash: echo "##vso[task.setvariable variable=start_main;isOutput=true]$RET"
3333
name: result
3434

35-
- stage: InitialTests
36-
condition: and(succeeded(), eq(dependencies.Check.outputs['Skip.result.start_main'], 'true'))
37-
dependsOn: Check
38-
jobs:
39-
40-
# Native build is based on gcc flag `-march=native`
41-
- job: Linux_baseline_native
42-
pool:
43-
vmImage: 'ubuntu-20.04'
44-
steps:
45-
- script: |
46-
git submodule update --init
47-
displayName: 'Fetch submodules'
48-
- script: |
49-
if ! `gcc 2>/dev/null`; then
50-
sudo apt install gcc
51-
fi
52-
sudo add-apt-repository ppa:deadsnakes/ppa -y
53-
sudo apt install python3.9
54-
sudo apt install python3.9-dev
55-
sudo apt install python3.9-distutils
56-
# python3 has no setuptools, so install one to get us going
57-
python3.9 -m pip install --user --upgrade pip 'setuptools<49.2.0'
58-
python3.9 -m pip install --user -r test_requirements.txt
59-
displayName: 'install python/requirements'
60-
- script: |
61-
python3.9 runtests.py --show-build-log --cpu-baseline=native --cpu-dispatch=none \
62-
--debug-info --mode=full -- -rsx --junitxml=junit/test-results.xml
63-
displayName: 'Run native baseline Build / Tests'
64-
- task: PublishTestResults@2
65-
condition: succeededOrFailed()
66-
inputs:
67-
testResultsFiles: '**/test-*.xml'
68-
failTaskOnFailedTests: true
69-
testRunTitle: 'Publish test results for baseline/native'
70-
7135
- stage: ComprehensiveTests
7236
condition: and(succeeded(), eq(dependencies.Check.outputs['Skip.result.start_main'], 'true'))
7337
dependsOn: Check
@@ -101,6 +65,7 @@ stages:
10165
git submodule update --init
10266
displayName: 'Fetch submodules'
10367
- script: |
68+
# yum does not have a ninja package, so use the PyPI one
10469
docker run -v $(pwd):/numpy -e CFLAGS="-msse2 -std=c99 -UNDEBUG" \
10570
-e F77=gfortran-5 -e F90=gfortran-5 quay.io/pypa/manylinux2014_i686 \
10671
/bin/bash -xc " \
@@ -111,6 +76,7 @@ stages:
11176
target=\$(python3 tools/openblas_support.py) && \
11277
cp -r \$target/lib/* /usr/lib && \
11378
cp \$target/include/* /usr/include && \
79+
python3 -m pip install ninja && \
11480
python3 -m pip install -r test_requirements.txt && \
11581
echo CFLAGS \$CFLAGS && \
11682
python3 -m pip install -v . && \
@@ -175,7 +141,7 @@ stages:
175141
- script: |
176142
python -m pip install -r test_requirements.txt
177143
# Don't use doc_requirements.txt since that messes up tests
178-
python -m pip install vulture sphinx==4.3.0 numpydoc==1.4.0
144+
python -m pip install vulture sphinx==4.3.0 numpydoc==1.4.0 ninja
179145
displayName: 'Install dependencies; some are optional to avoid test skips'
180146
- script: /bin/bash -c "! vulture . --min-confidence 100 --exclude doc/,numpy/distutils/ | grep 'unreachable'"
181147
displayName: 'Check for unreachable code paths in Python modules'

azure-steps-windows.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ steps:
1919
choco install --confirm --no-progress --allow-downgrade rtools --version=4.3.5550
2020
choco install unzip -y
2121
choco install -y --checksum 6004DF17818F5A6DBF19CB335CC92702 pkgconfiglite
22+
choco install ninja
2223
echo "##vso[task.setvariable variable=RTOOLS43_HOME]c:\rtools43"
2324
displayName: 'Install utilities'
2425

numpy/core/tests/test_array_interface.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import sys
22
import pytest
33
import numpy as np
4-
from numpy.testing import extbuild
4+
from numpy.testing import extbuild, IS_WASM
55

66

77
@pytest.fixture
@@ -12,6 +12,8 @@ def get_module(tmp_path):
1212

1313
if not sys.platform.startswith('linux'):
1414
pytest.skip('link fails on cygwin')
15+
if IS_WASM:
16+
pytest.skip("Can't build module inside Wasm")
1517

1618
prologue = '''
1719
#include <Python.h>
@@ -128,9 +130,6 @@ def get_module(tmp_path):
128130
more_init=more_init)
129131

130132

131-
# FIXME: numpy.testing.extbuild uses `numpy.distutils`, so this won't work on
132-
# Python 3.12 and up.
133-
@pytest.mark.skipif(sys.version_info >= (3, 12), reason="no numpy.distutils")
134133
@pytest.mark.slow
135134
def test_cstruct(get_module):
136135

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
project('random-build-examples', 'c', 'cpp', 'cython')
2+
3+
py_mod = import('python')
4+
py3 = py_mod.find_installation(pure: false)
5+
6+
cc = meson.get_compiler('c')
7+
cy = meson.get_compiler('cython')
8+
9+
if not cy.version().version_compare('>=0.29.35')
10+
error('tests requires Cython >= 0.29.35')
11+
endif
12+
13+
_numpy_abs = run_command(py3, ['-c',
14+
'import os; os.chdir(".."); import numpy; print(os.path.abspath(numpy.get_include() + "../../.."))'],
15+
check: true).stdout().strip()
16+
17+
npymath_path = _numpy_abs / 'core' / 'lib'
18+
npy_include_path = _numpy_abs / 'core' / 'include'
19+
npyrandom_path = _numpy_abs / 'random' / 'lib'
20+
npymath_lib = cc.find_library('npymath', dirs: npymath_path)
21+
npyrandom_lib = cc.find_library('npyrandom', dirs: npyrandom_path)
22+
23+
py3.extension_module(
24+
'extending_distributions',
25+
'extending_distributions.pyx',
26+
install: false,
27+
include_directories: [npy_include_path],
28+
dependencies: [npyrandom_lib, npymath_lib],
29+
)
30+
py3.extension_module(
31+
'extending',
32+
'extending.pyx',
33+
install: false,
34+
include_directories: [npy_include_path],
35+
dependencies: [npyrandom_lib, npymath_lib],
36+
)
37+
py3.extension_module(
38+
'extending_cpp',
39+
'extending_distributions.pyx',
40+
install: false,
41+
override_options : ['cython_language=cpp'],
42+
cython_args: ['--module-name', 'extending_cpp'],
43+
include_directories: [npy_include_path],
44+
dependencies: [npyrandom_lib, npymath_lib],
45+
)

numpy/random/_examples/cython/setup.py

Lines changed: 0 additions & 46 deletions
This file was deleted.

numpy/random/meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ py.install_sources(
152152
[
153153
'_examples/cython/extending.pyx',
154154
'_examples/cython/extending_distributions.pyx',
155-
'_examples/cython/setup.py',
155+
'_examples/cython/meson.build',
156156
],
157157
subdir: 'numpy/random/_examples/cython'
158158
)

numpy/random/tests/test_extending.py

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
from importlib.util import spec_from_file_location, module_from_spec
12
import os
3+
import pathlib
24
import pytest
35
import shutil
46
import subprocess
57
import sys
8+
import sysconfig
9+
import textwrap
610
import warnings
711

812
import numpy as np
@@ -39,55 +43,62 @@
3943
# other fixes in the 0.29 series that are needed even for earlier
4044
# Python versions.
4145
# Note: keep in sync with the one in pyproject.toml
42-
required_version = '0.29.30'
46+
required_version = '0.29.35'
4347
if _pep440.parse(cython_version) < _pep440.Version(required_version):
4448
# too old or wrong cython, skip the test
4549
cython = None
4650

4751

48-
@pytest.mark.skipif(sys.version_info >= (3, 12),
49-
reason="numpy.distutils not supported anymore")
5052
@pytest.mark.skipif(IS_WASM, reason="Can't start subprocess")
5153
@pytest.mark.skipif(cython is None, reason="requires cython")
5254
@pytest.mark.slow
5355
def test_cython(tmp_path):
54-
from numpy.distutils.misc_util import exec_mod_from_location
56+
import glob
57+
# build the examples in a temporary directory
5558
srcdir = os.path.join(os.path.dirname(__file__), '..')
5659
shutil.copytree(srcdir, tmp_path / 'random')
57-
# build the examples and "install" them into a temporary directory
5860
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-
)
61+
target_dir = build_dir / "build"
62+
os.makedirs(target_dir, exist_ok=True)
63+
if sys.platform == "win32":
64+
subprocess.check_call(["meson", "setup",
65+
"--buildtype=release",
66+
"--vsenv", str(build_dir)],
67+
cwd=target_dir,
68+
)
69+
else:
70+
subprocess.check_call(["meson", "setup", str(build_dir)],
71+
cwd=target_dir
72+
)
73+
subprocess.check_call(["meson", "compile", "-vv"], cwd=target_dir)
74+
6675
# gh-16162: make sure numpy's __init__.pxd was used for cython
6776
# not really part of this test, but it is a convenient place to check
68-
with open(build_dir / 'extending.c') as fid:
77+
78+
g = glob.glob(str(target_dir / "*" / "extending.pyx.c"))
79+
with open(g[0]) as fid:
6980
txt_to_find = 'NumPy API declarations from "numpy/__init__'
7081
for i, line in enumerate(fid):
7182
if txt_to_find in line:
7283
break
7384
else:
7485
assert False, ("Could not find '{}' in C file, "
7586
"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)
87+
# import without adding the directory to sys.path
88+
suffix = sysconfig.get_config_var('EXT_SUFFIX')
89+
90+
def load(modname):
91+
so = (target_dir / modname).with_suffix(suffix)
92+
spec = spec_from_file_location(modname, so)
93+
mod = module_from_spec(spec)
94+
spec.loader.exec_module(mod)
95+
return mod
96+
97+
# test that the module can be imported
98+
load("extending")
99+
load("extending_cpp")
90100
# actually test the cython c-extension
101+
extending_distributions = load("extending_distributions")
91102
from numpy.random import PCG64
92103
values = extending_distributions.uniforms_ex(PCG64(0), 10, 'd')
93104
assert values.shape == (10,)

0 commit comments

Comments
 (0)