From b0225ed5f5847162a1c8b28fa1c7429cc1d0f015 Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:09:41 +0000 Subject: [PATCH 01/11] add output to build command --- src/poetry/console/commands/build.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/poetry/console/commands/build.py b/src/poetry/console/commands/build.py index 0d1bd15af45..bd32651c73e 100644 --- a/src/poetry/console/commands/build.py +++ b/src/poetry/console/commands/build.py @@ -1,4 +1,5 @@ from __future__ import annotations +from pathlib import Path from typing import TYPE_CHECKING @@ -17,7 +18,14 @@ class BuildCommand(EnvCommand): description = "Builds a package, as a tarball and a wheel by default." options = [ - option("format", "f", "Limit the format to either sdist or wheel.", flag=False) + option("format", "f", "Limit the format to either sdist or wheel.", flag=False), + option( + "output", + "o", + "Set output directory for build artifacts. Default is `dist`.", + default="dist", + flag=False, + ), ] loggers = [ @@ -48,11 +56,14 @@ def _build( def handle(self) -> int: with build_environment(poetry=self.poetry, env=self.env, io=self.io) as env: fmt = self.option("format") or "all" + dist_dir = Path(self.option("output")) package = self.poetry.package self.line( f"Building {package.pretty_name} ({package.version})" ) - self._build(fmt, executable=env.python) + if not dist_dir.is_absolute(): + dist_dir = self.poetry.pyproject_path.parent / dist_dir + self._build(fmt, executable=env.python, target_dir=dist_dir) return 0 From de6d1b000b93b9702cf10f6fc80a8f0fa3c46a5f Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:09:41 +0000 Subject: [PATCH 02/11] add test for build with output option --- src/poetry/console/commands/build.py | 1 + tests/console/commands/test_build.py | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/poetry/console/commands/build.py b/src/poetry/console/commands/build.py index bd32651c73e..a9d056896b3 100644 --- a/src/poetry/console/commands/build.py +++ b/src/poetry/console/commands/build.py @@ -1,4 +1,5 @@ from __future__ import annotations + from pathlib import Path from typing import TYPE_CHECKING diff --git a/tests/console/commands/test_build.py b/tests/console/commands/test_build.py index 3b378d1e4e5..c04717ea7b7 100644 --- a/tests/console/commands/test_build.py +++ b/tests/console/commands/test_build.py @@ -67,6 +67,7 @@ def test_build_with_multiple_readme_files( tmp_path: Path, tmp_venv: VirtualEnv, command_tester_factory: CommandTesterFactory, + output_dir: str, ) -> None: source_dir = fixture_dir("with_multiple_readme_files") target_dir = tmp_path / "project" @@ -75,9 +76,16 @@ def test_build_with_multiple_readme_files( poetry = Factory().create_poetry(target_dir) tester = command_tester_factory("build", poetry, environment=tmp_venv) - tester.execute() + if output_dir is None: + tester.execute() + build_dir = target_dir / "dist" + elif output_dir == "absolute": + tester.execute(f"--output {target_dir / 'tmp/dist'}") + build_dir = target_dir / "tmp/dist" + else: + tester.execute(f"--output {output_dir}") + build_dir = target_dir / output_dir - build_dir = target_dir / "dist" assert build_dir.exists() sdist_file = build_dir / "my_package-0.1.tar.gz" From bfa13a74392f6961b82cb858e82acbde2fc8081d Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:09:41 +0000 Subject: [PATCH 03/11] update documentation --- docs/cli.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/cli.md b/docs/cli.md index f77d2f851e7..579a1fbe829 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -535,6 +535,7 @@ Note that, at the moment, only pure python wheels are supported. ### Options * `--format (-f)`: Limit the format to either `wheel` or `sdist`. +* `--output (-o)`: Set output directory for build artifacts. Default is `dist`. ## publish @@ -560,6 +561,7 @@ Should match a repository name set by the [`config`](#config) command. * `--password (-p)`: The password to access the repository. * `--cert`: Certificate authority to access the repository. * `--client-cert`: Client certificate to access the repository. +* `--dist-dir`: Dist directory where built artifact is stored. Default is `dist`. * `--build`: Build the package before publishing. * `--dry-run`: Perform all actions except upload the package. * `--skip-existing`: Ignore errors from files already existing in the repository. From ca6b0e2948f083b73715728b2f2a50faf4c5f090 Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:09:41 +0000 Subject: [PATCH 04/11] add dist-dir option to publish command --- src/poetry/console/commands/publish.py | 10 +++++++++- src/poetry/publishing/uploader.py | 13 +++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/poetry/console/commands/publish.py b/src/poetry/console/commands/publish.py index a53df8208dd..77f27dda15e 100644 --- a/src/poetry/console/commands/publish.py +++ b/src/poetry/console/commands/publish.py @@ -26,6 +26,13 @@ class PublishCommand(Command): "Client certificate to access the repository.", flag=False, ), + option( + "dist-dir", + None, + "Dist directory where built artifact is stored. Default is `dist`.", + default="dist", + flag=False, + ), option("build", None, "Build the package before publishing."), option("dry-run", None, "Perform all actions except upload the package."), option( @@ -61,7 +68,8 @@ def handle(self) -> int: return 1 - self.call("build") + output_dir = self.io.input.options["dist-dir"] + self.call("build", args=f"--output {output_dir}") files = publisher.files if not files: diff --git a/src/poetry/publishing/uploader.py b/src/poetry/publishing/uploader.py index e9b22561b92..dc74b34931a 100644 --- a/src/poetry/publishing/uploader.py +++ b/src/poetry/publishing/uploader.py @@ -61,9 +61,18 @@ def user_agent(self) -> str: agent: str = user_agent("poetry", __version__) return agent + @property + def dist_dir(self) -> Path: + dist_dir = Path(self._io.input.options["dist-dir"]) + + if not dist_dir.is_absolute(): + dist_dir = self._poetry.file.path.parent / dist_dir + + return dist_dir + @property def files(self) -> list[Path]: - dist = self._poetry.file.path.parent / "dist" + dist = self.dist_dir version = self._package.version.to_string() escaped_name = distribution_name(self._package.name) @@ -275,7 +284,7 @@ def _register(self, session: requests.Session, url: str) -> requests.Response: """ Register a package to a repository. """ - dist = self._poetry.file.path.parent / "dist" + dist = self.dist_dir escaped_name = distribution_name(self._package.name) file = dist / f"{escaped_name}-{self._package.version.to_string()}.tar.gz" From ef58af13aaee79156e2f2614bd1ed3094a696694 Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:09:41 +0000 Subject: [PATCH 05/11] add with_multiple_dist_dir fixture --- .../with_multiple_dist_dir/README.rst | 2 + .../simple_project-1.2.3-py2.py3-none-any.whl | Bin 0 -> 1320 bytes .../dist/simple_project-1.2.3.tar.gz | Bin 0 -> 1106 bytes .../simple_project-1.2.3-py2.py3-none-any.whl | Bin 0 -> 1320 bytes .../dist/simple_project-1.2.3.tar.gz | Bin 0 -> 1106 bytes .../with_multiple_dist_dir/pyproject.toml | 35 ++++++++++++++++++ .../simple_project/__init__.py | 0 7 files changed, 37 insertions(+) create mode 100644 tests/fixtures/with_multiple_dist_dir/README.rst create mode 100644 tests/fixtures/with_multiple_dist_dir/dist/simple_project-1.2.3-py2.py3-none-any.whl create mode 100644 tests/fixtures/with_multiple_dist_dir/dist/simple_project-1.2.3.tar.gz create mode 100644 tests/fixtures/with_multiple_dist_dir/other_dist/dist/simple_project-1.2.3-py2.py3-none-any.whl create mode 100644 tests/fixtures/with_multiple_dist_dir/other_dist/dist/simple_project-1.2.3.tar.gz create mode 100644 tests/fixtures/with_multiple_dist_dir/pyproject.toml create mode 100644 tests/fixtures/with_multiple_dist_dir/simple_project/__init__.py diff --git a/tests/fixtures/with_multiple_dist_dir/README.rst b/tests/fixtures/with_multiple_dist_dir/README.rst new file mode 100644 index 00000000000..f7fe15470f9 --- /dev/null +++ b/tests/fixtures/with_multiple_dist_dir/README.rst @@ -0,0 +1,2 @@ +My Package +========== diff --git a/tests/fixtures/with_multiple_dist_dir/dist/simple_project-1.2.3-py2.py3-none-any.whl b/tests/fixtures/with_multiple_dist_dir/dist/simple_project-1.2.3-py2.py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..fcdeda3133860f7a41040e0953be83034d01145f GIT binary patch literal 1320 zcmWIWW@Zs#U|`??VnrZkU|<513=C30x;QhpASX4xpeR2pHMvATK0Y%qvm`!Vub`5d zAplvYM@^pYvv8n}NFY|h(5Y*vXQXGWmy%grqMMnQmaiY~;p*zcd&-fkK|z4^!rtW{ zn3SWe^#$H4ExN`wpDW4DEwvm`6-N>XJOp~G}oyk*lXPObG5#*WWk@{`yV1s9qYzEQ?elykxsK41Y&2W}A^T~6C!g167 z-2T=U|EnbV`-0v7x7-e>Q;lR_)3n9x?aAqvLVb6w>AN5OI>2z6{y8_TwB(}*Z(W==luI(_)Q!&nz;>Z%q|0?*9aKZs)VCC$ko|D$ffn% z-l8T028IWB(>(=}7aEj2Q1@DSfk}{WnvBPUB~6x0wy!Uj7rl7GUGrVj?gaPZqFr2N zv#wA1H1YhDtWV-A_PMqF{PyY9V;3&%g3VGvpX@{~aM*5B(fKRaV=*Z)@a^{6ZEyM< z;#bzo-O2E{ouwOY{3N+NR-Exzdwb7wySHxP5`Hn;uGXHK-nC<=#2e^+p@?tBR)>y!lzn9LWgCBBW%jf$D$`EwD8_v2D|n5o-6X;SpSZ5 z!^O*$U3<@8VNdu9O#F;YBFwmRG%#quU`Zp0!kxd-%)!Xt5K|Z!8W^oG%)y@9(M?3p ymusw3=9CGeCVeD literal 0 HcmV?d00001 diff --git a/tests/fixtures/with_multiple_dist_dir/dist/simple_project-1.2.3.tar.gz b/tests/fixtures/with_multiple_dist_dir/dist/simple_project-1.2.3.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..149aa9527c577a1828a5a3114377960fd1e41a88 GIT binary patch literal 1106 zcmV-Y1g-lYiwFpPU6EV@|8r?=aBO8QaB^>IWn*+LF)lJLGcI&tascgF+j84B5cM;@ z0%ac9YD9<^QSxxAOx)UOJh2ju<@Uu^IW!5&s7ZnaKqs1{{hxkEf2;s6x;gSxX{=6c z?u&rME{N;y!4c}9&Wlm-{uK@)%=R8c%u+V}nx@lTl$GAHx~{zk-|y`}axMZUKmVmC z`IU&h4--KWJg{8b?OS%&>7m}fZS}2vu-C|=7fzBa#zw~IZ#Wc&g>2+>PLB=_hewEU z@x|_cuiM>x|Lxw|{qNen-X1iY`~ToFoWW5L-UL$&26Jg{{*w{ZPpUtW|5;Tb)I{#aiWv|_T*R{+h|L;Q11*I{{C>Crs0cnt6IDp#f zsnEbJW}MJeH5DgB0}VkiFL0?sgg)261jHo7DK7>yJU-I^U@}3KgIl0eslJvU&LnzK4c9_s-0O78*`P&_ zn)J>nCxWusvf-47>--XhH0kh&@GKCRRo-%jG|Us6ilCn3#_l`Pl*_T);MqIMqGHNg zR-h`9PPI1FBAnqg!f7~DwdxBK0Kz!noLmvSyiR8{BO&xWIHp(PUBECr#J4!6nHr7K z|B#b7f@gB$xYqucJ}2ao1&m;>Dx;a)niLLcl*gE>>`Ahv9$L z%T~W{^&9;6|Ls2(dG@)x{TcZG&i;4hQ?%LtUC1+NvRf|b-_g~IU>1V<%WIRYAtWvcMV2(jQM}``X}S~ z&C9ntivO;){{N5DH?1cA??Q%H1S)bEzm&1ngEq3j8ySW@xOz6g+@d%nV4NpOz-Eea zSPQq{mDCuDmGR)lI0p`jpefz&gw?9aDB`Ic#wVgFcwKQVb^Md*tG!@Z+U4g!#c6P( zWIR0hAHpE`aZc7KI;EtiJP*DdAH#!8F48TIRDF1SRyVJ>j2NA=AW7s%;YpBAbH!RM z$QW6&x3x$8Ej^rV?NM)QkJT}4LuPH~cn_lmMpZcb`Siqths#7>8{SXjt-7AhX~Tuz YJ)~ii4I62sk*`Sp0Yvm`6-N>XJOp~G}oyk*lXPObG5#*WWk@{`yV1s9qYzEQ?elykxsK41Y&2W}A^T~6C!g167 z-2T=U|EnbV`-0v7x7-e>Q;lR_)3n9x?aAqvLVb6w>AN5OI>2z6{y8_TwB(}*Z(W==luI(_)Q!&nz;>Z%q|0?*9aKZs)VCC$ko|D$ffn% z-l8T028IWB(>(=}7aEj2Q1@DSfk}{WnvBPUB~6x0wy!Uj7rl7GUGrVj?gaPZqFr2N zv#wA1H1YhDtWV-A_PMqF{PyY9V;3&%g3VGvpX@{~aM*5B(fKRaV=*Z)@a^{6ZEyM< z;#bzo-O2E{ouwOY{3N+NR-Exzdwb7wySHxP5`Hn;uGXHK-nC<=#2e^+p@?tBR)>y!lzn9LWgCBBW%jf$D$`EwD8_v2D|n5o-6X;SpSZ5 z!^O*$U3<@8VNdu9O#F;YBFwmRG%#quU`Zp0!kxd-%)!Xt5K|Z!8W^oG%)y@9(M?3p ymusw3=9CGeCVeD literal 0 HcmV?d00001 diff --git a/tests/fixtures/with_multiple_dist_dir/other_dist/dist/simple_project-1.2.3.tar.gz b/tests/fixtures/with_multiple_dist_dir/other_dist/dist/simple_project-1.2.3.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..149aa9527c577a1828a5a3114377960fd1e41a88 GIT binary patch literal 1106 zcmV-Y1g-lYiwFpPU6EV@|8r?=aBO8QaB^>IWn*+LF)lJLGcI&tascgF+j84B5cM;@ z0%ac9YD9<^QSxxAOx)UOJh2ju<@Uu^IW!5&s7ZnaKqs1{{hxkEf2;s6x;gSxX{=6c z?u&rME{N;y!4c}9&Wlm-{uK@)%=R8c%u+V}nx@lTl$GAHx~{zk-|y`}axMZUKmVmC z`IU&h4--KWJg{8b?OS%&>7m}fZS}2vu-C|=7fzBa#zw~IZ#Wc&g>2+>PLB=_hewEU z@x|_cuiM>x|Lxw|{qNen-X1iY`~ToFoWW5L-UL$&26Jg{{*w{ZPpUtW|5;Tb)I{#aiWv|_T*R{+h|L;Q11*I{{C>Crs0cnt6IDp#f zsnEbJW}MJeH5DgB0}VkiFL0?sgg)261jHo7DK7>yJU-I^U@}3KgIl0eslJvU&LnzK4c9_s-0O78*`P&_ zn)J>nCxWusvf-47>--XhH0kh&@GKCRRo-%jG|Us6ilCn3#_l`Pl*_T);MqIMqGHNg zR-h`9PPI1FBAnqg!f7~DwdxBK0Kz!noLmvSyiR8{BO&xWIHp(PUBECr#J4!6nHr7K z|B#b7f@gB$xYqucJ}2ao1&m;>Dx;a)niLLcl*gE>>`Ahv9$L z%T~W{^&9;6|Ls2(dG@)x{TcZG&i;4hQ?%LtUC1+NvRf|b-_g~IU>1V<%WIRYAtWvcMV2(jQM}``X}S~ z&C9ntivO;){{N5DH?1cA??Q%H1S)bEzm&1ngEq3j8ySW@xOz6g+@d%nV4NpOz-Eea zSPQq{mDCuDmGR)lI0p`jpefz&gw?9aDB`Ic#wVgFcwKQVb^Md*tG!@Z+U4g!#c6P( zWIR0hAHpE`aZc7KI;EtiJP*DdAH#!8F48TIRDF1SRyVJ>j2NA=AW7s%;YpBAbH!RM z$QW6&x3x$8Ej^rV?NM)QkJT}4LuPH~cn_lmMpZcb`Siqths#7>8{SXjt-7AhX~Tuz YJ)~ii4I62sk*`Sp0Y" +] +license = "MIT" + +readme = ["README.rst"] + +homepage = "https://python-poetry.org" +repository = "https://github.com/python-poetry/poetry" +documentation = "https://python-poetry.org/docs" + +keywords = ["packaging", "dependency", "poetry"] + +classifiers = [ + "Topic :: Software Development :: Build Tools", + "Topic :: Software Development :: Libraries :: Python Modules" +] + +# Requirements +[tool.poetry.dependencies] +python = "~2.7 || ^3.4" + +[tool.poetry.scripts] +foo = "foo:bar" +baz = "bar:baz.boom.bim" +fox = "fuz.foo:bar.baz" + + +[build-system] +requires = ["poetry-core>=1.1.0a7"] +build-backend = "poetry.core.masonry.api" diff --git a/tests/fixtures/with_multiple_dist_dir/simple_project/__init__.py b/tests/fixtures/with_multiple_dist_dir/simple_project/__init__.py new file mode 100644 index 00000000000..e69de29bb2d From 342ae6c5cc2af1050f7a8711235e030d0a0151da Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:09:41 +0000 Subject: [PATCH 06/11] update test publish --- tests/console/commands/test_publish.py | 80 ++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tests/console/commands/test_publish.py b/tests/console/commands/test_publish.py index 5f230c01ff3..8bb185d6c39 100644 --- a/tests/console/commands/test_publish.py +++ b/tests/console/commands/test_publish.py @@ -1,5 +1,7 @@ from __future__ import annotations +import shutil + from pathlib import Path from typing import TYPE_CHECKING from typing import Any @@ -7,6 +9,7 @@ import pytest import requests +from poetry.factory import Factory from poetry.publishing.uploader import UploadError @@ -16,7 +19,10 @@ from cleo.testers.application_tester import ApplicationTester from pytest_mock import MockerFixture + from poetry.utils.env import VirtualEnv from tests.helpers import PoetryTestApplication + from tests.types import CommandTesterFactory + from tests.types import FixtureDirGetter def test_publish_returns_non_zero_code_for_upload_errors( @@ -130,3 +136,77 @@ def test_skip_existing_output( error = app_tester.io.fetch_error() assert "- Uploading simple_project-1.2.3.tar.gz File exists. Skipping" in error + + +@pytest.mark.parametrize("dist_dir", [None, "dist", "other_dist/dist", "absolute"]) +def test_publish_dist_dir_option( + http: type[httpretty.httpretty], + fixture_dir: FixtureDirGetter, + tmp_path: Path, + tmp_venv: VirtualEnv, + command_tester_factory: CommandTesterFactory, + dist_dir: str | None, +) -> None: + source_dir = fixture_dir("with_multiple_dist_dir") + target_dir = tmp_path / "project" + shutil.copytree(str(source_dir), str(target_dir)) + + http.register_uri( + http.POST, "https://upload.pypi.org/legacy/", status=409, body="Conflict" + ) + + poetry = Factory().create_poetry(target_dir) + tester = command_tester_factory("publish", poetry, environment=tmp_venv) + + if dist_dir is None: + exit_code = tester.execute("--dry-run") + elif dist_dir == "absolute": + exit_code = tester.execute(f"--dist-dir {target_dir / 'dist'} --dry-run") + else: + exit_code = tester.execute(f"--dist-dir {dist_dir} --dry-run") + + assert exit_code == 0 + + output = tester.io.fetch_output() + error = tester.io.fetch_error() + + assert "Publishing simple-project (1.2.3) to PyPI" in output + assert "- Uploading simple_project-1.2.3.tar.gz" in error + assert "- Uploading simple_project-1.2.3-py2.py3-none-any.whl" in error + + +@pytest.mark.parametrize("dist_dir", ["../dist", "tmp/dist", "absolute"]) +def test_publish_dist_dir_and_build_options( + http: type[httpretty.httpretty], + fixture_dir: FixtureDirGetter, + tmp_path: Path, + tmp_venv: VirtualEnv, + command_tester_factory: CommandTesterFactory, + dist_dir: str | None, +) -> None: + source_dir = fixture_dir("with_multiple_dist_dir") + target_dir = tmp_path / "project" + shutil.copytree(str(source_dir), str(target_dir)) + + http.register_uri( + http.POST, "https://upload.pypi.org/legacy/", status=409, body="Conflict" + ) + + poetry = Factory().create_poetry(target_dir) + tester = command_tester_factory("publish", poetry, environment=tmp_venv) + + if dist_dir == "absolute": + exit_code = tester.execute( + f"--dist-dir {target_dir / 'test/dist'} --dry-run --build" + ) + else: + exit_code = tester.execute(f"--dist-dir {dist_dir} --dry-run --build") + + assert exit_code == 0 + + output = tester.io.fetch_output() + error = tester.io.fetch_error() + + assert "Publishing simple-project (1.2.3) to PyPI" in output + assert "- Uploading simple_project-1.2.3.tar.gz" in error + assert "- Uploading simple_project-1.2.3-py2.py3-none-any.whl" in error From c692cc34a59c82461cb83e2443325eef55732f7a Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:09:41 +0000 Subject: [PATCH 07/11] fix uploader when runned without publish --- docs/cli.md | 2 +- src/poetry/console/commands/publish.py | 2 +- src/poetry/publishing/uploader.py | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/cli.md b/docs/cli.md index 579a1fbe829..5ea0b16051f 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -561,7 +561,7 @@ Should match a repository name set by the [`config`](#config) command. * `--password (-p)`: The password to access the repository. * `--cert`: Certificate authority to access the repository. * `--client-cert`: Client certificate to access the repository. -* `--dist-dir`: Dist directory where built artifact is stored. Default is `dist`. +* `--dist-dir`: Dist directory where built artifact are stored. Default is `dist`. * `--build`: Build the package before publishing. * `--dry-run`: Perform all actions except upload the package. * `--skip-existing`: Ignore errors from files already existing in the repository. diff --git a/src/poetry/console/commands/publish.py b/src/poetry/console/commands/publish.py index 77f27dda15e..32239583693 100644 --- a/src/poetry/console/commands/publish.py +++ b/src/poetry/console/commands/publish.py @@ -29,7 +29,7 @@ class PublishCommand(Command): option( "dist-dir", None, - "Dist directory where built artifact is stored. Default is `dist`.", + "Dist directory where built artifact are stored. Default is `dist`.", default="dist", flag=False, ), diff --git a/src/poetry/publishing/uploader.py b/src/poetry/publishing/uploader.py index dc74b34931a..1efcb5d2ecd 100644 --- a/src/poetry/publishing/uploader.py +++ b/src/poetry/publishing/uploader.py @@ -63,7 +63,10 @@ def user_agent(self) -> str: @property def dist_dir(self) -> Path: - dist_dir = Path(self._io.input.options["dist-dir"]) + io_dist_dir = "dist" + if "dist-dir" in self._io.input.options: # Option comes with publish command. + io_dist_dir = self._io.input.options["dist-dir"] + dist_dir = Path(io_dist_dir) if not dist_dir.is_absolute(): dist_dir = self._poetry.file.path.parent / dist_dir From 097563e14023e267ee9b34995f1ef0107ba71798 Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:09:41 +0000 Subject: [PATCH 08/11] make dist-dir optional argument of init Uploader --- src/poetry/console/commands/publish.py | 7 ++++--- src/poetry/publishing/publisher.py | 4 ++-- src/poetry/publishing/uploader.py | 18 +++++++++--------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/poetry/console/commands/publish.py b/src/poetry/console/commands/publish.py index 32239583693..18d4cb0f456 100644 --- a/src/poetry/console/commands/publish.py +++ b/src/poetry/console/commands/publish.py @@ -56,7 +56,9 @@ class PublishCommand(Command): def handle(self) -> int: from poetry.publishing.publisher import Publisher - publisher = Publisher(self.poetry, self.io) + dist_dir = self.option("dist-dir") + + publisher = Publisher(self.poetry, self.io, Path(dist_dir)) # Building package first, if told if self.option("build"): @@ -68,8 +70,7 @@ def handle(self) -> int: return 1 - output_dir = self.io.input.options["dist-dir"] - self.call("build", args=f"--output {output_dir}") + self.call("build", args=f"--output {dist_dir}") files = publisher.files if not files: diff --git a/src/poetry/publishing/publisher.py b/src/poetry/publishing/publisher.py index a5335258041..a009e7ab9af 100644 --- a/src/poetry/publishing/publisher.py +++ b/src/poetry/publishing/publisher.py @@ -23,11 +23,11 @@ class Publisher: Registers and publishes packages to remote repositories. """ - def __init__(self, poetry: Poetry, io: IO) -> None: + def __init__(self, poetry: Poetry, io: IO, dist_dir: Path | None = None) -> None: self._poetry = poetry self._package = poetry.package self._io = io - self._uploader = Uploader(poetry, io) + self._uploader = Uploader(poetry, io, dist_dir) self._authenticator = Authenticator(poetry.config, self._io) @property diff --git a/src/poetry/publishing/uploader.py b/src/poetry/publishing/uploader.py index 1efcb5d2ecd..972e376e0bf 100644 --- a/src/poetry/publishing/uploader.py +++ b/src/poetry/publishing/uploader.py @@ -49,10 +49,11 @@ def __init__(self, error: ConnectionError | HTTPError | str) -> None: class Uploader: - def __init__(self, poetry: Poetry, io: IO) -> None: + def __init__(self, poetry: Poetry, io: IO, dist_dir: Path | None = None) -> None: self._poetry = poetry self._package = poetry.package self._io = io + self._dist_dir = dist_dir or self.default_dist_dir self._username: str | None = None self._password: str | None = None @@ -62,16 +63,15 @@ def user_agent(self) -> str: return agent @property - def dist_dir(self) -> Path: - io_dist_dir = "dist" - if "dist-dir" in self._io.input.options: # Option comes with publish command. - io_dist_dir = self._io.input.options["dist-dir"] - dist_dir = Path(io_dist_dir) + def default_dist_dir(self) -> Path: + return self._poetry.file.path.parent / "dist" - if not dist_dir.is_absolute(): - dist_dir = self._poetry.file.path.parent / dist_dir + @property + def dist_dir(self) -> Path: + if not self._dist_dir.is_absolute(): + return self._poetry.file.path.parent / self._dist_dir - return dist_dir + return self._dist_dir @property def files(self) -> list[Path]: From 31dda414ea3e8cb69209b5dcb3b7826463d8b91b Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:09:41 +0000 Subject: [PATCH 09/11] add new test build with output option --- src/poetry/console/commands/build.py | 6 ----- tests/console/commands/test_build.py | 37 +++++++++++++++++++--------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/poetry/console/commands/build.py b/src/poetry/console/commands/build.py index a9d056896b3..86626fcf64a 100644 --- a/src/poetry/console/commands/build.py +++ b/src/poetry/console/commands/build.py @@ -2,18 +2,12 @@ from pathlib import Path -from typing import TYPE_CHECKING - from cleo.helpers import option from poetry.console.commands.env_command import EnvCommand from poetry.utils.env import build_environment -if TYPE_CHECKING: - from pathlib import Path - - class BuildCommand(EnvCommand): name = "build" description = "Builds a package, as a tarball and a wheel by default." diff --git a/tests/console/commands/test_build.py b/tests/console/commands/test_build.py index c04717ea7b7..023e855ee59 100644 --- a/tests/console/commands/test_build.py +++ b/tests/console/commands/test_build.py @@ -67,7 +67,6 @@ def test_build_with_multiple_readme_files( tmp_path: Path, tmp_venv: VirtualEnv, command_tester_factory: CommandTesterFactory, - output_dir: str, ) -> None: source_dir = fixture_dir("with_multiple_readme_files") target_dir = tmp_path / "project" @@ -75,17 +74,9 @@ def test_build_with_multiple_readme_files( poetry = Factory().create_poetry(target_dir) tester = command_tester_factory("build", poetry, environment=tmp_venv) + tester.execute() - if output_dir is None: - tester.execute() - build_dir = target_dir / "dist" - elif output_dir == "absolute": - tester.execute(f"--output {target_dir / 'tmp/dist'}") - build_dir = target_dir / "tmp/dist" - else: - tester.execute(f"--output {output_dir}") - build_dir = target_dir / output_dir - + build_dir = target_dir / "dist" assert build_dir.exists() sdist_file = build_dir / "my_package-0.1.tar.gz" @@ -101,3 +92,27 @@ def test_build_with_multiple_readme_files( assert "my_package-0.1/README-1.rst" in sdist_content assert "my_package-0.1/README-2.rst" in sdist_content + + +@pytest.mark.parametrize( + "output_dir", [None, "dist", "test/dir", "../dist", "absolute"] +) +def test_build_output_option( + tmp_tester: CommandTester, + tmp_project_path: Path, + tmp_poetry: Poetry, + output_dir: str, +) -> None: + if output_dir is None: + tmp_tester.execute() + build_dir = tmp_project_path / "dist" + elif output_dir == "absolute": + tmp_tester.execute(f"--output {tmp_project_path / 'tmp/dist'}") + build_dir = tmp_project_path / "tmp/dist" + else: + tmp_tester.execute(f"--output {output_dir}") + build_dir = tmp_project_path / output_dir + + build_artifacts = tuple(build_dir.glob(get_package_glob(tmp_poetry))) + assert len(build_artifacts) > 0 + assert all(archive.exists() for archive in build_artifacts) From aa3fe9a3f92b09a644fea258fa5152b44aabe98e Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:09:41 +0000 Subject: [PATCH 10/11] remove dist dir and change to simple_project fixture --- tests/console/commands/test_publish.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/console/commands/test_publish.py b/tests/console/commands/test_publish.py index 8bb185d6c39..8d83f9508a0 100644 --- a/tests/console/commands/test_publish.py +++ b/tests/console/commands/test_publish.py @@ -184,9 +184,12 @@ def test_publish_dist_dir_and_build_options( command_tester_factory: CommandTesterFactory, dist_dir: str | None, ) -> None: - source_dir = fixture_dir("with_multiple_dist_dir") + source_dir = fixture_dir("simple_project") target_dir = tmp_path / "project" shutil.copytree(str(source_dir), str(target_dir)) + + # Remove dist dir because as it will be built again + shutil.rmtree(target_dir / "dist") http.register_uri( http.POST, "https://upload.pypi.org/legacy/", status=409, body="Conflict" From 9c9c143e1e40e705ba7d30c104ae8d71f0833806 Mon Sep 17 00:00:00 2001 From: Benjamin Callonnec Date: Fri, 9 Feb 2024 15:13:58 +0000 Subject: [PATCH 11/11] trim trailing ws --- tests/console/commands/test_publish.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/console/commands/test_publish.py b/tests/console/commands/test_publish.py index 8d83f9508a0..e123a082c9a 100644 --- a/tests/console/commands/test_publish.py +++ b/tests/console/commands/test_publish.py @@ -187,7 +187,7 @@ def test_publish_dist_dir_and_build_options( source_dir = fixture_dir("simple_project") target_dir = tmp_path / "project" shutil.copytree(str(source_dir), str(target_dir)) - + # Remove dist dir because as it will be built again shutil.rmtree(target_dir / "dist")