Skip to content

Commit 297ae7d

Browse files
authored
fix --directory for plugins that access the poetry instance during activation (#10352)
see nat-n/poethepoet#288
1 parent d447030 commit 297ae7d

File tree

4 files changed

+79
-14
lines changed

4 files changed

+79
-14
lines changed

src/poetry/console/application.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -251,11 +251,11 @@ def _run(self, io: IO) -> int:
251251
# display the error cleanly unless the user uses verbose or debug
252252
self._configure_global_options(io)
253253

254-
self._load_plugins(io)
254+
with directory(self._working_directory):
255+
self._load_plugins(io)
255256

256-
exit_code: int = 1
257+
exit_code: int = 1
257258

258-
with directory(self._working_directory):
259259
try:
260260
exit_code = super()._run(io)
261261
except PoetryRuntimeError as e:

tests/console/test_application_global_options.py

+68-10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from pathlib import Path
77
from typing import TYPE_CHECKING
8+
from typing import ClassVar
89

910
import pytest
1011

@@ -13,7 +14,10 @@
1314
from cleo.testers.application_tester import ApplicationTester
1415

1516
from poetry.console.application import Application
17+
from poetry.console.commands.command import Command
1618
from poetry.console.commands.version import VersionCommand
19+
from poetry.plugins import ApplicationPlugin
20+
from tests.helpers import mock_metadata_entry_points
1721
from tests.helpers import switch_working_directory
1822

1923

@@ -27,11 +31,58 @@
2731
NO_PYPROJECT_TOML_ERROR = "Poetry could not find a pyproject.toml file in"
2832

2933

34+
class CheckProjectPathCommand(Command):
35+
name = "check-project-path"
36+
37+
description = "Check Project Path Command"
38+
39+
def handle(self) -> int:
40+
if not self.poetry.pyproject_path.exists():
41+
raise RuntimeError(
42+
f"Wrong project path in handle: {self.poetry.pyproject_path}\nWorking directory: {Path.cwd()}"
43+
)
44+
45+
return 0
46+
47+
48+
class EarlyPoetryAccessPlugin(ApplicationPlugin):
49+
commands: ClassVar[list[type[Command]]] = [CheckProjectPathCommand]
50+
51+
def activate(self, application: Application) -> None:
52+
super().activate(application)
53+
54+
# access application.poetry
55+
# see https://github.com/nat-n/poethepoet/issues/288
56+
if not application.poetry.pyproject_path.exists():
57+
raise RuntimeError(
58+
f"Wrong project path in activate: {application.poetry.pyproject_path}\nWorking directory: {Path.cwd()}"
59+
)
60+
61+
62+
@pytest.fixture
63+
def with_early_poetry_access_plugin(mocker: MockerFixture) -> None:
64+
mock_metadata_entry_points(mocker, EarlyPoetryAccessPlugin)
65+
66+
3067
@pytest.fixture
3168
def project_source_directory(fixture_copier: FixtureCopier) -> Path:
3269
return fixture_copier("up_to_date_lock")
3370

3471

72+
@pytest.fixture
73+
def relative_project_source_directory(project_source_directory: Path) -> Path:
74+
# ensure pre-conditions are met
75+
cwd = Path.cwd()
76+
assert project_source_directory.is_relative_to(cwd)
77+
78+
# construct relative path
79+
relative_source_directory = project_source_directory.relative_to(cwd)
80+
assert relative_source_directory.as_posix() != project_source_directory.as_posix()
81+
assert not relative_source_directory.is_absolute()
82+
83+
return relative_source_directory
84+
85+
3586
@pytest.fixture
3687
def tester() -> ApplicationTester:
3788
return ApplicationTester(Application())
@@ -149,20 +200,14 @@ def test_application_with_context_parameters(
149200
def test_application_with_relative_project_parameter(
150201
tester: ApplicationTester,
151202
project_source_directory: Path,
203+
relative_project_source_directory: Path,
152204
with_mocked_version_command: None,
153205
tmp_path_factory: TempPathFactory,
154206
) -> None:
155-
# ensure pre-conditions are met
156207
cwd = Path.cwd()
157-
assert project_source_directory.is_relative_to(cwd)
158-
159-
# construct relative path
160-
relative_source_directory = project_source_directory.relative_to(cwd)
161-
assert relative_source_directory.as_posix() != project_source_directory.as_posix()
162-
assert not relative_source_directory.is_absolute()
163-
164-
# we expect application run to be executed within current cwd but project to be a subdirectory
165-
args = f"--directory '{cwd}' --project {relative_source_directory} version"
208+
# we expect application run to be executed within current cwd
209+
# but project to be a subdirectory
210+
args = f"--directory '{cwd}' --project {relative_project_source_directory} version"
166211

167212
# we switch cwd to a new temporary directory unrelated to the project directory
168213
new_working_dir = tmp_path_factory.mktemp("unrelated-working-directory")
@@ -181,6 +226,19 @@ def test_application_with_relative_project_parameter(
181226
""")
182227

183228

229+
def test_application_with_relative_directory_parameter_and_early_poetry_access_plugin(
230+
tester: ApplicationTester,
231+
with_early_poetry_access_plugin: None,
232+
relative_project_source_directory: Path,
233+
) -> None:
234+
"""see https://github.com/nat-n/poethepoet/issues/288"""
235+
tester.execute(
236+
f"--directory {relative_project_source_directory} check-project-path"
237+
)
238+
239+
assert tester.status_code == 0, tester.io.fetch_error()
240+
241+
184242
@pytest.mark.parametrize(
185243
("parameter", "check", "result"),
186244
[

tests/helpers.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,15 @@ def mock_metadata_entry_points(
277277
name: str = "my-plugin",
278278
dist: metadata.Distribution | None = None,
279279
) -> None:
280+
def patched_entry_points(*args: Any, **kwargs: Any) -> list[metadata.EntryPoint]:
281+
if "group" in kwargs and kwargs["group"] != getattr(cls, "group", None):
282+
return []
283+
return [make_entry_point_from_plugin(name, cls, dist)]
284+
280285
mocker.patch.object(
281286
metadata,
282287
"entry_points",
283-
return_value=[make_entry_point_from_plugin(name, cls, dist)],
288+
side_effect=patched_entry_points,
284289
)
285290

286291

tests/plugins/test_plugin_manager.py

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ class MyCommandPlugin(ApplicationPlugin):
5757

5858

5959
class InvalidPlugin:
60+
group = "poetry.plugin"
61+
6062
def activate(self, poetry: Poetry, io: IO) -> None:
6163
io.write_line("Updating version")
6264
poetry.package.version = Version.parse("9.9.9")

0 commit comments

Comments
 (0)