Skip to content

Commit 85d74a7

Browse files
committed
feat(cli): introduce --directory to actually switch the directory
1 parent fd2aece commit 85d74a7

File tree

2 files changed

+77
-39
lines changed

2 files changed

+77
-39
lines changed

docs/cli.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ then `--help` combined with any of those can give you more information.
2929
* `--no-interaction (-n)`: Do not ask any interactive question.
3030
* `--no-plugins`: Disables plugins.
3131
* `--no-cache`: Disables Poetry source caches.
32+
* `--directory=DIRECTORY (-C)`: The working directory for the Poetry command (defaults to the current working directory). All command-line arguments will be resolved relative to the given directory.
3233
* `--project=PROJECT (-P)`: Specify another path as the project root. All command-line arguments will be resolved relative to the current working directory.
3334

3435

src/poetry/console/application.py

Lines changed: 76 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from __future__ import annotations
22

3+
import contextlib
34
import logging
5+
import os
46
import re
57

68
from contextlib import suppress
@@ -25,6 +27,7 @@
2527

2628
if TYPE_CHECKING:
2729
from collections.abc import Callable
30+
from collections.abc import Iterator
2831

2932
from cleo.events.event import Event
3033
from cleo.io.inputs.argv_input import ArgvInput
@@ -48,6 +51,17 @@ def _load() -> Command:
4851
return _load
4952

5053

54+
@contextlib.contextmanager
55+
def switch_working_directory(path: Path) -> Iterator[Path]:
56+
original_cwd = Path.cwd()
57+
os.chdir(path)
58+
59+
try:
60+
yield path
61+
finally:
62+
os.chdir(original_cwd)
63+
64+
5165
COMMANDS = [
5266
"about",
5367
"add",
@@ -111,6 +125,63 @@ def __init__(self) -> None:
111125
command_loader = CommandLoader({name: load_command(name) for name in COMMANDS})
112126
self.set_command_loader(command_loader)
113127

128+
@property
129+
def _default_definition(self) -> Definition:
130+
from cleo.io.inputs.option import Option
131+
132+
definition = super()._default_definition
133+
134+
definition.add_option(
135+
Option("--no-plugins", flag=True, description="Disables plugins.")
136+
)
137+
138+
definition.add_option(
139+
Option(
140+
"--no-cache", flag=True, description="Disables Poetry source caches."
141+
)
142+
)
143+
144+
definition.add_option(
145+
Option(
146+
"--project",
147+
"-P",
148+
flag=False,
149+
description=(
150+
"Specify another path as the project root."
151+
" All command-line arguments will be resolved relative to the current working directory."
152+
),
153+
)
154+
)
155+
156+
definition.add_option(
157+
Option(
158+
"--directory",
159+
"-C",
160+
flag=False,
161+
description=(
162+
"The working directory for the Poetry command (defaults to the"
163+
" current working directory). All command-line arguments will be"
164+
" resolved relative to the given directory."
165+
),
166+
)
167+
)
168+
169+
return definition
170+
171+
@cached_property
172+
def _project_directory(self) -> Path:
173+
if self._io and self._io.input.option("project"):
174+
return Path(self._io.input.option("project")).absolute()
175+
176+
return self._working_directory
177+
178+
@cached_property
179+
def _working_directory(self) -> Path:
180+
if self._io and self._io.input.option("directory"):
181+
return Path(self._io.input.option("directory")).absolute()
182+
183+
return Path.cwd()
184+
114185
@property
115186
def poetry(self) -> Poetry:
116187
from poetry.factory import Factory
@@ -119,7 +190,7 @@ def poetry(self) -> Poetry:
119190
return self._poetry
120191

121192
self._poetry = Factory().create_poetry(
122-
cwd=self._directory,
193+
cwd=self._project_directory,
123194
io=self._io,
124195
disable_plugins=self._disable_plugins,
125196
disable_cache=self._disable_cache,
@@ -172,7 +243,9 @@ def _run(self, io: IO) -> int:
172243

173244
self._load_plugins(io)
174245

175-
exit_code: int = super()._run(io)
246+
with switch_working_directory(self._working_directory):
247+
exit_code: int = super()._run(io)
248+
176249
return exit_code
177250

178251
def _configure_io(self, io: IO) -> None:
@@ -335,49 +408,13 @@ def _load_plugins(self, io: IO | None = None) -> None:
335408
from poetry.plugins.application_plugin import ApplicationPlugin
336409
from poetry.plugins.plugin_manager import PluginManager
337410

338-
PluginManager.add_project_plugin_path(self._directory)
411+
PluginManager.add_project_plugin_path(self._project_directory)
339412
manager = PluginManager(ApplicationPlugin.group)
340413
manager.load_plugins()
341414
manager.activate(self)
342415

343416
self._plugins_loaded = True
344417

345-
@property
346-
def _default_definition(self) -> Definition:
347-
from cleo.io.inputs.option import Option
348-
349-
definition = super()._default_definition
350-
351-
definition.add_option(
352-
Option("--no-plugins", flag=True, description="Disables plugins.")
353-
)
354-
355-
definition.add_option(
356-
Option(
357-
"--no-cache", flag=True, description="Disables Poetry source caches."
358-
)
359-
)
360-
361-
definition.add_option(
362-
Option(
363-
"--project",
364-
"-P",
365-
flag=False,
366-
description=(
367-
"Specify another path as the project root."
368-
" All command-line arguments will be resolved relative to the current working directory."
369-
),
370-
)
371-
)
372-
373-
return definition
374-
375-
@cached_property
376-
def _directory(self) -> Path:
377-
if self._io and self._io.input.option("project"):
378-
return Path(self._io.input.option("project")).absolute()
379-
return Path.cwd()
380-
381418

382419
def main() -> int:
383420
exit_code: int = Application().run()

0 commit comments

Comments
 (0)