diff --git a/docs/history/hatch.md b/docs/history/hatch.md index 0d8af505a..8394be4ca 100644 --- a/docs/history/hatch.md +++ b/docs/history/hatch.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ***Fixed:*** - Ensure that the `dependency_hash` method of the `environment` interface is called after `sync_dependencies` for cases where the hash is only known at that point, such as for dependency lockers +- Only acknowledge the `HATCH_PYTHON_VARIANT_*` environment variables for Python resolution for supported platforms and architectures ## [1.9.0](https://github.com/pypa/hatch/releases/tag/hatch-v1.9.0) - 2023-12-19 ## {: #hatch-v1.9.0 } diff --git a/src/hatch/python/resolve.py b/src/hatch/python/resolve.py index 44772ee40..afb5ffa54 100644 --- a/src/hatch/python/resolve.py +++ b/src/hatch/python/resolve.py @@ -170,15 +170,24 @@ def get_compatible_distributions() -> dict[str, Distribution]: def _get_default_variant(name: str, system: str, arch: str, abi: str) -> str: - variant = os.environ.get(f'HATCH_PYTHON_VARIANT_{system.upper()}', '').lower() - if variant: - return variant - + # not PyPy if name[0].isdigit(): - if system == 'windows' and abi == 'msvc': - return 'shared' + # https://gregoryszorc.com/docs/python-build-standalone/main/running.html + variant = os.environ.get(f'HATCH_PYTHON_VARIANT_{system.upper()}', '').lower() + + if system == 'windows': + # Shared versus static + if variant: + return variant + + if abi == 'msvc': + return 'shared' if system == 'linux' and arch == 'x86_64': + # Intel-specific optimizations depending on age of release + if variant: + return variant + if name == '3.8': return 'v1' diff --git a/tests/cli/python/test_install.py b/tests/cli/python/test_install.py index 388289387..7d27abc92 100644 --- a/tests/cli/python/test_install.py +++ b/tests/cli/python/test_install.py @@ -3,10 +3,10 @@ import pytest +from hatch.errors import PythonDistributionResolutionError from hatch.python.core import InstalledDistribution from hatch.python.distributions import ORDERED_DISTRIBUTIONS from hatch.python.resolve import get_distribution -from hatch.utils.structures import EnvVars def test_unknown(hatch, helpers, path_append, mocker): @@ -25,11 +25,11 @@ def test_unknown(hatch, helpers, path_append, mocker): path_append.assert_not_called() -def test_incompatible_single(hatch, helpers, path_append, platform, dist_name, mocker): +def test_incompatible_single(hatch, helpers, path_append, dist_name, mocker): + mocker.patch('hatch.python.resolve.get_distribution', side_effect=PythonDistributionResolutionError) install = mocker.patch('hatch.python.core.PythonManager.install') - with EnvVars({f'HATCH_PYTHON_VARIANT_{platform.name.upper()}': 'foo'}): - result = hatch('python', 'install', dist_name) + result = hatch('python', 'install', dist_name) assert result.exit_code == 1, result.output assert result.output == helpers.dedent( @@ -42,11 +42,11 @@ def test_incompatible_single(hatch, helpers, path_append, platform, dist_name, m path_append.assert_not_called() -def test_incompatible_all(hatch, helpers, path_append, platform, mocker): +def test_incompatible_all(hatch, helpers, path_append, mocker): + mocker.patch('hatch.python.resolve.get_distribution', side_effect=PythonDistributionResolutionError) install = mocker.patch('hatch.python.core.PythonManager.install') - with EnvVars({f'HATCH_PYTHON_VARIANT_{platform.name.upper()}': 'foo'}): - result = hatch('python', 'install', 'all') + result = hatch('python', 'install', 'all') assert result.exit_code == 1, result.output assert result.output == helpers.dedent( diff --git a/tests/conftest.py b/tests/conftest.py index e3f6580dd..f3daed4b5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -125,6 +125,13 @@ def current_platform(): return PLATFORM.name +@pytest.fixture(scope='session') +def current_arch(): + import platform + + return platform.machine().lower() + + @pytest.fixture(scope='session') def uri_slash_prefix(): return '//' if os.sep == '/' else '///' diff --git a/tests/python/test_core.py b/tests/python/test_core.py index 475c8640f..1fd11d690 100644 --- a/tests/python/test_core.py +++ b/tests/python/test_core.py @@ -3,7 +3,7 @@ import pytest from hatch.python.core import InstalledDistribution, PythonManager -from hatch.python.distributions import DISTRIBUTIONS, ORDERED_DISTRIBUTIONS +from hatch.python.distributions import ORDERED_DISTRIBUTIONS from hatch.python.resolve import get_distribution @@ -64,10 +64,10 @@ def test_no_python_path(self, temp_dir): assert manager.get_installed() == {} - def test_order(self, temp_dir): + def test_order(self, temp_dir, compatible_python_distributions): manager = PythonManager(temp_dir) - for name in DISTRIBUTIONS: + for name in compatible_python_distributions: dist = get_distribution(name) path = temp_dir / dist.name path.mkdir() @@ -77,4 +77,4 @@ def test_order(self, temp_dir): python_path.parent.ensure_dir_exists() python_path.touch() - assert tuple(manager.get_installed()) == ORDERED_DISTRIBUTIONS + assert tuple(manager.get_installed()) == compatible_python_distributions diff --git a/tests/python/test_resolve.py b/tests/python/test_resolve.py index 5b60fc030..9a7d11e8c 100644 --- a/tests/python/test_resolve.py +++ b/tests/python/test_resolve.py @@ -1,3 +1,5 @@ +import sys + import pytest from hatch.errors import PythonDistributionResolutionError, PythonDistributionUnknownError @@ -10,6 +12,7 @@ def test_unknown_distribution(self): with pytest.raises(PythonDistributionUnknownError, match='Unknown distribution: foo'): get_distribution('foo') + @pytest.mark.skipif(sys.platform == 'darwin', reason='No variants for macOS') def test_resolution_error(self, platform): with EnvVars({f'HATCH_PYTHON_VARIANT_{platform.name.upper()}': 'foo'}), pytest.raises( PythonDistributionResolutionError, @@ -47,14 +50,14 @@ def test_pypy(self): ('linux', 'v4'), ], ) -def test_variants(platform, system, variant): +def test_variants(platform, system, variant, current_arch): if platform.name != system: pytest.skip(f'Skipping test for: {system}') with EnvVars({f'HATCH_PYTHON_VARIANT_{system.upper()}': variant}): dist = get_distribution('3.11') - if system == 'linux' and variant == 'v1': + if system == 'linux' and (current_arch != 'x86_64' or variant == 'v1'): assert variant not in dist.source else: assert variant in dist.source