diff --git a/src/wheel/bdist_wheel.py b/src/wheel/bdist_wheel.py index 4754fd11..7fcf4a37 100644 --- a/src/wheel/bdist_wheel.py +++ b/src/wheel/bdist_wheel.py @@ -15,6 +15,7 @@ import warnings from collections import OrderedDict from email.generator import BytesGenerator, Generator +from email.policy import EmailPolicy from glob import iglob from io import BytesIO from shutil import rmtree @@ -534,8 +535,13 @@ def adios(p): adios(dependency_links_path) pkg_info_path = os.path.join(distinfo_path, "METADATA") + serialization_policy = EmailPolicy( + utf8=True, + mangle_from_=False, + max_line_length=0, + ) with open(pkg_info_path, "w", encoding="utf-8") as out: - Generator(out, mangle_from_=False, maxheaderlen=0).flatten(pkg_info) + Generator(out, policy=serialization_policy).flatten(pkg_info) for license_path in self.license_paths: filename = os.path.basename(license_path) diff --git a/tests/test_bdist_wheel.py b/tests/test_bdist_wheel.py index 531d9e6f..5a6db16e 100644 --- a/tests/test_bdist_wheel.py +++ b/tests/test_bdist_wheel.py @@ -72,6 +72,45 @@ def test_unicode_record(wheel_paths): assert "åäö_日本語.py".encode() in record +UTF8_PKG_INFO = """\ +Metadata-Version: 2.1 +Name: helloworld +Version: 42 +Author-email: "John X. Ãørçeč" , Γαμα קּ 東 + + +UTF-8 描述 説明 +""" + + +def test_preserve_unicode_metadata(monkeypatch, tmp_path): + monkeypatch.chdir(tmp_path) + egginfo = tmp_path / "dummy_dist.egg-info" + distinfo = tmp_path / "dummy_dist.dist-info" + + egginfo.mkdir() + (egginfo / "PKG-INFO").write_text(UTF8_PKG_INFO, encoding="utf-8") + (egginfo / "dependency_links.txt").touch() + + class simpler_bdist_wheel(bdist_wheel): + """Avoid messing with setuptools/distutils internals""" + + def __init__(self): + pass + + @property + def license_paths(self): + return [] + + cmd_obj = simpler_bdist_wheel() + cmd_obj.egg2dist(egginfo, distinfo) + + metadata = (distinfo / "METADATA").read_text(encoding="utf-8") + assert 'Author-email: "John X. Ãørçeč"' in metadata + assert "Γαμα קּ 東 " in metadata + assert "UTF-8 描述 説明" in metadata + + def test_licenses_default(dummy_dist, monkeypatch, tmpdir): monkeypatch.chdir(dummy_dist) subprocess.check_call(