Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/poetry/console/commands/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,13 @@ def handle(self) -> int:

# Building package first, if told
if self.option("build"):
if publisher.files and not self.confirm(
f"There are <info>{len(publisher.files)}</info> files ready for"
" publishing. Build anyway?"
if (
publisher.files
and self.io.is_interactive()
and not self.confirm(
f"There are <info>{len(publisher.files)}</info> files ready for"
" publishing. Build anyway?"
)
):
self.line_error("<error>Aborted!</error>")

Expand Down
27 changes: 27 additions & 0 deletions tests/console/commands/test_publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pathlib import Path
from typing import TYPE_CHECKING
from typing import NoReturn
from unittest.mock import PropertyMock

import pytest
import requests
Expand Down Expand Up @@ -215,3 +216,29 @@ def test_publish_dist_dir_and_build_options(
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


def test_publish_build_no_interaction_skips_confirmation(
app_tester: ApplicationTester, mocker: MockerFixture
) -> None:
mocker.patch(
"poetry.publishing.publisher.Publisher.files",
new_callable=PropertyMock,
return_value=[Path("dist/simple_project-1.2.3-py2.py3-none-any.whl")],
)
confirm = mocker.patch("poetry.console.commands.publish.PublishCommand.confirm")
command_call = mocker.patch("poetry.console.commands.publish.PublishCommand.call")
publisher_files = mocker.patch(
"poetry.publishing.publisher.Publisher.files",
new_callable=mocker.PropertyMock,
return_value=[Path("dist/existing.whl")],
)
publisher_publish = mocker.patch("poetry.publishing.Publisher.publish")

exit_code = app_tester.execute("publish --build --no-interaction --dry-run")

assert exit_code == 0
Comment on lines +221 to +240
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (testing): Test does not simulate pre-existing dist artifacts, so it doesn’t cover the regression scenario described in the PR

Because Publisher.publish is mocked and publisher.files is never set, publisher.files remains falsy and the if publisher.files and self.io.is_interactive() branch is never hit. This test only proves that --no-interaction skips confirm when there are no existing artifacts. To actually cover the regression, ensure the Publisher used by PublishCommand has a non-empty files list (e.g. via a fixture, a real Publisher, or by patching the constructor and setting .files), so the scenario with pre-existing dist artifacts is exercised.

confirm.assert_not_called()
command_call.assert_called_once_with("build", args="--output dist")
assert publisher_files.call_count >= 1
assert publisher_publish.call_count == 1