From 7351b29827b9d7fc08433c2edcd98409520252c6 Mon Sep 17 00:00:00 2001 From: Ofek Lev Date: Thu, 26 Oct 2023 00:12:08 -0400 Subject: [PATCH] Fix handling of the metadata and Python resolution --- src/hatch/env/virtual.py | 15 +++++++++++++-- src/hatch/utils/metadata.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/hatch/utils/metadata.py diff --git a/src/hatch/env/virtual.py b/src/hatch/env/virtual.py index 47e3ea1ab..78e8c867d 100644 --- a/src/hatch/env/virtual.py +++ b/src/hatch/env/virtual.py @@ -18,6 +18,7 @@ if TYPE_CHECKING: from collections.abc import Iterable + from packaging.specifiers import SpecifierSet from virtualenv.discovery.py_info import PythonInfo from hatch.python.core import PythonManager @@ -210,7 +211,7 @@ def get_interpreter_resolver_env(self) -> dict[str, str]: return env internal_path = os.pathsep.join(python_dirs) - old_path = os.environ.pop('PATH', None) + old_path = env.pop('PATH', None) env['PATH'] = internal_path if old_path is None else f'{old_path}{os.pathsep}{internal_path}' return env @@ -231,7 +232,7 @@ def _interpreter_is_compatible(self, interpreter: PythonInfo) -> bool: return ( interpreter.executable and self._is_stable_path(interpreter.executable) - and self.metadata.core.python_constraint.contains(interpreter.version_str) + and self._python_constraint.contains(interpreter.version_str) ) def _get_concrete_interpreter_path(self, python_version: str = '') -> str | None: @@ -349,6 +350,16 @@ def _python_resolvers(self) -> dict[str, Callable[[str], str | None]]: 'internal': self._resolve_internal_interpreter_path, } + @cached_property + def _python_constraint(self) -> SpecifierSet: + from packaging.specifiers import SpecifierSet + + from hatch.utils.metadata import get_project_metadata + + project_metadata = get_project_metadata(self) + + return SpecifierSet(project_metadata['requires-python']) + @contextmanager def safe_activation(self): # Set user-defined environment variables first so ours take precedence diff --git a/src/hatch/utils/metadata.py b/src/hatch/utils/metadata.py new file mode 100644 index 000000000..a2358496b --- /dev/null +++ b/src/hatch/utils/metadata.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from hatch.env.plugin.interface import EnvironmentInterface + + +def get_project_metadata(environment: EnvironmentInterface) -> dict[str, Any]: + from hatchling.dep.core import dependencies_in_sync + + if not environment.metadata.hatch.metadata.hook_config or dependencies_in_sync( + environment.metadata.build.requires_complex + ): + from hatchling.metadata.utils import resolve_metadata_fields + + with environment.root.as_cwd(): + return resolve_metadata_fields(environment.metadata) + + try: + environment.check_compatibility() + except Exception as e: + environment.app.abort(f'Environment `{environment.name}` is incompatible: {e}') + + import json + + with environment.root.as_cwd(), environment.build_environment(environment.metadata.build.requires): + command = ['python', '-u', '-W', 'ignore', '-m', 'hatchling', 'metadata', '--app', '--compact'] + process = environment.platform.capture_process(command) + return json.loads(environment.app.read_builder(process))