Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Add version to metadata hook, use version to retrieve deps #1511

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions backend/src/hatchling/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ def build_sdist(sdist_directory: str, config_settings: dict[str, Any] | None = N
"""
from hatchling.builders.sdist import SdistBuilder

builder = SdistBuilder(os.getcwd())
return os.path.basename(next(builder.build(directory=sdist_directory, versions=['standard'])))
builder = SdistBuilder(os.getcwd(), versions=['standard'])
return os.path.basename(next(builder.build(directory=sdist_directory)))


def get_requires_for_build_wheel(config_settings: dict[str, Any] | None = None) -> list[str]: # noqa: ARG001
Expand All @@ -54,8 +54,8 @@ def build_wheel(
"""
from hatchling.builders.wheel import WheelBuilder

builder = WheelBuilder(os.getcwd())
return os.path.basename(next(builder.build(directory=wheel_directory, versions=['standard'])))
builder = WheelBuilder(os.getcwd(), versions=['standard'])
return os.path.basename(next(builder.build(directory=wheel_directory)))


def get_requires_for_build_editable(config_settings: dict[str, Any] | None = None) -> list[str]: # noqa: ARG001
Expand All @@ -79,9 +79,8 @@ def build_editable(
"""
from hatchling.builders.wheel import WheelBuilder

builder = WheelBuilder(os.getcwd())
return os.path.basename(next(builder.build(directory=wheel_directory, versions=['editable'])))

builder = WheelBuilder(os.getcwd(), versions=['editable'])
return os.path.basename(next(builder.build(directory=wheel_directory)))

# Any builder that has build-time hooks like Hatchling and setuptools cannot technically keep PEP 517's identical
# metadata promise e.g. C extensions would require different tags in the `WHEEL` file. Therefore, we consider the
Expand All @@ -106,8 +105,7 @@ def prepare_metadata_for_build_wheel(
https://peps.python.org/pep-0517/#prepare-metadata-for-build-wheel
"""
from hatchling.builders.wheel import WheelBuilder

builder = WheelBuilder(os.getcwd())
builder = WheelBuilder(os.getcwd(), versions=["standard"])

directory = os.path.join(metadata_directory, f'{builder.artifact_project_id}.dist-info')
if not os.path.isdir(directory):
Expand All @@ -128,7 +126,7 @@ def prepare_metadata_for_build_editable(
from hatchling.builders.constants import EDITABLES_REQUIREMENT
from hatchling.builders.wheel import WheelBuilder

builder = WheelBuilder(os.getcwd())
builder = WheelBuilder(os.getcwd(), versions=['editable'])

directory = os.path.join(metadata_directory, f'{builder.artifact_project_id}.dist-info')
if not os.path.isdir(directory):
Expand Down
9 changes: 5 additions & 4 deletions backend/src/hatchling/builders/plugin/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,15 @@ def __init__(
config: dict[str, Any] | None = None,
metadata: ProjectMetadata | None = None,
app: Application | None = None,
versions: list[str] | None = None,
) -> None:
self.__root = root
self.__plugin_manager = cast(PluginManagerBound, plugin_manager)
self.__raw_config = config
self.__metadata = metadata
self.__app = app
self.__config = cast(BuilderConfigBound, None)
self.__versions = versions
self.__project_config: dict[str, Any] | None = None
self.__hatch_config: dict[str, Any] | None = None
self.__build_config: dict[str, Any] | None = None
Expand All @@ -80,7 +82,6 @@ def build(
self,
*,
directory: str | None = None,
versions: list[str] | None = None,
hooks_only: bool | None = None,
clean: bool | None = None,
clean_hooks_after: bool | None = None,
Expand All @@ -101,7 +102,7 @@ def build(

version_api = self.get_version_api()

versions = versions or self.config.versions
versions = self.__versions or self.config.versions
if versions:
unknown_versions = set(versions) - set(version_api)
if unknown_versions:
Expand Down Expand Up @@ -290,8 +291,8 @@ def metadata(self) -> ProjectMetadata:
if self.__metadata is None:
from hatchling.metadata.core import ProjectMetadata

self.__metadata = ProjectMetadata(self.root, self.plugin_manager, self.__raw_config)

self.__metadata = ProjectMetadata(self.root, self.plugin_manager, self.__raw_config,
self.__versions)
return self.__metadata

@property
Expand Down
1 change: 0 additions & 1 deletion backend/src/hatchling/builders/wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,6 @@ def build_editable_detection(self, directory: str, **build_data: Any) -> str:
from editables import EditableProject

build_data['tag'] = self.get_default_tag()

with WheelArchive(
self.artifact_project_id, reproducible=self.config.reproducible
) as archive, RecordFile() as records:
Expand Down
4 changes: 3 additions & 1 deletion backend/src/hatchling/cli/metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ def metadata_impl(
called_by_app: bool, # noqa: ARG001
field: str,
compact: bool,
version: str = "standard",
) -> None:
import json
import os
Expand All @@ -22,7 +23,7 @@ def metadata_impl(

root = os.getcwd()
plugin_manager = PluginManager()
project_metadata = ProjectMetadata(root, plugin_manager)
project_metadata = ProjectMetadata(root, plugin_manager, build_versions=[version])

metadata = resolve_metadata_fields(project_metadata)
if field: # no cov
Expand Down Expand Up @@ -55,4 +56,5 @@ def metadata_command(
parser.add_argument('field', nargs='?')
parser.add_argument('-c', '--compact', action='store_true')
parser.add_argument('--app', dest='called_by_app', action='store_true', help=argparse.SUPPRESS)
parser.add_argument('--version', dest='version', default="standard")
parser.set_defaults(func=metadata_impl)
17 changes: 14 additions & 3 deletions backend/src/hatchling/metadata/core.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from __future__ import annotations

import contextlib
import os
import sys
from contextlib import suppress
from copy import deepcopy
from typing import TYPE_CHECKING, Any, Generic, cast
from typing import TYPE_CHECKING, Any, Generic, cast, Generator

from hatchling.metadata.utils import (
format_dependency,
Expand Down Expand Up @@ -36,12 +37,20 @@ def load_toml(path: str) -> dict[str, Any]:
return tomllib.loads(f.read())


@contextlib.contextmanager
def set_version(hook: MetadataHookInterface, version: str) -> Generator[None, None, None]:
old_version = hook.version
hook.version = version
yield
hook.version = old_version

class ProjectMetadata(Generic[PluginManagerBound]):
def __init__(
self,
root: str,
plugin_manager: PluginManagerBound | None,
config: dict[str, Any] | None = None,
build_versions: list[str] | None = None,
) -> None:
self.root = root
self.plugin_manager = plugin_manager
Expand All @@ -57,6 +66,7 @@ def __init__(
self._name: str | None = None
self._version: str | None = None
self._project_file: str | None = None
self._build_versions = build_versions

# App already loaded config
if config is not None and root is not None:
Expand Down Expand Up @@ -193,8 +203,9 @@ def core(self) -> CoreMetadata:

if metadata.dynamic:
for metadata_hook in metadata_hooks.values():
metadata_hook.update(self.core_raw_metadata)
metadata.add_known_classifiers(metadata_hook.get_known_classifiers())
with set_version(metadata_hook, self.version):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the context manager - and we have version property in the hook which we set (and can query in the hook).

metadata_hook.update(self.core_raw_metadata)
metadata.add_known_classifiers(metadata_hook.get_known_classifiers())

new_fields = set(self.core_raw_metadata) - static_fields
for new_field in new_fields:
Expand Down
15 changes: 15 additions & 0 deletions backend/src/hatchling/metadata/plugin/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def hatch_register_metadata_hook():
def __init__(self, root: str, config: dict) -> None:
self.__root = root
self.__config = config
self.__version: str = "standard"

@property
def root(self) -> str:
Expand All @@ -53,6 +54,20 @@ def config(self) -> dict:
"""
return self.__config

@property
def version(self) -> str:
"""
Gets the version of build (standard/editable) that is being run.
"""
return self.__version

@version.setter
def version(self, version: str) -> None:
"""
This sets the version of build (standard/editable) that is being run.
"""
self.__version = version

@abstractmethod
def update(self, metadata: dict) -> None:
"""
Expand Down
3 changes: 2 additions & 1 deletion src/hatch/utils/dep.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ def get_project_dependencies_complex(
from packaging.requirements import Requirement

with environment.root.as_cwd(), environment.build_environment(environment.metadata.build.requires):
command = ['python', '-u', '-W', 'ignore', '-m', 'hatchling', 'metadata', '--compact']
command = ['python', '-u', '-W', 'ignore', '-m', 'hatchling', 'metadata', '--compact',
"--version", "editable" if environment.dev_mode else "standard"]
output = environment.platform.check_command_output(
command,
# Only capture stdout
Expand Down
Loading