|
from importlib.util import spec_from_file_location, module_from_spec |
|
import os |
|
import pytest |
|
import shutil |
|
import subprocess |
|
import sys |
|
import sysconfig |
|
import warnings |
|
|
|
import numpy as np |
|
from numpy.testing import IS_WASM, IS_EDITABLE |
|
|
|
|
|
try: |
|
import cffi |
|
except ImportError: |
|
cffi = None |
|
|
|
if sys.flags.optimize > 1: |
|
|
|
|
|
cffi = None |
|
|
|
try: |
|
with warnings.catch_warnings(record=True) as w: |
|
|
|
warnings.filterwarnings('always', '', DeprecationWarning) |
|
import numba |
|
except (ImportError, SystemError): |
|
|
|
numba = None |
|
|
|
try: |
|
import cython |
|
from Cython.Compiler.Version import version as cython_version |
|
except ImportError: |
|
cython = None |
|
else: |
|
from numpy._utils import _pep440 |
|
|
|
required_version = '3.0.6' |
|
if _pep440.parse(cython_version) < _pep440.Version(required_version): |
|
|
|
cython = None |
|
|
|
|
|
@pytest.mark.skipif( |
|
IS_EDITABLE, |
|
reason='Editable install cannot find .pxd headers' |
|
) |
|
@pytest.mark.skipif( |
|
sys.platform == "win32" and sys.maxsize < 2**32, |
|
reason="Failing in 32-bit Windows wheel build job, skip for now" |
|
) |
|
@pytest.mark.skipif(IS_WASM, reason="Can't start subprocess") |
|
@pytest.mark.skipif(cython is None, reason="requires cython") |
|
@pytest.mark.slow |
|
def test_cython(tmp_path): |
|
import glob |
|
|
|
srcdir = os.path.join(os.path.dirname(__file__), '..') |
|
shutil.copytree(srcdir, tmp_path / 'random') |
|
build_dir = tmp_path / 'random' / '_examples' / 'cython' |
|
target_dir = build_dir / "build" |
|
os.makedirs(target_dir, exist_ok=True) |
|
|
|
|
|
native_file = str(build_dir / 'interpreter-native-file.ini') |
|
with open(native_file, 'w') as f: |
|
f.write("[binaries]\n") |
|
f.write(f"python = '{sys.executable}'\n") |
|
f.write(f"python3 = '{sys.executable}'") |
|
if sys.platform == "win32": |
|
subprocess.check_call(["meson", "setup", |
|
"--buildtype=release", |
|
"--vsenv", "--native-file", native_file, |
|
str(build_dir)], |
|
cwd=target_dir, |
|
) |
|
else: |
|
subprocess.check_call(["meson", "setup", |
|
"--native-file", native_file, str(build_dir)], |
|
cwd=target_dir |
|
) |
|
subprocess.check_call(["meson", "compile", "-vv"], cwd=target_dir) |
|
|
|
|
|
|
|
|
|
g = glob.glob(str(target_dir / "*" / "extending.pyx.c")) |
|
with open(g[0]) as fid: |
|
txt_to_find = 'NumPy API declarations from "numpy/__init__' |
|
for line in fid: |
|
if txt_to_find in line: |
|
break |
|
else: |
|
assert False, ("Could not find '{}' in C file, " |
|
"wrong pxd used".format(txt_to_find)) |
|
|
|
suffix = sysconfig.get_config_var('EXT_SUFFIX') |
|
|
|
def load(modname): |
|
so = (target_dir / modname).with_suffix(suffix) |
|
spec = spec_from_file_location(modname, so) |
|
mod = module_from_spec(spec) |
|
spec.loader.exec_module(mod) |
|
return mod |
|
|
|
|
|
load("extending") |
|
load("extending_cpp") |
|
|
|
extending_distributions = load("extending_distributions") |
|
from numpy.random import PCG64 |
|
values = extending_distributions.uniforms_ex(PCG64(0), 10, 'd') |
|
assert values.shape == (10,) |
|
assert values.dtype == np.float64 |
|
|
|
@pytest.mark.skipif(numba is None or cffi is None, |
|
reason="requires numba and cffi") |
|
def test_numba(): |
|
from numpy.random._examples.numba import extending |
|
|
|
@pytest.mark.skipif(cffi is None, reason="requires cffi") |
|
def test_cffi(): |
|
from numpy.random._examples.cffi import extending |
|
|