diff --git a/mesonpy/__init__.py b/mesonpy/__init__.py index feca54a4..0455bfd1 100644 --- a/mesonpy/__init__.py +++ b/mesonpy/__init__.py @@ -747,7 +747,7 @@ def __init__( self._metadata.requires_python.prereleases = True if platform.python_version().rstrip('+') not in self._metadata.requires_python: raise MesonBuilderError( - f'Package requires Python version {self._metadata.requires_python}, ' + f'The package requires Python version {self._metadata.requires_python}, ' f'running on {platform.python_version()}') # limited API @@ -759,6 +759,11 @@ def __init__( if not value: self._limited_api = False + if self._limited_api and bool(sysconfig.get_config_var('Py_GIL_DISABLED')): + raise BuildError( + 'The package targets Python\'s Limited API, which is not supported by free-threaded CPython. ' + 'The "python.allow_limited_api" Meson build option may be used to override the package default.') + def _run(self, cmd: Sequence[str]) -> None: """Invoke a subprocess.""" # Flush the line to ensure that the log line with the executed diff --git a/tests/test_editable.py b/tests/test_editable.py index 3121d688..13f03f13 100644 --- a/tests/test_editable.py +++ b/tests/test_editable.py @@ -6,6 +6,8 @@ import os import pathlib import pkgutil +import re +import subprocess import sys from contextlib import redirect_stdout @@ -16,7 +18,16 @@ from mesonpy import _editable -from .test_wheel import EXT_SUFFIX +from .test_wheel import EXT_SUFFIX, NOGIL_BUILD + + +def find_cython_version(): + cython_version_str = subprocess.run(['cython', '--version'], check=True, + stdout=subprocess.PIPE, text=True).stdout + version_str = re.search(r'(\d{1,4}\.\d{1,4}\.?\d{0,4})', cython_version_str).group(0) + return tuple(map(int, version_str.split('.'))) + +CYTHON_VERSION = find_cython_version() def test_walk(package_complex): @@ -280,6 +291,8 @@ def test_editable_rebuild(package_purelib_and_platlib, tmp_path, verbose, args): sys.modules.pop('pure', None) +@pytest.mark.skipif(NOGIL_BUILD and CYTHON_VERSION < (3, 1, 0), + reason='Cython version too old, no free-threaded CPython support') def test_editable_verbose(venv, package_complex, editable_complex, monkeypatch): monkeypatch.setenv('MESONPY_EDITABLE_VERBOSE', '1') venv.pip('install', os.fspath(editable_complex)) diff --git a/tests/test_project.py b/tests/test_project.py index db56136d..d2a4e5e4 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -23,7 +23,7 @@ def test_unsupported_python_version(package_unsupported_python_version): - with pytest.raises(mesonpy.MesonBuilderError, match='Package requires Python version ==1.0.0'): + with pytest.raises(mesonpy.MesonBuilderError, match='The package requires Python version ==1.0.0'): with mesonpy._project(): pass diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 659ecbf5..24ed59ff 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -39,6 +39,8 @@ 'win32': '.dll', }.get(sys.platform, '.so') +NOGIL_BUILD = bool(sysconfig.get_config_var('Py_GIL_DISABLED')) + # Test against the wheel tag generated by packaging module. tag = next(packaging.tags.sys_tags()) ABI = tag.abi @@ -287,6 +289,7 @@ def test_skip_subprojects(package_subproject, tmp_path, arg): # Requires Meson 1.3.0, see https://github.com/mesonbuild/meson/pull/11745. @pytest.mark.skipif(MESON_VERSION < (1, 2, 99), reason='Meson version too old') +@pytest.mark.skipif(NOGIL_BUILD, reason='Free-threaded CPython does not support the limited API') def test_limited_api(wheel_limited_api): artifact = wheel.wheelfile.WheelFile(wheel_limited_api) name = artifact.parsed_filename @@ -297,6 +300,7 @@ def test_limited_api(wheel_limited_api): # Requires Meson 1.3.0, see https://github.com/mesonbuild/meson/pull/11745. @pytest.mark.skipif(MESON_VERSION < (1, 2, 99), reason='Meson version too old') +@pytest.mark.skipif(NOGIL_BUILD, reason='Free-threaded CPython does not support the limited API') @pytest.mark.xfail('__pypy__' in sys.builtin_module_names, reason='PyPy does not use special modules suffix for stable ABI') def test_limited_api_bad(package_limited_api, tmp_path): with pytest.raises(mesonpy.BuildError, match='The package declares compatibility with Python limited API but '):