diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 581c9268..8f719202 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,19 +11,9 @@ jobs:
strategy:
# Duplicate changes to this matrix to 'poc_tests'
matrix:
- os: [ubuntu-latest, macos-11, windows-latest]
- python-version: ['3.9', '3.10']
+ os: [macos-11, macos-12, macos-13, macos-14]
+ python-version: ['3.10']
compiler: [""]
- include:
- - os: ubuntu-latest
- python-version: '3.8'
- - os: ubuntu-latest
- python-version: '3.10'
- compiler: 'g++'
- - os: ubuntu-latest
- python-version: '3.11'
- - os: ubuntu-latest
- python-version: '3.12'
steps:
- uses: actions/checkout@v4
@@ -57,370 +47,3 @@ jobs:
run: |
python -m pip install pytest pytest-xdist filelock
python -m pytest --basetemp=.tmpdir --durations=16 -n auto test/
-
- main_tests_debug:
- name: Main tests on CPython debug builds
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest]
- python-version: ['3.12', '3.11', '3.10', '3.9', '3.8']
-
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up Python from deadsnakes
- uses: deadsnakes/action@v2.1.1 # Upgrading will cause test failures.
- with:
- python-version: ${{ matrix.python-version }}
- debug: true
-
- - name: Check Python debug build
- run: python -c "import sys; print(hasattr(sys, 'gettotalrefcount'))"
-
- - name: Install/Upgrade Python dependencies
- run: python -m pip install --upgrade pip wheel
-
- - name: Build
- run: |
- make
- python -m pip install .
-
- - name: Run tests
- run: |
- python -m pip install pytest pytest-xdist filelock
- python -m pytest --durations=16 -n auto test/
-
- poc_tests:
- name: Proof of concept tests
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest, macos-11, windows-latest]
- python-version: ['3.10']
- include:
- - os: ubuntu-latest
- python-version: '3.8'
- - os: ubuntu-latest
- python-version: '3.9'
- - os: ubuntu-latest
- python-version: '3.11'
- - os: ubuntu-latest
- python-version: '3.12'
-
- steps:
- - uses: actions/checkout@v4
-
- # - template: azure-templates/ccache.yml
- # parameters:
- # pythonVersion: $(python.version)
- # - template: azure-templates/python.yml
- # parameters:
- # pythonVersion: $(python.version)
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
- allow-prereleases: true
-
- - name: Install/Upgrade Python dependencies
- run: python -m pip install --upgrade pip wheel
- shell: bash
-
- - name: 'Test setup.py --hpy-abi=cpython bdist_wheel'
- run: proof-of-concept/test_pof.sh wheel cpython
- shell: bash
-
- - name: 'Test setup.py --hpy-abi=universal bdist_wheel'
- run: proof-of-concept/test_pof.sh wheel universal
- shell: bash
-
- - name: 'Test setup.py --hpy-abi=cpython install'
- run: proof-of-concept/test_pof.sh setup_py_install cpython
- shell: bash
-
- - name: 'Test setup.py --hpy-abi=universal install'
- run: proof-of-concept/test_pof.sh setup_py_install universal
- shell: bash
-
- - name: 'Test setup.py --hpy-abi=cpython build_ext --inplace'
- run: proof-of-concept/test_pof.sh setup_py_build_ext_inplace cpython
- shell: bash
-
- - name: 'Test setup.py --hpy-abi=universal build_ext --inplace'
- run: proof-of-concept/test_pof.sh setup_py_build_ext_inplace universal
- shell: bash
-
-
- porting_example_tests:
- name: Porting example tests
- runs-on: ${{ matrix.os }}
- continue-on-error: true
- strategy:
- matrix:
- os: [ubuntu-latest, macos-11, windows-latest]
- python-version: ['3.9']
-
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
-
- - name: Install/Upgrade Python dependencies
- run: python -m pip install --upgrade pip wheel
- shell: bash
-
- - name: Install HPy
- run: python -m pip install .
-
- - name: Install pytest
- run: |
- python -m pip install pytest
-
- - name: Run tests
- run: make porting-example-tests
- shell: bash
-
- - name: Run tests of completed port in debug mode
- env:
- HPY_DEBUG: "1"
- TEST_ARGS: "-s -k hpy_final"
- run: make porting-example-tests
- shell: bash
-
-
- valgrind_tests_1:
- name: 'Valgrind tests (1/3)'
- uses: ./.github/workflows/valgrind-tests.yml
- with:
- portion: '1/3'
-
-
- valgrind_tests_2:
- name: 'Valgrind tests (2/3)'
- uses: ./.github/workflows/valgrind-tests.yml
- with:
- portion: '2/3'
-
-
- valgrind_tests_3:
- name: 'Valgrind tests (3/3)'
- uses: ./.github/workflows/valgrind-tests.yml
- with:
- portion: '3/3'
-
-
- docs_examples_tests:
- name: Documentation examples tests
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest, macos-11, windows-latest]
- python-version: ['3.10']
-
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
-
- - name: Install/Upgrade Python dependencies
- run: python -m pip install --upgrade pip wheel
- shell: bash
-
- - name: Install HPy
- run: python -m pip install .
-
- - name: Install pytest
- run: |
- python -m pip install pytest pytest-xdist filelock
- - name: Run tests
- run: make docs-examples-tests
- shell: bash
-
- build_docs:
- name: Build documentation
- runs-on: 'ubuntu-latest'
- steps:
- - uses: actions/checkout@v4
-
- # - template: azure-templates/python.yml
-
- - name: Install / Upgrade system requirements
- run: sudo apt update && sudo apt install -y libclang-11-dev
-
- - name: Install / Upgrade Python requirements
- run: |
- python -m pip install --upgrade pip
- python -m pip install -r docs/requirements.txt
-
- - name: Build docs
- run: |
- cd docs;
- python -m sphinx -T -W -E -b html -d _build/doctrees -D language=en . _build/html
-
- - name: Upload built HTML files
- uses: actions/upload-artifact@v4
- with:
- name: hpy_html_docs
- path: docs/_build/html/*
- if-no-files-found: error
- retention-days: 5
-
- c_tests:
- name: C tests
- runs-on: 'ubuntu-latest'
- steps:
- - uses: actions/checkout@v4
- - run: make -C c_test
-
-
- check_autogen:
- name: Check autogen
- runs-on: 'ubuntu-latest'
- steps:
- - uses: actions/checkout@v4
-
- # - template: azure-templates/python.yml
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- # autogen needs distutils
- python-version: '3.11'
-
- - name: Install/Upgrade Python dependencies
- run: python -m pip install --upgrade pip wheel
-
- - name: Install autogen dependencies
- run: pip install -r requirements-autogen.txt
-
- - name: make autogen
- run: |
- make autogen
- if [ -z "$(git status --porcelain)" ]; then
- # clean working copy
- echo "Working copy is clean, everything ok"
- else
- # Uncommitted changes
- echo "ERROR: uncommitted changes after running make autogen"
- echo "git status"
- git status
- echo
- echo "git diff"
- git diff
- exit 1
- fi
-
-
- check_py27_compat:
- name: Check Python 2.7 compatibility
- runs-on: 'ubuntu-20.04'
- steps:
- - uses: actions/checkout@v4
-
- # - template: azure-templates/python.yml
- # parameters:
- # pythonVersion: "2.7"
-
- - name: Set up Python2
- # Copied from cython's ci.yml
- run: |
- sudo ln -fs python2 /usr/bin/python
- sudo apt-get update
- sudo apt-get install python-setuptools python2.7 python2.7-dev
- curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
- sudo python2 get-pip.py
- ls -l /usr/bin/pip* /usr/local/bin/pip*
- which pip
-
- - name: Install/Upgrade Python dependencies
- run: python -m pip install --upgrade pip wheel
-
- - name: check_py27_compat.py
- run: |
- python -m pip install pytest pytest-xdist filelock pathlib
- python test/check_py27_compat.py
-
-
- cpp_check:
- name: Cppcheck static analysis
- runs-on: 'ubuntu-22.04'
- continue-on-error: true
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: '3.10'
-
- - name: Install Cppcheck
- run: sudo apt-get -qq -y install cppcheck=2.7-1
-
- - name: Run Cppcheck
- run: make cppcheck
-
-
- infer:
- name: Infer static analysis
- runs-on: 'ubuntu-latest'
- steps:
- - uses: actions/checkout@v4
-
- # - template: azure-templates/python.yml
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: '3.10'
-
- - name: Install/Upgrade Python dependencies
- run: python -m pip install --upgrade pip wheel
-
- - name: Install Infer
- run: |
- python -m pip install compiledb wheel;
- VERSION=1.1.0; \
- curl -sSL "https://github.com/facebook/infer/releases/download/v$VERSION/infer-linux64-v$VERSION.tar.xz" \
- | sudo tar -C /opt -xJ && \
- echo "/opt/infer-linux64-v$VERSION/bin" >> $GITHUB_PATH
-
- - name: Run Infer
- run: make infer
-
- check_microbench:
- name: Check micro benchmarks
- runs-on: 'ubuntu-latest'
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: '3.x'
-
- - name: Install / Upgrade system dependencies
- run: sudo apt update && sudo apt install -y valgrind
-
- - name: Install / Upgrade Python requirements
- run: |
- python -m pip install --upgrade pip wheel 'setuptools>=60.2'
- python -m pip install pytest cffi
-
- - name: Build and install HPy
- run: |
- make
- python -m pip install .
-
- - name: Run microbenchmarks
- run: |
- cd microbench
- python setup.py build_ext -i
- python -m pytest -v
diff --git a/.github/workflows/valgrind-tests.yml b/.github/workflows/valgrind-tests.yml.DISABLED
similarity index 100%
rename from .github/workflows/valgrind-tests.yml
rename to .github/workflows/valgrind-tests.yml.DISABLED
diff --git a/test/hpy_devel/test_build.py b/test/hpy_devel/test_build.py
new file mode 100644
index 00000000..7c9b47f9
--- /dev/null
+++ b/test/hpy_devel/test_build.py
@@ -0,0 +1,386 @@
+"""
+Test the hpy+build integration. Most of the relevant code is in
+hpy/devel/__init__.py.
+
+Note that this is a different kind of test than the majority of the other
+files in this directory, which all inherit from HPyTest and test the API
+itself.
+"""
+
+import sys
+import os
+import textwrap
+import subprocess
+import shutil
+import venv
+import py
+import pytest
+
+from ..support import atomic_run, HPY_ROOT
+
+# ====== IMPORTANT DEVELOPMENT TIP =====
+# You can use pytest --reuse-venv to speed up local testing.
+#
+# The env is created once in /tmp/venv-for-hpytest and reused among tests and
+# sessions. If you want to recreate it, simply rm -r /tmp/venv-for-hpytest
+
+def print_CalledProcessError(p):
+ """
+ Print all information about a CalledProcessError
+ """
+ print('========== subprocess failed ==========')
+ print('command:', ' '.join(p.cmd))
+ print('argv: ', p.cmd)
+ print('return code:', p.returncode)
+ print()
+ print('---------- ----------')
+ print(p.stdout.decode('latin-1'))
+ print('---------- ---------')
+ print()
+ print('---------- ----------')
+ print(p.stderr.decode('latin-1'))
+ print('---------- ---------')
+
+@pytest.fixture(scope='session')
+def venv_template(request, tmpdir_factory):
+ if request.config.option.reuse_venv:
+ d = py.path.local('/tmp/venv-for-hpytest')
+ if d.check(dir=True):
+ # if it exists, we assume it's correct. If you want to recreate,
+ # just manually delete /tmp/venv-for-hpytest
+ return d
+ else:
+ d = tmpdir_factory.mktemp('venv')
+
+ venv.create(d, with_pip=True)
+
+ # remove the scripts: they contains a shebang and it will fail subtly
+ # after we clone the template. Yes, we could try to fix the shebangs, but
+ # it's just easier to use e.g. python -m pip
+ attach_python_to_venv(d)
+ for script in d.bin.listdir():
+ if script.basename.startswith('python'):
+ continue
+ script.remove()
+ #
+ try:
+ atomic_run(
+ [str(d.python), '-m', 'pip', 'install', '--upgrade', 'build', 'pip', 'setuptools', 'wheel'],
+ check=True,
+ capture_output=True,
+ )
+ atomic_run(
+ [str(d.python), '-m', 'pip', 'install', str(HPY_ROOT)],
+ check=True,
+ capture_output=True,
+ )
+ except subprocess.CalledProcessError as cpe:
+ print_CalledProcessError(cpe)
+ raise
+ return d
+
+def attach_python_to_venv(d):
+ if os.name == 'nt':
+ d.bin = d.join('Scripts')
+ else:
+ d.bin = d.join('bin')
+ d.python = d.bin.join('python')
+
+
+@pytest.mark.usefixtures('initargs')
+class TestDistutils:
+
+ @pytest.fixture()
+ def initargs(self, pytestconfig, tmpdir, venv_template):
+ self.tmpdir = tmpdir
+ # create a fresh venv by copying the template
+ self.venv = tmpdir.join('venv')
+ shutil.copytree(venv_template, self.venv)
+ attach_python_to_venv(self.venv)
+ # create the files for our test project
+ self.hpy_test_project = tmpdir.join('hpy_test_project').ensure(dir=True)
+ self.gen_project()
+ self.hpy_test_project.chdir()
+
+ @pytest.fixture(params=['cpython', 'hybrid', 'universal'])
+ def hpy_abi(self, request):
+ return request.param
+
+ def python(self, *args, capture=False, hpy_abi=None):
+ """
+ Run python inside the venv; if capture==True, return stdout
+ """
+ cmd = [str(self.venv.python)] + list(args)
+ if hpy_abi: # prepend an environment variable definition: HPY_ABI=...
+ cmd = [f'HPY_ABI={hpy_abi}'] + cmd
+ print('[RUN]', ' '.join(cmd))
+ if capture:
+ proc = atomic_run(cmd, capture_output=True)
+ out = proc.stdout.decode('latin-1').strip()
+ else:
+ proc = atomic_run(cmd)
+ out = None
+ proc.check_returncode()
+ return out
+
+
+ def writefile(self, fname, content):
+ """
+ Write a file inside hpy_test_project
+ """
+ f = self.hpy_test_project.join(fname)
+ content = textwrap.dedent(content)
+ f.write(content)
+
+ def gen_project(self):
+ """
+ Generate the files needed to build the project, except setup.py
+ """
+ self.writefile('cpymod.c', """
+ // the simplest possible Python/C module
+ #include
+ static PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "cpymod",
+ "cpymod docstring"
+ };
+
+ PyMODINIT_FUNC
+ PyInit_cpymod(void)
+ {
+ return PyModule_Create(&moduledef);
+ }
+ """)
+
+ self.writefile('hpymod.c', """
+ // the simplest possible HPy module
+ #include
+ static HPyModuleDef moduledef = {
+ .doc = "hpymod with HPy ABI: " HPY_ABI,
+ };
+
+ HPy_MODINIT(hpymod, moduledef)
+ """)
+
+ self.writefile('hpymod_legacy.c', """
+ // the simplest possible HPy+legacy module
+ #include
+ #include
+
+ static PyObject *f(PyObject *self, PyObject *args)
+ {
+ return PyLong_FromLong(1234);
+ }
+ static PyMethodDef my_legacy_methods[] = {
+ {"f", (PyCFunction)f, METH_NOARGS},
+ {NULL}
+ };
+
+ static HPyModuleDef moduledef = {
+ .doc = "hpymod_legacy with HPy ABI: " HPY_ABI,
+ .legacy_methods = my_legacy_methods,
+ };
+
+ HPy_MODINIT(hpymod_legacy, moduledef)
+ """)
+
+ def gen_setup_py(self, src):
+ preamble = textwrap.dedent("""
+ from setuptools import setup, Extension
+ cpymod = Extension("cpymod", ["cpymod.c"])
+ hpymod = Extension("hpymod", ["hpymod.c"])
+ hpymod_legacy = Extension("hpymod_legacy", ["hpymod_legacy.c"])
+ """)
+ src = preamble + textwrap.dedent(src)
+ f = self.hpy_test_project.join('setup.py')
+ f.write(src)
+
+ def get_docstring(self, modname):
+ cmd = f'import {modname}; print({modname}.__doc__)'
+ return self.python('-c', cmd, capture=True)
+
+ def test_cpymod_setup_install(self):
+ # CPython-only project, no hpy at all. This is a baseline to check
+ # that everything works even without hpy.
+ self.gen_setup_py("""
+ setup(name = "hpy_test_project",
+ ext_modules = [cpymod],
+ )
+ """)
+ # self.python('setup.py', 'install')
+ self.python('-m', 'build')
+ self.python('-m', 'pip', 'install', '.')
+ doc = self.get_docstring('cpymod')
+ assert doc == 'cpymod docstring'
+
+ def test_cpymod_with_empty_hpy_ext_modules_setup_install(self):
+ # if we have hpy_ext_modules=[] we trigger the hpy.devel monkey
+ # patch. This checks that we don't ext_modules still works after that.
+ self.gen_setup_py("""
+ setup(name = "hpy_test_project",
+ ext_modules = [cpymod],
+ hpy_ext_modules = []
+ )
+ """)
+ # self.python('setup.py', 'install')
+ self.python('-m', 'build')
+ self.python('-m', 'pip', 'install', '.')
+ doc = self.get_docstring('cpymod')
+ assert doc == 'cpymod docstring'
+
+ def test_hpymod_py_stub(self):
+ # check that that we generated the .py stub for universal
+ self.gen_setup_py("""
+ setup(name = "hpy_test_project",
+ hpy_ext_modules = [hpymod],
+ )
+ """)
+ # self.python('setup.py', '--hpy-abi=universal', 'build')
+ self.python('-m', 'build', hpy_abi='universal')
+ self.python('-m', 'pip', 'install', '.')
+ build = self.hpy_test_project.join('build')
+ lib = build.listdir('lib*')[0]
+ hpymod_py = lib.join('hpymod.py')
+ assert hpymod_py.check(exists=True)
+ assert 'This file is automatically generated by hpy' in hpymod_py.read()
+
+ def test_hpymod_build_platlib(self):
+ # check that if we have only hpy_ext_modules, the distribution is
+ # detected as "platform-specific" and not "platform-neutral". In
+ # particular, we want the end result to be in
+ # e.g. build/lib.linux-x86_64-3.8 and NOT in build/lib.
+ self.gen_setup_py("""
+ setup(name = "hpy_test_project",
+ hpy_ext_modules = [hpymod],
+ )
+ """)
+ # self.python('setup.py', 'build')
+ self.python('-m', 'build')
+ self.python('-m', 'pip', 'install', '.')
+ build = self.hpy_test_project.join('build')
+ libs = build.listdir('lib*')
+ assert len(libs) == 1
+ libdir = libs[0]
+ # this is something like lib.linux-x86_64-cpython-38
+ assert libdir.basename != 'lib'
+
+ def test_hpymod_build_ext_inplace(self, hpy_abi):
+ # check that we can install hpy modules with setup.py build_ext -i
+ self.gen_setup_py("""
+ setup(name = "hpy_test_project",
+ hpy_ext_modules = [hpymod],
+ )
+ """)
+ # self.python('setup.py', f'--hpy-abi={hpy_abi}', 'build_ext', '--inplace')
+ self.python('-m', 'build', hpy_abi=hpy_abi)
+ self.python('-m', 'pip', 'install', '.')
+ doc = self.get_docstring('hpymod')
+ assert doc == f'hpymod with HPy ABI: {hpy_abi}'
+
+ def test_hpymod_setup_install(self, hpy_abi):
+ # check that we can install hpy modules with setup.py install
+ self.gen_setup_py("""
+ setup(name = "hpy_test_project",
+ hpy_ext_modules = [hpymod],
+ )
+ """)
+ # self.python('setup.py', f'--hpy-abi={hpy_abi}', 'install')
+ self.python('-m', 'build', hpy_abi=hpy_abi)
+ self.python('-m', 'pip', 'install', '.')
+ doc = self.get_docstring('hpymod')
+ assert doc == f'hpymod with HPy ABI: {hpy_abi}'
+
+ def test_hpymod_wheel(self, hpy_abi):
+ # check that we can build and install wheels
+ self.gen_setup_py("""
+ setup(name = "hpy_test_project",
+ hpy_ext_modules = [hpymod],
+ )
+ """)
+ # self.python('-m', f'--hpy-abi={hpy_abi}', 'bdist_wheel')
+ # self.python('setup.py', f'--hpy-abi={hpy_abi}', 'bdist_wheel')
+ self.python('-m', 'build', hpy_abi=hpy_abi)
+ self.python('-m', 'pip', 'install', 'bdist_wheel')
+ dist = self.hpy_test_project.join('dist')
+ whl = dist.listdir('*.whl')[0]
+ self.python('-m', 'pip', 'install', str(whl))
+ doc = self.get_docstring('hpymod')
+ assert doc == f'hpymod with HPy ABI: {hpy_abi}'
+
+ def test_dont_mix_cpython_and_universal_abis(self):
+ """
+ See issue #322
+ """
+ # make sure that the build dirs for cpython and universal ABIs are
+ # distinct
+ self.gen_setup_py("""
+ setup(name = "hpy_test_project",
+ hpy_ext_modules = [hpymod],
+ install_requires = [],
+ )
+ """)
+ # self.python('setup.py', 'install')
+ self.python('-m', 'build')
+ self.python('-m', 'pip', 'install', '.')
+ # in the build/ dir, we should have 2 directories: temp and lib
+ build = self.hpy_test_project.join('build')
+ temps = build.listdir('temp*')
+ libs = build.listdir('lib*')
+ assert len(temps) == 1
+ assert len(libs) == 1
+ #
+ doc = self.get_docstring('hpymod')
+ assert doc == 'hpymod with HPy ABI: cpython'
+
+ # now recompile with universal *without* cleaning the build
+ # self.python('setup.py', '--hpy-abi=universal', 'install')
+ self.python('-m', 'build', hpy_abi='universal')
+ self.python('-m', 'pip', 'install', '.')
+ # in the build/ dir, we should have 4 directories: 2 temp*, and 2 lib*
+ build = self.hpy_test_project.join('build')
+ temps = build.listdir('temp*')
+ libs = build.listdir('lib*')
+ assert len(temps) == 2
+ assert len(libs) == 2
+ #
+ doc = self.get_docstring('hpymod')
+ assert doc == 'hpymod with HPy ABI: universal'
+
+ def test_hpymod_legacy(self, hpy_abi):
+ if hpy_abi == 'universal':
+ pytest.skip('only for cpython and hybrid ABIs')
+ self.gen_setup_py("""
+ setup(name = "hpy_test_project",
+ hpy_ext_modules = [hpymod_legacy],
+ install_requires = [],
+ )
+ """)
+ # self.python('setup.py', 'install')
+ self.python('-m', 'build', hpy_abi=hpy_abi)
+ self.python('-m', 'pip', 'install', '.')
+ src = 'import hpymod_legacy; print(hpymod_legacy.f())'
+ out = self.python('-c', src, capture=True)
+ assert out == '1234'
+
+ def test_hpymod_legacy_fails_with_universal(self):
+ self.gen_setup_py("""
+ setup(name = "hpy_test_project",
+ hpy_ext_modules = [hpymod_legacy],
+ install_requires = [],
+ )
+ """)
+ self.python('-m', 'build', hpy_abi='universal')
+ with pytest.raises(subprocess.CalledProcessError) as exc:
+ # self.python('setup.py', '--hpy-abi=universal', 'install', capture=True)
+ self.python('-m', 'pip', 'install', '.')
+ expected_msg = ("It is forbidden to #include when "
+ "targeting the HPy Universal ABI")
+
+ # gcc/clang prints the #error on stderr, MSVC prints it on
+ # stdout. Here we check that the error is printed "somewhere", we
+ # don't care exactly where.
+ out = exc.value.stdout + b'\n' + exc.value.stderr
+ out = out.decode('latin-1')
+ if expected_msg not in out:
+ print_CalledProcessError(exc.value)
+ assert expected_msg in out
diff --git a/test/hpy_devel/test_distutils.py b/test/hpy_devel/test_distutils.py.DISABLED
similarity index 100%
rename from test/hpy_devel/test_distutils.py
rename to test/hpy_devel/test_distutils.py.DISABLED