diff --git a/newsfragments/4617.feature.rst b/newsfragments/4617.feature.rst new file mode 100644 index 0000000000..905e9fd497 --- /dev/null +++ b/newsfragments/4617.feature.rst @@ -0,0 +1 @@ +Deprecated ``bdist_wheel.universal`` configuration. diff --git a/setuptools/command/bdist_wheel.py b/setuptools/command/bdist_wheel.py index 8f06786659..fa97976fef 100644 --- a/setuptools/command/bdist_wheel.py +++ b/setuptools/command/bdist_wheel.py @@ -26,6 +26,7 @@ from wheel.wheelfile import WheelFile from .. import Command, __version__ +from ..warnings import SetuptoolsDeprecationWarning from .egg_info import egg_info as egg_info_cls from distutils import log @@ -205,7 +206,7 @@ class bdist_wheel(Command): "g", "Group name used when creating a tar file [default: current group]", ), - ("universal", None, "make a universal wheel [default: false]"), + ("universal", None, "*DEPRECATED* make a universal wheel [default: false]"), ( "compression=", None, @@ -278,13 +279,26 @@ def finalize_options(self) -> None: # Support legacy [wheel] section for setting universal wheel = self.distribution.get_option_dict("wheel") - if "universal" in wheel: + if "universal" in wheel: # pragma: no cover # please don't define this in your global configs log.warn("The [wheel] section is deprecated. Use [bdist_wheel] instead.") val = wheel["universal"][1].strip() if val.lower() in ("1", "true", "yes"): self.universal = True + if self.universal: + SetuptoolsDeprecationWarning.emit( + "bdist_wheel.universal is deprecated", + """ + With Python 2.7 end-of-life, support for building universal wheels + (i.e., wheels that support both Python 2 and Python 3) + is being obviated. + Please discontinue using this option, or if you still need it, + file an issue with pypa/setuptools describing your use case. + """, + due_date=(2025, 8, 30), # Introduced in 2024-08-30 + ) + if self.build_number is not None and not self.build_number[:1].isdigit(): raise ValueError("Build tag (build-number) must start with a digit.") diff --git a/setuptools/tests/test_bdist_wheel.py b/setuptools/tests/test_bdist_wheel.py index a1e3d9a73e..8b64e90f72 100644 --- a/setuptools/tests/test_bdist_wheel.py +++ b/setuptools/tests/test_bdist_wheel.py @@ -26,6 +26,7 @@ remove_readonly_exc, ) from setuptools.dist import Distribution +from setuptools.warnings import SetuptoolsDeprecationWarning from distutils.core import run_setup @@ -123,7 +124,6 @@ ) """ ), - "setup.cfg": "[bdist_wheel]\nuniversal=1", "headersdist.py": "", "header.h": "", }, @@ -300,8 +300,8 @@ def license_paths(self): def test_licenses_default(dummy_dist, monkeypatch, tmp_path): monkeypatch.chdir(dummy_dist) - bdist_wheel_cmd(bdist_dir=str(tmp_path), universal=True).run() - with ZipFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: + bdist_wheel_cmd(bdist_dir=str(tmp_path)).run() + with ZipFile("dist/dummy_dist-1.0-py3-none-any.whl") as wf: license_files = { "dummy_dist-1.0.dist-info/" + fname for fname in DEFAULT_LICENSE_FILES } @@ -314,9 +314,9 @@ def test_licenses_deprecated(dummy_dist, monkeypatch, tmp_path): ) monkeypatch.chdir(dummy_dist) - bdist_wheel_cmd(bdist_dir=str(tmp_path), universal=True).run() + bdist_wheel_cmd(bdist_dir=str(tmp_path)).run() - with ZipFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: + with ZipFile("dist/dummy_dist-1.0-py3-none-any.whl") as wf: license_files = {"dummy_dist-1.0.dist-info/DUMMYFILE"} assert set(wf.namelist()) == DEFAULT_FILES | license_files @@ -337,8 +337,8 @@ def test_licenses_deprecated(dummy_dist, monkeypatch, tmp_path): def test_licenses_override(dummy_dist, monkeypatch, tmp_path, config_file, config): dummy_dist.joinpath(config_file).write_text(config, encoding="utf-8") monkeypatch.chdir(dummy_dist) - bdist_wheel_cmd(bdist_dir=str(tmp_path), universal=True).run() - with ZipFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: + bdist_wheel_cmd(bdist_dir=str(tmp_path)).run() + with ZipFile("dist/dummy_dist-1.0-py3-none-any.whl") as wf: license_files = { "dummy_dist-1.0.dist-info/" + fname for fname in {"DUMMYFILE", "LICENSE"} } @@ -350,20 +350,29 @@ def test_licenses_disabled(dummy_dist, monkeypatch, tmp_path): "[metadata]\nlicense_files=\n", encoding="utf-8" ) monkeypatch.chdir(dummy_dist) - bdist_wheel_cmd(bdist_dir=str(tmp_path), universal=True).run() - with ZipFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: + bdist_wheel_cmd(bdist_dir=str(tmp_path)).run() + with ZipFile("dist/dummy_dist-1.0-py3-none-any.whl") as wf: assert set(wf.namelist()) == DEFAULT_FILES def test_build_number(dummy_dist, monkeypatch, tmp_path): monkeypatch.chdir(dummy_dist) - bdist_wheel_cmd(bdist_dir=str(tmp_path), build_number="2", universal=True).run() - with ZipFile("dist/dummy_dist-1.0-2-py2.py3-none-any.whl") as wf: + bdist_wheel_cmd(bdist_dir=str(tmp_path), build_number="2").run() + with ZipFile("dist/dummy_dist-1.0-2-py3-none-any.whl") as wf: filenames = set(wf.namelist()) assert "dummy_dist-1.0.dist-info/RECORD" in filenames assert "dummy_dist-1.0.dist-info/METADATA" in filenames +def test_universal_deprecated(dummy_dist, monkeypatch, tmp_path): + monkeypatch.chdir(dummy_dist) + with pytest.warns(SetuptoolsDeprecationWarning, match=".*universal is deprecated"): + bdist_wheel_cmd(bdist_dir=str(tmp_path), universal=True).run() + + # For now we still respect the option + assert os.path.exists("dist/dummy_dist-1.0-py2.py3-none-any.whl") + + EXTENSION_EXAMPLE = """\ #include @@ -431,8 +440,8 @@ def test_build_from_readonly_tree(dummy_dist, monkeypatch, tmp_path): ) def test_compression(dummy_dist, monkeypatch, tmp_path, option, compress_type): monkeypatch.chdir(dummy_dist) - bdist_wheel_cmd(bdist_dir=str(tmp_path), universal=True, compression=option).run() - with ZipFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: + bdist_wheel_cmd(bdist_dir=str(tmp_path), compression=option).run() + with ZipFile("dist/dummy_dist-1.0-py3-none-any.whl") as wf: filenames = set(wf.namelist()) assert "dummy_dist-1.0.dist-info/RECORD" in filenames assert "dummy_dist-1.0.dist-info/METADATA" in filenames @@ -451,8 +460,8 @@ def test_wheelfile_line_endings(wheel_paths): def test_unix_epoch_timestamps(dummy_dist, monkeypatch, tmp_path): monkeypatch.setenv("SOURCE_DATE_EPOCH", "0") monkeypatch.chdir(dummy_dist) - bdist_wheel_cmd(bdist_dir=str(tmp_path), build_number="2a", universal=True).run() - with ZipFile("dist/dummy_dist-1.0-2a-py2.py3-none-any.whl") as wf: + bdist_wheel_cmd(bdist_dir=str(tmp_path), build_number="2a").run() + with ZipFile("dist/dummy_dist-1.0-2a-py3-none-any.whl") as wf: for zinfo in wf.filelist: assert zinfo.date_time >= (1980, 1, 1, 0, 0, 0) # min epoch is used diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py index cfd4cd453a..53095afb52 100644 --- a/setuptools/tests/test_build_meta.py +++ b/setuptools/tests/test_build_meta.py @@ -358,9 +358,6 @@ def test_build_with_pyproject_config(self, tmpdir, setup_script): [tool.distutils.sdist] formats = "gztar" - - [tool.distutils.bdist_wheel] - universal = true """ ), "MANIFEST.in": DALS(