Skip to content

Commit 129c2bc

Browse files
authored
use tempfile.TemporaryDirectory (#337)
1 parent a63b696 commit 129c2bc

File tree

6 files changed

+88
-174
lines changed

6 files changed

+88
-174
lines changed

src/poetry/core/masonry/builders/wheel.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from functools import cached_property
1818
from io import StringIO
1919
from pathlib import Path
20+
from tempfile import TemporaryDirectory
2021
from typing import TYPE_CHECKING
2122
from typing import Any
2223
from typing import TextIO
@@ -30,7 +31,6 @@
3031
from poetry.core.masonry.utils.helpers import distribution_name
3132
from poetry.core.masonry.utils.helpers import normalize_file_permissions
3233
from poetry.core.masonry.utils.package_include import PackageInclude
33-
from poetry.core.utils.helpers import temporary_directory
3434

3535

3636
if TYPE_CHECKING:
@@ -137,7 +137,7 @@ def build(
137137
self._copy_file_scripts(zip_file)
138138

139139
if self._metadata_directory is None:
140-
with temporary_directory() as temp_dir:
140+
with TemporaryDirectory(ignore_cleanup_errors=True) as temp_dir:
141141
metadata_directory = self.prepare_metadata(Path(temp_dir))
142142
self._copy_dist_info(zip_file, metadata_directory)
143143
else:

src/poetry/core/utils/helpers.py

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,12 @@
11
from __future__ import annotations
22

3-
import shutil
4-
import stat
5-
import tempfile
6-
import time
73
import unicodedata
84

9-
from contextlib import contextmanager
105
from pathlib import Path
11-
from typing import TYPE_CHECKING
12-
from typing import Any
136

147
from packaging.utils import canonicalize_name
158

169

17-
if TYPE_CHECKING:
18-
from collections.abc import Iterator
19-
20-
2110
def combine_unicode(string: str) -> str:
2211
return unicodedata.normalize("NFC", string)
2312

@@ -26,15 +15,6 @@ def module_name(name: str) -> str:
2615
return canonicalize_name(name).replace("-", "_")
2716

2817

29-
@contextmanager
30-
def temporary_directory(*args: Any, **kwargs: Any) -> Iterator[Path]:
31-
# mypy reports an error if ignore_cleanup_errors is
32-
# specified literally in the call
33-
kwargs["ignore_cleanup_errors"] = True
34-
with tempfile.TemporaryDirectory(*args, **kwargs) as name:
35-
yield Path(name)
36-
37-
3818
def parse_requires(requires: str) -> list[str]:
3919
lines = requires.split("\n")
4020

@@ -72,42 +52,6 @@ def parse_requires(requires: str) -> list[str]:
7252
return requires_dist
7353

7454

75-
def _on_rm_error(func: Any, path: str | Path, exc_info: Any) -> None:
76-
path = Path(path)
77-
if not path.exists():
78-
return
79-
80-
path.chmod(stat.S_IWRITE)
81-
func(path)
82-
83-
84-
def robust_rmtree(path: str | Path, max_timeout: float = 1) -> None:
85-
"""
86-
Robustly tries to delete paths.
87-
Retries several times if an OSError occurs.
88-
If the final attempt fails, the Exception is propagated
89-
to the caller.
90-
"""
91-
path = Path(path) # make sure this is a Path object, not str
92-
timeout = 0.001
93-
while timeout < max_timeout:
94-
try:
95-
# both os.unlink and shutil.rmtree can throw exceptions on Windows
96-
# if the files are in use when called
97-
if path.is_symlink():
98-
path.unlink()
99-
else:
100-
shutil.rmtree(path)
101-
return # Only hits this on success
102-
except OSError:
103-
# Increase the timeout and try again
104-
time.sleep(timeout)
105-
timeout *= 2
106-
107-
# Final attempt, pass any Exceptions up to caller.
108-
shutil.rmtree(path, onerror=_on_rm_error)
109-
110-
11155
def readme_content_type(path: str | Path) -> str:
11256
suffix = Path(path).suffix
11357
if suffix == ".rst":

tests/conftest.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ def masonry_project(
8484

8585
@pytest.fixture
8686
def temporary_directory() -> Iterator[Path]:
87-
with tempfile.TemporaryDirectory(prefix="poetry-core") as tmp:
87+
with tempfile.TemporaryDirectory(
88+
prefix="poetry-core", ignore_cleanup_errors=True
89+
) as tmp:
8890
yield Path(tmp)
8991

9092

tests/masonry/test_api.py

Lines changed: 80 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55

66
from contextlib import contextmanager
77
from pathlib import Path
8+
from tempfile import TemporaryDirectory
89
from typing import TYPE_CHECKING
910

1011
import pytest
1112

1213
from poetry.core import __version__
1314
from poetry.core.masonry import api
14-
from poetry.core.utils.helpers import temporary_directory
1515
from tests.testutils import validate_sdist_contents
1616
from tests.testutils import validate_wheel_contents
1717

@@ -51,47 +51,62 @@ def test_get_requires_for_build_sdist(project: str) -> None:
5151

5252
@pytest.mark.parametrize("project", ["complete", "complete_new", "complete_dynamic"])
5353
def test_build_wheel(project: str) -> None:
54-
with temporary_directory() as tmp_dir, cwd(fixtures / project):
54+
with (
55+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
56+
cwd(fixtures / project),
57+
):
5558
filename = api.build_wheel(str(tmp_dir))
5659
validate_wheel_contents(
5760
name="my_package",
5861
version="1.2.3",
59-
path=tmp_dir / filename,
62+
path=Path(tmp_dir) / filename,
6063
files=["entry_points.txt"],
6164
)
6265

6366

6467
def test_build_wheel_with_local_version() -> None:
65-
with temporary_directory() as tmp_dir, cwd(fixtures / "complete"):
68+
with (
69+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
70+
cwd(fixtures / "complete"),
71+
):
6672
filename = api.build_wheel(
6773
str(tmp_dir), config_settings={"local-version": "some-label"}
6874
)
6975
validate_wheel_contents(
7076
name="my_package",
7177
version="1.2.3+some-label",
72-
path=tmp_dir / filename,
78+
path=Path(tmp_dir) / filename,
7379
files=["entry_points.txt"],
7480
)
7581

7682

7783
def test_build_wheel_with_include() -> None:
78-
with temporary_directory() as tmp_dir, cwd(fixtures / "with-include"):
84+
with (
85+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
86+
cwd(fixtures / "with-include"),
87+
):
7988
filename = api.build_wheel(str(tmp_dir))
8089
validate_wheel_contents(
8190
name="with_include",
8291
version="1.2.3",
83-
path=tmp_dir / filename,
92+
path=Path(tmp_dir) / filename,
8493
files=["entry_points.txt"],
8594
)
8695

8796

8897
def test_build_wheel_with_bad_path_dev_dep_succeeds() -> None:
89-
with temporary_directory() as tmp_dir, cwd(fixtures / "with_bad_path_dev_dep"):
98+
with (
99+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
100+
cwd(fixtures / "with_bad_path_dev_dep"),
101+
):
90102
api.build_wheel(str(tmp_dir))
91103

92104

93105
def test_build_wheel_with_bad_path_dep_succeeds(caplog: LogCaptureFixture) -> None:
94-
with temporary_directory() as tmp_dir, cwd(fixtures / "with_bad_path_dep"):
106+
with (
107+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
108+
cwd(fixtures / "with_bad_path_dep"),
109+
):
95110
api.build_wheel(str(tmp_dir))
96111
assert len(caplog.records) == 1
97112
record = caplog.records[0]
@@ -100,7 +115,10 @@ def test_build_wheel_with_bad_path_dep_succeeds(caplog: LogCaptureFixture) -> No
100115

101116

102117
def test_build_wheel_extended() -> None:
103-
with temporary_directory() as tmp_dir, cwd(fixtures / "extended"):
118+
with (
119+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
120+
cwd(fixtures / "extended"),
121+
):
104122
filename = api.build_wheel(str(tmp_dir))
105123
whl = Path(tmp_dir) / filename
106124
assert whl.exists()
@@ -109,47 +127,62 @@ def test_build_wheel_extended() -> None:
109127

110128
@pytest.mark.parametrize("project", ["complete", "complete_new", "complete_dynamic"])
111129
def test_build_sdist(project: str) -> None:
112-
with temporary_directory() as tmp_dir, cwd(fixtures / project):
130+
with (
131+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
132+
cwd(fixtures / project),
133+
):
113134
filename = api.build_sdist(str(tmp_dir))
114135
validate_sdist_contents(
115136
name="my-package",
116137
version="1.2.3",
117-
path=tmp_dir / filename,
138+
path=Path(tmp_dir) / filename,
118139
files=["LICENSE"],
119140
)
120141

121142

122143
def test_build_sdist_with_local_version() -> None:
123-
with temporary_directory() as tmp_dir, cwd(fixtures / "complete"):
144+
with (
145+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
146+
cwd(fixtures / "complete"),
147+
):
124148
filename = api.build_sdist(
125149
str(tmp_dir), config_settings={"local-version": "some-label"}
126150
)
127151
validate_sdist_contents(
128152
name="my-package",
129153
version="1.2.3+some-label",
130-
path=tmp_dir / filename,
154+
path=Path(tmp_dir) / filename,
131155
files=["LICENSE"],
132156
)
133157

134158

135159
def test_build_sdist_with_include() -> None:
136-
with temporary_directory() as tmp_dir, cwd(fixtures / "with-include"):
160+
with (
161+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
162+
cwd(fixtures / "with-include"),
163+
):
137164
filename = api.build_sdist(str(tmp_dir))
138165
validate_sdist_contents(
139166
name="with-include",
140167
version="1.2.3",
141-
path=tmp_dir / filename,
168+
path=Path(tmp_dir) / filename,
142169
files=["LICENSE"],
143170
)
144171

145172

146173
def test_build_sdist_with_bad_path_dev_dep_succeeds() -> None:
147-
with temporary_directory() as tmp_dir, cwd(fixtures / "with_bad_path_dev_dep"):
174+
with (
175+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
176+
cwd(fixtures / "with_bad_path_dev_dep"),
177+
):
148178
api.build_sdist(str(tmp_dir))
149179

150180

151181
def test_build_sdist_with_bad_path_dep_succeeds(caplog: LogCaptureFixture) -> None:
152-
with temporary_directory() as tmp_dir, cwd(fixtures / "with_bad_path_dep"):
182+
with (
183+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
184+
cwd(fixtures / "with_bad_path_dep"),
185+
):
153186
api.build_sdist(str(tmp_dir))
154187
assert len(caplog.records) == 1
155188
record = caplog.records[0]
@@ -222,7 +255,10 @@ def test_prepare_metadata_for_build_wheel(project: str) -> None:
222255
metadata = metadata.replace("License:", "License-Expression:").replace(
223256
"Classifier: License :: OSI Approved :: MIT License\n", ""
224257
)
225-
with temporary_directory() as tmp_dir, cwd(fixtures / project):
258+
with (
259+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
260+
cwd(fixtures / project),
261+
):
226262
dirname = api.prepare_metadata_for_build_wheel(str(tmp_dir))
227263

228264
assert dirname == "my_package-1.2.3.dist-info"
@@ -304,7 +340,10 @@ def test_prepare_metadata_for_build_wheel_with_local_version() -> None:
304340
==========
305341
306342
"""
307-
with temporary_directory() as tmp_dir, cwd(fixtures / "complete"):
343+
with (
344+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
345+
cwd(fixtures / "complete"),
346+
):
308347
dirname = api.prepare_metadata_for_build_wheel(
309348
str(tmp_dir), config_settings={"local-version": local_version}
310349
)
@@ -329,7 +368,7 @@ def test_prepare_metadata_for_build_wheel_with_local_version() -> None:
329368

330369
def test_prepare_metadata_excludes_optional_without_extras() -> None:
331370
with (
332-
temporary_directory() as tmp_dir,
371+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
333372
cwd(fixtures / "with_optional_without_extras"),
334373
):
335374
dirname = api.prepare_metadata_for_build_wheel(str(tmp_dir))
@@ -356,14 +395,20 @@ def test_prepare_metadata_excludes_optional_without_extras() -> None:
356395

357396

358397
def test_prepare_metadata_for_build_wheel_with_bad_path_dev_dep_succeeds() -> None:
359-
with temporary_directory() as tmp_dir, cwd(fixtures / "with_bad_path_dev_dep"):
398+
with (
399+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
400+
cwd(fixtures / "with_bad_path_dev_dep"),
401+
):
360402
api.prepare_metadata_for_build_wheel(str(tmp_dir))
361403

362404

363405
def test_prepare_metadata_for_build_wheel_with_bad_path_dep_succeeds(
364406
caplog: LogCaptureFixture,
365407
) -> None:
366-
with temporary_directory() as tmp_dir, cwd(fixtures / "with_bad_path_dep"):
408+
with (
409+
TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir,
410+
cwd(fixtures / "with_bad_path_dep"),
411+
):
367412
api.prepare_metadata_for_build_wheel(str(tmp_dir))
368413
assert len(caplog.records) == 1
369414
record = caplog.records[0]
@@ -374,7 +419,7 @@ def test_prepare_metadata_for_build_wheel_with_bad_path_dep_succeeds(
374419
@pytest.mark.parametrize("project", ["complete", "complete_new", "complete_dynamic"])
375420
def test_build_editable_wheel(project: str) -> None:
376421
pkg_dir = fixtures / project
377-
with temporary_directory() as tmp_dir, cwd(pkg_dir):
422+
with TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir, cwd(pkg_dir):
378423
filename = api.build_editable(str(tmp_dir))
379424
wheel_pth = Path(tmp_dir) / filename
380425

@@ -393,7 +438,7 @@ def test_build_editable_wheel(project: str) -> None:
393438

394439
def test_build_editable_wheel_with_local_version() -> None:
395440
pkg_dir = fixtures / "complete"
396-
with temporary_directory() as tmp_dir, cwd(pkg_dir):
441+
with TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir, cwd(pkg_dir):
397442
filename = api.build_editable(
398443
str(tmp_dir), config_settings={"local-version": "some-label"}
399444
)
@@ -410,10 +455,13 @@ def test_build_editable_wheel_with_local_version() -> None:
410455
def test_build_wheel_with_metadata_directory(project: str) -> None:
411456
pkg_dir = fixtures / project
412457

413-
with temporary_directory() as metadata_tmp_dir, cwd(pkg_dir):
458+
with (
459+
TemporaryDirectory(ignore_cleanup_errors=True) as metadata_tmp_dir,
460+
cwd(pkg_dir),
461+
):
414462
metadata_directory = api.prepare_metadata_for_build_wheel(str(metadata_tmp_dir))
415463

416-
with temporary_directory() as wheel_tmp_dir:
464+
with TemporaryDirectory(ignore_cleanup_errors=True) as wheel_tmp_dir:
417465
dist_info_path = Path(metadata_tmp_dir) / metadata_directory
418466
(dist_info_path / "CUSTOM").touch()
419467
filename = api.build_wheel(
@@ -438,12 +486,15 @@ def test_build_wheel_with_metadata_directory(project: str) -> None:
438486
def test_build_editable_wheel_with_metadata_directory(project: str) -> None:
439487
pkg_dir = fixtures / project
440488

441-
with temporary_directory() as metadata_tmp_dir, cwd(pkg_dir):
489+
with (
490+
TemporaryDirectory(ignore_cleanup_errors=True) as metadata_tmp_dir,
491+
cwd(pkg_dir),
492+
):
442493
metadata_directory = api.prepare_metadata_for_build_editable(
443494
str(metadata_tmp_dir)
444495
)
445496

446-
with temporary_directory() as wheel_tmp_dir:
497+
with TemporaryDirectory(ignore_cleanup_errors=True) as wheel_tmp_dir:
447498
dist_info_path = Path(metadata_tmp_dir) / metadata_directory
448499
(dist_info_path / "CUSTOM").touch()
449500
filename = api.build_editable(

0 commit comments

Comments
 (0)