19
19
from tox .tox_env .api import ToxEnvCreateArgs
20
20
from tox .tox_env .errors import Fail
21
21
from tox .tox_env .package import Package , PackageToxEnv
22
- from tox .tox_env .python .package import DevLegacyPackage , PythonPackageToxEnv , SdistPackage , WheelPackage
22
+ from tox .tox_env .python .package import (
23
+ EditableLegacyPackage ,
24
+ EditablePackage ,
25
+ PythonPackageToxEnv ,
26
+ SdistPackage ,
27
+ WheelPackage ,
28
+ )
23
29
from tox .tox_env .register import ToxEnvRegister
24
30
from tox .tox_env .runner import RunToxEnv
25
31
@@ -128,6 +134,9 @@ def register_run_env(self, run_env: RunToxEnv) -> Generator[tuple[str, str], Pac
128
134
129
135
def _setup_env (self ) -> None :
130
136
super ()._setup_env ()
137
+ if "editable" in self .builds :
138
+ build_requires = self ._frontend .get_requires_for_build_editable ().requires
139
+ self .installer .install (build_requires , PythonPackageToxEnv .__name__ , "requires_for_build_editable" )
131
140
if "wheel" in self .builds :
132
141
build_requires = self ._frontend .get_requires_for_build_wheel ().requires
133
142
self .installer .install (build_requires , PythonPackageToxEnv .__name__ , "requires_for_build_wheel" )
@@ -151,28 +160,29 @@ def perform_packaging(self, for_env: EnvConfigSet) -> list[Package]:
151
160
"""build the package to install"""
152
161
deps = self ._load_deps (for_env )
153
162
of_type : str = for_env ["package" ]
154
- if of_type == "dev -legacy" :
163
+ if of_type == "editable -legacy" :
155
164
self .setup ()
156
165
deps = [* self .requires (), * self ._frontend .get_requires_for_build_sdist ().requires ] + deps
157
- package : Package = DevLegacyPackage (self .core ["tox_root" ], deps ) # the folder itself is the package
166
+ package : Package = EditableLegacyPackage (self .core ["tox_root" ], deps ) # the folder itself is the package
158
167
elif of_type == "sdist" :
159
168
self .setup ()
160
169
with self ._pkg_lock :
161
170
package = SdistPackage (self ._frontend .build_sdist (sdist_directory = self .pkg_dir ).sdist , deps )
162
- elif of_type == "wheel" :
171
+ elif of_type in { "wheel" , "editable" } :
163
172
w_env = self ._wheel_build_envs .get (for_env ["wheel_build_env" ])
164
173
if w_env is not None and w_env is not self :
165
174
with w_env .display_context (self ._has_display_suspended ):
166
175
return w_env .perform_packaging (for_env )
167
176
else :
168
177
self .setup ()
169
178
with self ._pkg_lock :
170
- path = self ._frontend .build_wheel (
179
+ method = "build_editable" if of_type == "editable" else "build_wheel"
180
+ path = getattr (self ._frontend , method )(
171
181
wheel_directory = self .pkg_dir ,
172
182
metadata_directory = self .meta_folder ,
173
183
config_settings = self ._wheel_config_settings ,
174
184
).wheel
175
- package = WheelPackage (path , deps )
185
+ package = ( EditablePackage if of_type == "editable" else WheelPackage ) (path , deps )
176
186
else : # pragma: no cover # for when we introduce new packaging types and don't implement
177
187
raise TypeError (f"cannot handle package type { of_type } " ) # pragma: no cover
178
188
return [package ]
@@ -209,38 +219,42 @@ def _load_deps_from_built_metadata(self, for_env: EnvConfigSet) -> list[Requirem
209
219
# to calculate the package metadata, otherwise ourselves
210
220
of_type : str = for_env ["package" ]
211
221
reqs : list [Requirement ] | None = None
212
- if of_type == "wheel" : # wheel packages
222
+ if of_type in ( "wheel" , "editable" ) : # wheel packages
213
223
w_env = self ._wheel_build_envs .get (for_env ["wheel_build_env" ])
214
224
if w_env is not None and w_env is not self :
215
225
with w_env .display_context (self ._has_display_suspended ):
216
- reqs = w_env .get_package_dependencies () if isinstance (w_env , Pep517VirtualEnvPackager ) else []
226
+ if isinstance (w_env , Pep517VirtualEnvPackager ):
227
+ reqs = w_env .get_package_dependencies (for_env )
228
+ else :
229
+ reqs = []
217
230
if reqs is None :
218
- reqs = self .get_package_dependencies ()
231
+ reqs = self .get_package_dependencies (for_env )
219
232
extras : set [str ] = for_env ["extras" ]
220
233
deps = dependencies_with_extras (reqs , extras )
221
234
return deps
222
235
223
- def get_package_dependencies (self ) -> list [Requirement ]:
236
+ def get_package_dependencies (self , for_env : EnvConfigSet ) -> list [Requirement ]:
224
237
with self ._pkg_lock :
225
238
if self ._package_dependencies is None : # pragma: no branch
226
- self ._ensure_meta_present ()
239
+ self ._ensure_meta_present (for_env )
227
240
requires : list [str ] = cast (PathDistribution , self ._distribution_meta ).requires or []
228
241
self ._package_dependencies = [Requirement (i ) for i in requires ] # pragma: no branch
229
242
return self ._package_dependencies
230
243
231
- def _ensure_meta_present (self ) -> None :
244
+ def _ensure_meta_present (self , for_env : EnvConfigSet ) -> None :
232
245
if self ._distribution_meta is not None : # pragma: no branch
233
246
return # pragma: no cover
234
247
self .setup ()
235
- dist_info = self ._frontend .prepare_metadata_for_build_wheel (
236
- self .meta_folder ,
237
- self ._wheel_config_settings ,
238
- ).metadata
248
+ end = self ._frontend
249
+ if for_env ["package" ] == "editable" :
250
+ dist_info = end .prepare_metadata_for_build_editable (self .meta_folder , self ._wheel_config_settings ).metadata
251
+ else :
252
+ dist_info = end .prepare_metadata_for_build_wheel (self .meta_folder , self ._wheel_config_settings ).metadata
239
253
self ._distribution_meta = Distribution .at (str (dist_info ))
240
254
241
255
@property
242
256
def _wheel_config_settings (self ) -> ConfigSettings | None :
243
- return {"--global -option" : ["--bdist-dir" , str ( self . env_dir / "build" ) ]}
257
+ return {"--build -option" : []}
244
258
245
259
def requires (self ) -> tuple [Requirement , ...]:
246
260
return self ._frontend .requires
@@ -258,16 +272,17 @@ def __init__(self, root: Path, env: Pep517VirtualEnvPackager) -> None:
258
272
)
259
273
self .build_wheel = pkg_cache (self .build_wheel ) # type: ignore
260
274
self .build_sdist = pkg_cache (self .build_sdist ) # type: ignore
275
+ self .build_editable = pkg_cache (self .build_editable ) # type: ignore
261
276
262
277
@property
263
278
def backend_cmd (self ) -> Sequence [str ]:
264
279
return ["python" ] + self .backend_args
265
280
266
281
def _send (self , cmd : str , ** kwargs : Any ) -> tuple [Any , str , str ]:
267
282
try :
268
- if cmd == "prepare_metadata_for_build_wheel" :
283
+ if cmd in ( "prepare_metadata_for_build_wheel" , "prepare_metadata_for_build_editable" ) :
269
284
# given we'll build a wheel we might skip the prepare step
270
- if "wheel" in self ._tox_env .builds :
285
+ if "wheel" in self ._tox_env .builds or "editable" in self . _tox_env . builds :
271
286
result = {
272
287
"code" : 1 ,
273
288
"exc_type" : "AvoidRedundant" ,
0 commit comments