Skip to content

Commit af98abc

Browse files
Allow optional output directory for building (#527)
1 parent a917354 commit af98abc

2 files changed

Lines changed: 78 additions & 2 deletions

File tree

src/poetry/core/masonry/builder.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ def __init__(self, poetry: Poetry) -> None:
2121
"wheel": WheelBuilder,
2222
}
2323

24-
def build(self, fmt: str, executable: str | Path | None = None) -> None:
24+
def build(
25+
self,
26+
fmt: str,
27+
executable: str | Path | None = None,
28+
*,
29+
target_dir: Path | None = None,
30+
) -> None:
2531
if fmt in self._formats:
2632
builders = [self._formats[fmt]]
2733
elif fmt == "all":
@@ -30,4 +36,4 @@ def build(self, fmt: str, executable: str | Path | None = None) -> None:
3036
raise ValueError(f"Invalid format: {fmt}")
3137

3238
for builder in builders:
33-
builder(self._poetry, executable=executable).build()
39+
builder(self._poetry, executable=executable).build(target_dir)

tests/masonry/test_builder.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
from __future__ import annotations
2+
3+
import shutil
4+
5+
from contextlib import contextmanager
6+
from pathlib import Path
7+
from typing import TYPE_CHECKING
8+
from typing import Iterator
9+
10+
import pytest
11+
12+
from poetry.core.factory import Factory
13+
from poetry.core.masonry.builder import Builder
14+
15+
16+
if TYPE_CHECKING:
17+
from poetry.core.poetry import Poetry
18+
19+
20+
def get_project(name: str) -> Path:
21+
project_directory = Path(__file__).parent / "builders" / "fixtures" / name
22+
assert project_directory.is_dir()
23+
return project_directory
24+
25+
26+
@contextmanager
27+
def get_project_context(name: str) -> Iterator[Path]:
28+
project_directory = get_project(name)
29+
try:
30+
yield project_directory
31+
finally:
32+
shutil.rmtree(project_directory / "dist")
33+
34+
35+
def get_poetry(name: str) -> Poetry:
36+
return Factory().create_poetry(get_project(name))
37+
38+
39+
def get_package_glob(poetry: Poetry) -> str:
40+
return f"{poetry.package.name.replace('-', '_')}-{poetry.package.version}*"
41+
42+
43+
def test_builder_factory_raises_error_when_format_is_not_valid() -> None:
44+
with pytest.raises(ValueError, match=r"Invalid format.*"):
45+
Builder(get_poetry("complete")).build("not_valid")
46+
47+
48+
@pytest.mark.parametrize("format", ["sdist", "wheel", "all"])
49+
def test_builder_creates_places_built_files_in_specified_directory(
50+
tmp_path: Path, format: str
51+
) -> None:
52+
poetry = get_poetry("complete")
53+
Builder(poetry).build(format, target_dir=tmp_path)
54+
build_artifacts = tuple(tmp_path.glob(get_package_glob(poetry)))
55+
assert len(build_artifacts) > 0
56+
assert all(archive.exists() for archive in build_artifacts)
57+
58+
59+
@pytest.mark.parametrize("format", ["sdist", "wheel", "all"])
60+
def test_builder_creates_packages_in_dist_directory_if_no_output_is_specified(
61+
format: str,
62+
) -> None:
63+
with get_project_context("complete") as project:
64+
poetry = Factory().create_poetry(project)
65+
Builder(poetry).build(format, target_dir=None)
66+
package_directory = project / "dist"
67+
build_artifacts = tuple(package_directory.glob(get_package_glob(poetry)))
68+
assert package_directory.is_dir()
69+
assert len(build_artifacts) > 0
70+
assert all(archive.exists() for archive in build_artifacts)

0 commit comments

Comments
 (0)