Skip to content

Commit 108b218

Browse files
committed
Support passing dist-info-dir to bdist_wheel, enabling setuptools to handle prepare_metadata_for_build_wheel correctly as per PEP-517. Closes pypa#611
1 parent 0a4f40e commit 108b218

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

src/wheel/bdist_wheel.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from __future__ import annotations
88

99
import os
10+
from pathlib import Path
1011
import re
1112
import shutil
1213
import stat
@@ -22,6 +23,7 @@
2223

2324
import setuptools
2425
from setuptools import Command
26+
import setuptools.dist
2527

2628
from . import __version__ as wheel_version
2729
from .macosx_libfile import calculate_macosx_platform_tag
@@ -219,6 +221,12 @@ class bdist_wheel(Command):
219221
None,
220222
"Python tag (cp32|cp33|cpNN) for abi3 wheel tag" " (default: false)",
221223
),
224+
(
225+
"dist-info-dir=",
226+
None,
227+
"directory where a pre-generated dist-info can be found (e.g. as a "
228+
"result of calling the PEP517 'prepare_metadata_for_build_wheel' "
229+
"method)"),
222230
]
223231

224232
boolean_options = ["keep-temp", "skip-build", "relative", "universal"]
@@ -231,6 +239,7 @@ def initialize_options(self):
231239
self.format = "zip"
232240
self.keep_temp = False
233241
self.dist_dir = None
242+
self.dist_info_dir = None
234243
self.egginfo_dir = None
235244
self.root_is_pure = None
236245
self.skip_build = None
@@ -249,8 +258,9 @@ def finalize_options(self):
249258
bdist_base = self.get_finalized_command("bdist").bdist_base
250259
self.bdist_dir = os.path.join(bdist_base, "wheel")
251260

252-
egg_info = self.distribution.get_command_obj("egg_info")
253-
egg_info.ensure_finalized() # needed for correct `wheel_dist_name`
261+
if self.dist_info_dir is None:
262+
egg_info = self.distribution.get_command_obj("egg_info")
263+
egg_info.ensure_finalized() # needed for correct `wheel_dist_name`
254264

255265
self.data_dir = self.wheel_dist_name + ".data"
256266
self.plat_name_supplied = self.plat_name is not None
@@ -412,12 +422,21 @@ def run(self):
412422
)
413423

414424
self.set_undefined_options("install_egg_info", ("target", "egginfo_dir"))
425+
415426
distinfo_dirname = (
416427
f"{safer_name(self.distribution.get_name())}-"
417428
f"{safer_version(self.distribution.get_version())}.dist-info"
418429
)
419430
distinfo_dir = os.path.join(self.bdist_dir, distinfo_dirname)
420-
self.egg2dist(self.egginfo_dir, distinfo_dir)
431+
if self.dist_info_dir:
432+
# Use the given dist-info directly.
433+
shutil.copytree(self.dist_info_dir, distinfo_dir)
434+
# Egg info is still generated, so remove it now to avoid it getting
435+
# copied into the wheel.
436+
shutil.rmtree(self.egginfo_dir)
437+
else:
438+
# Convert the generated egg-info into dist-info.
439+
self.egg2dist(self.egginfo_dir, distinfo_dir)
421440

422441
self.write_wheelfile(distinfo_dir)
423442

tests/test_bdist_wheel.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,29 @@ def license_paths(self):
123123
assert "UTF-8 描述 説明" in metadata
124124

125125

126+
def test_dist_info_provided(dummy_dist, monkeypatch, tmp_path):
127+
monkeypatch.chdir(dummy_dist)
128+
distinfo = tmp_path / "dummy_dist.dist-info"
129+
distinfo.mkdir()
130+
(distinfo / 'METADATA').write_text("name: helloworld", encoding="utf-8")
131+
132+
# We don't control the metadata. According to PEP-517, "The hook MAY also
133+
# create other files inside this directory, and a build frontend MUST
134+
# preserve".
135+
(distinfo / 'FOO').write_text("bar", encoding="utf-8")
136+
subprocess.check_call(
137+
[
138+
sys.executable, "setup.py", "bdist_wheel",
139+
"-b", str(tmp_path), "--universal",
140+
"--dist-info-dir", str(distinfo),
141+
],
142+
)
143+
with WheelFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf:
144+
with wf.open("dummy_dist-1.0.dist-info/METADATA") as fh:
145+
assert fh.read() == b'name: helloworld'
146+
assert 'dummy_dist-1.0.dist-info/FOO' in list(wf.namelist())
147+
148+
126149
def test_licenses_default(dummy_dist, monkeypatch, tmp_path):
127150
monkeypatch.chdir(dummy_dist)
128151
subprocess.check_call(

0 commit comments

Comments
 (0)