diff --git a/poetry/core/masonry/builders/wheel.py b/poetry/core/masonry/builders/wheel.py index 1d0b13e18..969de059e 100644 --- a/poetry/core/masonry/builders/wheel.py +++ b/poetry/core/masonry/builders/wheel.py @@ -78,18 +78,19 @@ def build(self): new_mode = normalize_file_permissions(st_mode) os.chmod(temp_path, new_mode) - with zipfile.ZipFile( - os.fdopen(fd, "w+b"), mode="w", compression=zipfile.ZIP_DEFLATED - ) as zip_file: - if not self._poetry.package.build_should_generate_setup(): - self._build(zip_file) - self._copy_module(zip_file) - else: - self._copy_module(zip_file) - self._build(zip_file) - - self._write_metadata(zip_file) - self._write_record(zip_file) + with os.fdopen(fd, "w+b") as fd_file: + with zipfile.ZipFile( + fd_file, mode="w", compression=zipfile.ZIP_DEFLATED + ) as zip_file: + if not self._poetry.package.build_should_generate_setup(): + self._build(zip_file) + self._copy_module(zip_file) + else: + self._copy_module(zip_file) + self._build(zip_file) + + self._write_metadata(zip_file) + self._write_record(zip_file) wheel_path = dist_dir / self.wheel_filename if wheel_path.exists(): diff --git a/tests/masonry/builders/test_wheel.py b/tests/masonry/builders/test_wheel.py index 530680d16..e300bb34c 100644 --- a/tests/masonry/builders/test_wheel.py +++ b/tests/masonry/builders/test_wheel.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +import os import shutil import zipfile @@ -284,3 +285,24 @@ def test_default_src_with_excluded_data(mocker): assert "my_package/data/data1.txt" in names assert "my_package/data/sub_data/data2.txt" not in names assert "my_package/data/sub_data/data3.txt" in names + + +def test_wheel_file_is_closed(monkeypatch): + """Confirm that wheel zip files are explicitly closed.""" + + # Using a list is a hack for Python 2.7 compatibility. + fd_file = [None] + + real_fdopen = os.fdopen + + def capturing_fdopen(*args, **kwargs): + fd_file[0] = real_fdopen(*args, **kwargs) + return fd_file[0] + + monkeypatch.setattr(os, "fdopen", capturing_fdopen) + + module_path = fixtures_dir / "module1" + WheelBuilder.make(Factory().create_poetry(module_path)) + + assert fd_file[0] is not None + assert fd_file[0].closed