Skip to content

Commit 9af72eb

Browse files
committed
Add PEP 660 support (editables)
1 parent ae9934d commit 9af72eb

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

doc/callhooks.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@ Calling the build system
1212

1313
.. automethod:: get_requires_for_build_wheel
1414

15+
.. automethod:: get_requires_for_build_editable
16+
1517
.. automethod:: prepare_metadata_for_build_wheel
1618

19+
.. automethod:: prepare_metadata_for_build_editable
20+
1721
.. automethod:: build_sdist
1822

1923
.. automethod:: build_wheel
2024

25+
.. automethod:: build_editable
26+
2127
.. automethod:: subprocess_runner
2228

2329
Subprocess runners

pep517/in_process/_in_process.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,20 @@ def get_requires_for_build_wheel(config_settings):
114114
return hook(config_settings)
115115

116116

117+
def get_requires_for_build_editable(config_settings):
118+
"""Invoke the optional get_requires_for_build_editable hook
119+
120+
Returns [] if the hook is not defined.
121+
"""
122+
backend = _build_backend()
123+
try:
124+
hook = backend.get_requires_for_build_editable
125+
except AttributeError:
126+
return []
127+
else:
128+
return hook(config_settings)
129+
130+
117131
def prepare_metadata_for_build_wheel(
118132
metadata_directory, config_settings, _allow_fallback):
119133
"""Invoke optional prepare_metadata_for_build_wheel
@@ -134,6 +148,27 @@ def prepare_metadata_for_build_wheel(
134148
return hook(metadata_directory, config_settings)
135149

136150

151+
def prepare_metadata_for_build_editable(
152+
metadata_directory, config_settings, _allow_fallback):
153+
"""Invoke optional prepare_metadata_for_build_editable
154+
155+
Implements a fallback by building an editable wheel if the hook isn't
156+
defined, unless _allow_fallback is False in which case HookMissing is
157+
raised.
158+
"""
159+
backend = _build_backend()
160+
try:
161+
hook = backend.prepare_metadata_for_build_editable
162+
except AttributeError:
163+
if not _allow_fallback:
164+
raise HookMissing()
165+
whl_basename = backend.build_editable(metadata_directory, config_settings)
166+
return _get_wheel_metadata_from_wheel(whl_basename, metadata_directory,
167+
config_settings)
168+
else:
169+
return hook(metadata_directory, config_settings)
170+
171+
137172
WHEEL_BUILT_MARKER = 'PEP517_ALREADY_BUILT_WHEEL'
138173

139174

@@ -205,6 +240,27 @@ def build_wheel(wheel_directory, config_settings, metadata_directory=None):
205240
metadata_directory)
206241

207242

243+
def build_editable(wheel_directory, config_settings, metadata_directory=None):
244+
"""Invoke the optional build_editable hook.
245+
246+
If a wheel was already built in the
247+
prepare_metadata_for_build_editable fallback, this
248+
will copy it rather than rebuilding the wheel.
249+
"""
250+
prebuilt_whl = _find_already_built_wheel(metadata_directory)
251+
if prebuilt_whl:
252+
shutil.copy2(prebuilt_whl, wheel_directory)
253+
return os.path.basename(prebuilt_whl)
254+
255+
backend = _build_backend()
256+
try:
257+
hook = backend.build_editable
258+
except AttributeError:
259+
raise HookMissing()
260+
else:
261+
return hook(wheel_directory, config_settings, metadata_directory)
262+
263+
208264
def get_requires_for_build_sdist(config_settings):
209265
"""Invoke the optional get_requires_for_build_wheel hook
210266

pep517/wrappers.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,59 @@ def build_wheel(
207207
'metadata_directory': metadata_directory,
208208
})
209209

210+
def get_requires_for_build_editblae(self, config_settings=None):
211+
"""Identify packages required for building an editable wheel
212+
213+
Returns a list of dependency specifications, e.g.::
214+
215+
["wheel >= 0.25", "setuptools"]
216+
217+
This does not include requirements specified in pyproject.toml.
218+
It returns the result of calling the equivalently named hook in a
219+
subprocess.
220+
"""
221+
return self._call_hook('get_requires_for_build_editblae', {
222+
'config_settings': config_settings
223+
})
224+
225+
def prepare_metadata_for_build_editable(
226+
self, metadata_directory, config_settings=None,
227+
_allow_fallback=True):
228+
"""Prepare a ``*.dist-info`` folder with metadata for this project.
229+
230+
Returns the name of the newly created folder.
231+
232+
If the build backend defines a hook with this name, it will be called
233+
in a subprocess. If not, the backend will be asked to build an editable
234+
wheel, and the dist-info extracted from that (unless _allow_fallback is
235+
False).
236+
"""
237+
return self._call_hook('prepare_metadata_for_build_editable', {
238+
'metadata_directory': abspath(metadata_directory),
239+
'config_settings': config_settings,
240+
'_allow_fallback': _allow_fallback,
241+
})
242+
243+
def build_editable(
244+
self, wheel_directory, config_settings=None,
245+
metadata_directory=None):
246+
"""Build an editable wheel from this project.
247+
248+
Returns the name of the newly created file.
249+
250+
In general, this will call the 'build_editable' hook in the backend.
251+
However, if that was previously called by
252+
'prepare_metadata_for_build_editable', and the same metadata_directory
253+
is used, the previously built wheel will be copied to wheel_directory.
254+
"""
255+
if metadata_directory is not None:
256+
metadata_directory = abspath(metadata_directory)
257+
return self._call_hook('build_editable', {
258+
'wheel_directory': abspath(wheel_directory),
259+
'config_settings': config_settings,
260+
'metadata_directory': metadata_directory,
261+
})
262+
210263
def get_requires_for_build_sdist(self, config_settings=None):
211264
"""Identify packages required for building a wheel
212265

0 commit comments

Comments
 (0)