From e74b501029ea3914cb4b8281bba0f93cba9169d3 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Fri, 13 Sep 2024 17:33:33 +0200 Subject: [PATCH 1/8] Implement the test for being able to pass dist-info dir --- setuptools/build_meta.py | 5 ++++- setuptools/tests/test_bdist_wheel.py | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py index a6b85afc42..ecf434bbf3 100644 --- a/setuptools/build_meta.py +++ b/setuptools/build_meta.py @@ -417,9 +417,12 @@ def build_wheel( config_settings: _ConfigSettings = None, metadata_directory: StrPath | None = None, ): + cmd = ['bdist_wheel'] + if metadata_directory: + cmd.extend(['--dist-info-dir', metadata_directory]) with suppress_known_deprecation(): return self._build_with_temp_dir( - ['bdist_wheel'], + cmd, '.whl', wheel_directory, config_settings, diff --git a/setuptools/tests/test_bdist_wheel.py b/setuptools/tests/test_bdist_wheel.py index 8b64e90f72..a127cc1b2d 100644 --- a/setuptools/tests/test_bdist_wheel.py +++ b/setuptools/tests/test_bdist_wheel.py @@ -619,3 +619,25 @@ def _fake_import(name: str, *args, **kwargs): monkeypatch.delitem(sys.modules, "setuptools.command.bdist_wheel") import setuptools.command.bdist_wheel # noqa: F401 + + +def test_dist_info_provided(dummy_dist, monkeypatch, tmp_path): + monkeypatch.chdir(dummy_dist) + distinfo = tmp_path / "dummy_dist.dist-info" + + distinfo.mkdir() + (distinfo / "METADATA").write_text("name: helloworld", encoding="utf-8") + + # We don't control the metadata. According to PEP-517, "The hook MAY also + # create other files inside this directory, and a build frontend MUST + # preserve". + (distinfo / "FOO").write_text("bar", encoding="utf-8") + + bdist_wheel_cmd(bdist_dir=str(tmp_path), universal=True, dist_info_dir=str(distinfo)).run() + expected = { + "dummy_dist-1.0.dist-info/FOO", + "dummy_dist-1.0.dist-info/RECORD", + } + with ZipFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: + # Check that all expected files are there. + assert set(wf.namelist()).intersection(expected) == expected From bc82d73b12b8260b9b2a3736cf7f3c603e379e93 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Fri, 13 Sep 2024 17:37:56 +0200 Subject: [PATCH 2/8] Implement the desired functionality --- setuptools/command/bdist_wheel.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/setuptools/command/bdist_wheel.py b/setuptools/command/bdist_wheel.py index fa97976fef..59c162dd9e 100644 --- a/setuptools/command/bdist_wheel.py +++ b/setuptools/command/bdist_wheel.py @@ -231,6 +231,13 @@ class bdist_wheel(Command): None, "Python tag (cp32|cp33|cpNN) for abi3 wheel tag [default: false]", ), + ( + "dist-info-dir=", + None, + "directory where a pre-generated dist-info can be found (e.g. as a " + "result of calling the PEP517 'prepare_metadata_for_build_wheel' " + "method)", + ), ] boolean_options = ["keep-temp", "skip-build", "relative", "universal"] @@ -243,6 +250,7 @@ def initialize_options(self) -> None: self.format = "zip" self.keep_temp = False self.dist_dir: str | None = None + self.dist_info_dir = None self.egginfo_dir: str | None = None self.root_is_pure: bool | None = None self.skip_build = False @@ -261,8 +269,9 @@ def finalize_options(self) -> None: bdist_base = self.get_finalized_command("bdist").bdist_base self.bdist_dir = os.path.join(bdist_base, "wheel") - egg_info = cast(egg_info_cls, self.distribution.get_command_obj("egg_info")) - egg_info.ensure_finalized() # needed for correct `wheel_dist_name` + if self.dist_info_dir is None: + egg_info = self.distribution.get_command_obj("egg_info") + egg_info.ensure_finalized() # needed for correct `wheel_dist_name` self.data_dir = self.wheel_dist_name + ".data" self.plat_name_supplied = bool(self.plat_name) @@ -447,7 +456,15 @@ def run(self): f"{safer_version(self.distribution.get_version())}.dist-info" ) distinfo_dir = os.path.join(self.bdist_dir, distinfo_dirname) - self.egg2dist(self.egginfo_dir, distinfo_dir) + if self.dist_info_dir: + # Use the given dist-info directly. + shutil.copytree(self.dist_info_dir, distinfo_dir) + # Egg info is still generated, so remove it now to avoid it getting + # copied into the wheel. + shutil.rmtree(self.egginfo_dir) + else: + # Convert the generated egg-info into dist-info. + self.egg2dist(self.egginfo_dir, distinfo_dir) self.write_wheelfile(distinfo_dir) From 283ce3b9eb8720a50948f4ee938b603d2f1e97d9 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Fri, 13 Sep 2024 17:46:44 +0200 Subject: [PATCH 3/8] Add a news fragment about the work --- newsfragments/1825.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 newsfragments/1825.bugfix.rst diff --git a/newsfragments/1825.bugfix.rst b/newsfragments/1825.bugfix.rst new file mode 100644 index 0000000000..1fd1e95a4f --- /dev/null +++ b/newsfragments/1825.bugfix.rst @@ -0,0 +1 @@ +Enabled passing dist-info-dir to the bdist_wheel, and to the PEP-517 build backend. Therefore, metadata can now be injected prior to wheel building when following PEP-517 -- by :user:`pelson` From bd615ee524a3c1b68b06347958c7d92f83e8a259 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Mon, 16 Sep 2024 06:02:37 +0200 Subject: [PATCH 4/8] Test that there is no egg-info files accidentally leaking into the wheel --- newsfragments/1825.bugfix.rst | 2 +- setuptools/command/bdist_wheel.py | 1 - setuptools/tests/test_bdist_wheel.py | 11 +++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/newsfragments/1825.bugfix.rst b/newsfragments/1825.bugfix.rst index 1fd1e95a4f..99e8fdf22a 100644 --- a/newsfragments/1825.bugfix.rst +++ b/newsfragments/1825.bugfix.rst @@ -1 +1 @@ -Enabled passing dist-info-dir to the bdist_wheel, and to the PEP-517 build backend. Therefore, metadata can now be injected prior to wheel building when following PEP-517 -- by :user:`pelson` +Allow passing dist-info-dir to the bdist_wheel command, as well as to the PEP-517 build backend. Metadata can therefore now be injected prior to wheel building when following PEP-517 -- by :user:`pelson` diff --git a/setuptools/command/bdist_wheel.py b/setuptools/command/bdist_wheel.py index 59c162dd9e..a770de2e54 100644 --- a/setuptools/command/bdist_wheel.py +++ b/setuptools/command/bdist_wheel.py @@ -27,7 +27,6 @@ from .. import Command, __version__ from ..warnings import SetuptoolsDeprecationWarning -from .egg_info import egg_info as egg_info_cls from distutils import log diff --git a/setuptools/tests/test_bdist_wheel.py b/setuptools/tests/test_bdist_wheel.py index a127cc1b2d..47200d0a26 100644 --- a/setuptools/tests/test_bdist_wheel.py +++ b/setuptools/tests/test_bdist_wheel.py @@ -633,11 +633,14 @@ def test_dist_info_provided(dummy_dist, monkeypatch, tmp_path): # preserve". (distinfo / "FOO").write_text("bar", encoding="utf-8") - bdist_wheel_cmd(bdist_dir=str(tmp_path), universal=True, dist_info_dir=str(distinfo)).run() + bdist_wheel_cmd(bdist_dir=str(tmp_path), dist_info_dir=str(distinfo)).run() expected = { "dummy_dist-1.0.dist-info/FOO", "dummy_dist-1.0.dist-info/RECORD", } - with ZipFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: - # Check that all expected files are there. - assert set(wf.namelist()).intersection(expected) == expected + with ZipFile("dist/dummy_dist-1.0-py3-none-any.whl") as wf: + files_found = set(wf.namelist()) + # Check that all expected files are there. + assert expected - files_found == set() + # Make sure there is no accidental egg-info bleeding into the wheel. + assert not [path for path in files_found if 'egg-info' in str(path)] From eb81747c129f033ede333e97589ff4f8b600b6e0 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Wed, 25 Sep 2024 13:52:22 +0200 Subject: [PATCH 5/8] Restore the egg-info-cls casting --- setuptools/command/bdist_wheel.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/command/bdist_wheel.py b/setuptools/command/bdist_wheel.py index a770de2e54..83abe6e0c3 100644 --- a/setuptools/command/bdist_wheel.py +++ b/setuptools/command/bdist_wheel.py @@ -27,6 +27,7 @@ from .. import Command, __version__ from ..warnings import SetuptoolsDeprecationWarning +from .egg_info import egg_info as egg_info_cls from distutils import log @@ -269,7 +270,7 @@ def finalize_options(self) -> None: self.bdist_dir = os.path.join(bdist_base, "wheel") if self.dist_info_dir is None: - egg_info = self.distribution.get_command_obj("egg_info") + egg_info = cast(egg_info_cls, self.distribution.get_command_obj("egg_info")) egg_info.ensure_finalized() # needed for correct `wheel_dist_name` self.data_dir = self.wheel_dist_name + ".data" From 2f3b273e534965d33fce9c5576ad89c4afbd8746 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Thu, 26 Sep 2024 07:55:43 +0200 Subject: [PATCH 6/8] Update newsfragments/1825.bugfix.rst Co-authored-by: Anderson Bravalheri --- newsfragments/1825.bugfix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newsfragments/1825.bugfix.rst b/newsfragments/1825.bugfix.rst index 99e8fdf22a..226df0a936 100644 --- a/newsfragments/1825.bugfix.rst +++ b/newsfragments/1825.bugfix.rst @@ -1 +1 @@ -Allow passing dist-info-dir to the bdist_wheel command, as well as to the PEP-517 build backend. Metadata can therefore now be injected prior to wheel building when following PEP-517 -- by :user:`pelson` +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`. From cf299fcb838f388a210569df7f5419fe762f26c7 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Thu, 26 Sep 2024 13:05:05 +0200 Subject: [PATCH 7/8] Update setuptools/command/bdist_wheel.py Co-authored-by: Anderson Bravalheri --- setuptools/command/bdist_wheel.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setuptools/command/bdist_wheel.py b/setuptools/command/bdist_wheel.py index 83abe6e0c3..aeade98f6f 100644 --- a/setuptools/command/bdist_wheel.py +++ b/setuptools/command/bdist_wheel.py @@ -458,6 +458,7 @@ def run(self): distinfo_dir = os.path.join(self.bdist_dir, distinfo_dirname) if self.dist_info_dir: # Use the given dist-info directly. + log.debug(f"reusing {self.dist_info_dir}") shutil.copytree(self.dist_info_dir, distinfo_dir) # Egg info is still generated, so remove it now to avoid it getting # copied into the wheel. From fc08e7ef01fea2033e7f1c33e51704574f392ca0 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 26 Sep 2024 14:28:56 +0100 Subject: [PATCH 8/8] Fix RST in newsfragment --- newsfragments/1825.bugfix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newsfragments/1825.bugfix.rst b/newsfragments/1825.bugfix.rst index 226df0a936..ff55d18725 100644 --- a/newsfragments/1825.bugfix.rst +++ b/newsfragments/1825.bugfix.rst @@ -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`. +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`.