Skip to content

Commit 89d3e94

Browse files
authored
Support the metadata directory (as per PEP-517) for build_wheel (pypa#4647)
2 parents 3106af0 + fc08e7e commit 89d3e94

File tree

4 files changed

+51
-4
lines changed

4 files changed

+51
-4
lines changed

newsfragments/1825.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Re-use pre-existing ``.dist-info`` dir when creating wheels via the build backend APIs (PEP 517) and the ``metadata_directory`` argument is passed -- by :user:`pelson`.

setuptools/build_meta.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,9 +417,12 @@ def build_wheel(
417417
config_settings: _ConfigSettings = None,
418418
metadata_directory: StrPath | None = None,
419419
):
420+
cmd = ['bdist_wheel']
421+
if metadata_directory:
422+
cmd.extend(['--dist-info-dir', metadata_directory])
420423
with suppress_known_deprecation():
421424
return self._build_with_temp_dir(
422-
['bdist_wheel'],
425+
cmd,
423426
'.whl',
424427
wheel_directory,
425428
config_settings,

setuptools/command/bdist_wheel.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,13 @@ class bdist_wheel(Command):
231231
None,
232232
"Python tag (cp32|cp33|cpNN) for abi3 wheel tag [default: false]",
233233
),
234+
(
235+
"dist-info-dir=",
236+
None,
237+
"directory where a pre-generated dist-info can be found (e.g. as a "
238+
"result of calling the PEP517 'prepare_metadata_for_build_wheel' "
239+
"method)",
240+
),
234241
]
235242

236243
boolean_options = ["keep-temp", "skip-build", "relative", "universal"]
@@ -243,6 +250,7 @@ def initialize_options(self) -> None:
243250
self.format = "zip"
244251
self.keep_temp = False
245252
self.dist_dir: str | None = None
253+
self.dist_info_dir = None
246254
self.egginfo_dir: str | None = None
247255
self.root_is_pure: bool | None = None
248256
self.skip_build = False
@@ -261,8 +269,9 @@ def finalize_options(self) -> None:
261269
bdist_base = self.get_finalized_command("bdist").bdist_base
262270
self.bdist_dir = os.path.join(bdist_base, "wheel")
263271

264-
egg_info = cast(egg_info_cls, self.distribution.get_command_obj("egg_info"))
265-
egg_info.ensure_finalized() # needed for correct `wheel_dist_name`
272+
if self.dist_info_dir is None:
273+
egg_info = cast(egg_info_cls, self.distribution.get_command_obj("egg_info"))
274+
egg_info.ensure_finalized() # needed for correct `wheel_dist_name`
266275

267276
self.data_dir = self.wheel_dist_name + ".data"
268277
self.plat_name_supplied = bool(self.plat_name)
@@ -447,7 +456,16 @@ def run(self):
447456
f"{safer_version(self.distribution.get_version())}.dist-info"
448457
)
449458
distinfo_dir = os.path.join(self.bdist_dir, distinfo_dirname)
450-
self.egg2dist(self.egginfo_dir, distinfo_dir)
459+
if self.dist_info_dir:
460+
# Use the given dist-info directly.
461+
log.debug(f"reusing {self.dist_info_dir}")
462+
shutil.copytree(self.dist_info_dir, distinfo_dir)
463+
# Egg info is still generated, so remove it now to avoid it getting
464+
# copied into the wheel.
465+
shutil.rmtree(self.egginfo_dir)
466+
else:
467+
# Convert the generated egg-info into dist-info.
468+
self.egg2dist(self.egginfo_dir, distinfo_dir)
451469

452470
self.write_wheelfile(distinfo_dir)
453471

setuptools/tests/test_bdist_wheel.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,3 +619,28 @@ def _fake_import(name: str, *args, **kwargs):
619619
monkeypatch.delitem(sys.modules, "setuptools.command.bdist_wheel")
620620

621621
import setuptools.command.bdist_wheel # noqa: F401
622+
623+
624+
def test_dist_info_provided(dummy_dist, monkeypatch, tmp_path):
625+
monkeypatch.chdir(dummy_dist)
626+
distinfo = tmp_path / "dummy_dist.dist-info"
627+
628+
distinfo.mkdir()
629+
(distinfo / "METADATA").write_text("name: helloworld", encoding="utf-8")
630+
631+
# We don't control the metadata. According to PEP-517, "The hook MAY also
632+
# create other files inside this directory, and a build frontend MUST
633+
# preserve".
634+
(distinfo / "FOO").write_text("bar", encoding="utf-8")
635+
636+
bdist_wheel_cmd(bdist_dir=str(tmp_path), dist_info_dir=str(distinfo)).run()
637+
expected = {
638+
"dummy_dist-1.0.dist-info/FOO",
639+
"dummy_dist-1.0.dist-info/RECORD",
640+
}
641+
with ZipFile("dist/dummy_dist-1.0-py3-none-any.whl") as wf:
642+
files_found = set(wf.namelist())
643+
# Check that all expected files are there.
644+
assert expected - files_found == set()
645+
# Make sure there is no accidental egg-info bleeding into the wheel.
646+
assert not [path for path in files_found if 'egg-info' in str(path)]

0 commit comments

Comments
 (0)