Skip to content

Commit f987adb

Browse files
committed
Move dependency-group logic to hatch
Dependency groups have no impact on binary distributions so moved to build frontend.
1 parent e2fcc89 commit f987adb

File tree

4 files changed

+43
-42
lines changed

4 files changed

+43
-42
lines changed

backend/src/hatchling/metadata/core.py

-35
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import os
44
import sys
5-
from collections import defaultdict
65
from contextlib import suppress
76
from copy import deepcopy
87
from typing import TYPE_CHECKING, Any, Generic, cast
@@ -53,8 +52,6 @@ def __init__(
5352
self._core: CoreMetadata | None = None
5453
self._hatch: HatchMetadata | None = None
5554

56-
self._dependency_groups: dict[str, list[str]] | None = None
57-
5855
self._core_raw_metadata: dict[str, Any] | None = None
5956
self._dynamic: list[str] | None = None
6057
self._name: str | None = None
@@ -80,38 +77,6 @@ def context(self) -> Context:
8077

8178
return self._context
8279

83-
@property
84-
def dependency_groups(self) -> dict[str, Any]:
85-
"""
86-
https://peps.python.org/pep-0735/
87-
"""
88-
if self._dependency_groups is None:
89-
dependency_groups = self.config.get('dependency-groups', {})
90-
91-
if not isinstance(dependency_groups, dict):
92-
message = 'Field `dependency-groups` must be a table'
93-
raise ValueError(message)
94-
95-
original_names = defaultdict(list)
96-
normalized_groups = {}
97-
98-
for group_name, value in dependency_groups.items():
99-
normed_group_name = normalize_project_name(group_name)
100-
original_names[normed_group_name].append(group_name)
101-
normalized_groups[normed_group_name] = value
102-
103-
errors = []
104-
for normed_name, names in original_names.items():
105-
if len(names) > 1:
106-
errors.append(f"{normed_name} ({', '.join(names)})")
107-
if errors:
108-
msg = f"Field `dependency-groups` contains duplicate names: {', '.join(errors)}"
109-
raise ValueError(msg)
110-
111-
self._dependency_groups = dependency_groups
112-
113-
return self._dependency_groups
114-
11580
@property
11681
def core_raw_metadata(self) -> dict[str, Any]:
11782
if self._core_raw_metadata is None:

src/hatch/env/plugin/interface.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ def dependencies_complex(self):
310310

311311
for dependency_group in self.dependency_groups:
312312
all_dependencies_complex.extend(
313-
get_complex_dependency_group(self.metadata.dependency_groups, dependency_group)
313+
get_complex_dependency_group(self.app.project.dependency_groups, dependency_group)
314314
)
315315

316316
return all_dependencies_complex
@@ -453,7 +453,7 @@ def dependency_groups(self):
453453
normalized_dependency_group = normalize_project_name(dependency_group)
454454
if (
455455
not self.metadata.hatch.metadata.hook_config
456-
and normalized_dependency_group not in self.metadata.dependency_groups
456+
and normalized_dependency_group not in self.app.project.dependency_groups
457457
):
458458
message = (
459459
f'Dependency Group `{normalized_dependency_group}` of field `tool.hatch.envs.{self.name}.dependency-groups` is not '

src/hatch/project/core.py

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from __future__ import annotations
22

33
import re
4+
from collections import defaultdict
45
from contextlib import contextmanager
56
from functools import cached_property
6-
from typing import TYPE_CHECKING, Generator, cast
7+
from typing import TYPE_CHECKING, Any, Generator, cast
78

89
from hatch.project.env import EnvironmentMetadata
910
from hatch.utils.fs import Path
@@ -103,6 +104,37 @@ def build_frontend(self) -> BuildFrontend:
103104
def env_metadata(self) -> EnvironmentMetadata:
104105
return EnvironmentMetadata(self.app.data_dir / 'env' / '.metadata', self.location)
105106

107+
@cached_property
108+
def dependency_groups(self) -> dict[str, Any]:
109+
"""
110+
https://peps.python.org/pep-0735/
111+
"""
112+
from hatchling.metadata.utils import normalize_project_name
113+
114+
dependency_groups = self.raw_config.get('dependency-groups', {})
115+
116+
if not isinstance(dependency_groups, dict):
117+
message = 'Field `dependency-groups` must be a table'
118+
raise TypeError(message)
119+
120+
original_names = defaultdict(list)
121+
normalized_groups = {}
122+
123+
for group_name, value in dependency_groups.items():
124+
normed_group_name = normalize_project_name(group_name)
125+
original_names[normed_group_name].append(group_name)
126+
normalized_groups[normed_group_name] = value
127+
128+
errors = []
129+
for normed_name, names in original_names.items():
130+
if len(names) > 1:
131+
errors.append(f"{normed_name} ({', '.join(names)})")
132+
if errors:
133+
msg = f"Field `dependency-groups` contains duplicate names: {', '.join(errors)}"
134+
raise ValueError(msg)
135+
136+
return normalized_groups
137+
106138
def get_environment(self, env_name: str | None = None) -> EnvironmentInterface:
107139
if env_name is None:
108140
env_name = self.app.env

tests/env/plugin/test_interface.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -793,13 +793,15 @@ def test_not_array(self, isolation, isolated_data_dir, platform, global_applicat
793793
):
794794
_ = environment.dependency_groups
795795

796-
def test_correct(self, isolation, isolated_data_dir, platform, global_application):
796+
def test_correct(self, isolation, isolated_data_dir, platform, temp_application):
797797
config = {
798798
'project': {'name': 'my_app', 'version': '0.0.1'},
799799
'dependency-groups': {'foo-bar': [], 'baz': []},
800800
'tool': {'hatch': {'envs': {'default': {'dependency-groups': ['Foo...Bar', 'Baz', 'baZ']}}}},
801801
}
802802
project = Project(isolation, config=config)
803+
project.set_app(temp_application)
804+
temp_application.project = project
803805
environment = MockEnvironment(
804806
isolation,
805807
project.metadata,
@@ -810,7 +812,7 @@ def test_correct(self, isolation, isolated_data_dir, platform, global_applicatio
810812
isolated_data_dir,
811813
platform,
812814
0,
813-
global_application,
815+
temp_application,
814816
)
815817

816818
assert environment.dependency_groups == ['baz', 'foo-bar']
@@ -865,7 +867,7 @@ def test_group_empty_string(self, isolation, isolated_data_dir, platform, global
865867
):
866868
_ = environment.dependency_groups
867869

868-
def test_group_undefined(self, isolation, isolated_data_dir, platform, global_application):
870+
def test_group_undefined(self, isolation, isolated_data_dir, platform, temp_application):
869871
config = {
870872
'project': {
871873
'name': 'my_app',
@@ -875,6 +877,8 @@ def test_group_undefined(self, isolation, isolated_data_dir, platform, global_ap
875877
'tool': {'hatch': {'envs': {'default': {'dependency-groups': ['foo', 'bar', '']}}}},
876878
}
877879
project = Project(isolation, config=config)
880+
project.set_app(temp_application)
881+
temp_application.project = project
878882
environment = MockEnvironment(
879883
isolation,
880884
project.metadata,
@@ -885,7 +889,7 @@ def test_group_undefined(self, isolation, isolated_data_dir, platform, global_ap
885889
isolated_data_dir,
886890
platform,
887891
0,
888-
global_application,
892+
temp_application,
889893
)
890894

891895
with pytest.raises(

0 commit comments

Comments
 (0)