11from __future__ import annotations
22
3+ import contextlib
34import logging
5+ import os
46import re
57
68from contextlib import suppress
2426
2527if TYPE_CHECKING :
2628 from collections .abc import Callable
29+ from collections .abc import Iterator
2730
2831 from cleo .events .event import Event
2932 from cleo .io .inputs .argv_input import ArgvInput
@@ -47,6 +50,17 @@ def _load() -> Command:
4750 return _load
4851
4952
53+ @contextlib .contextmanager
54+ def switch_working_directory (path : Path ) -> Iterator [Path ]:
55+ original_cwd = Path .cwd ()
56+ os .chdir (path )
57+
58+ try :
59+ yield path
60+ finally :
61+ os .chdir (original_cwd )
62+
63+
5064COMMANDS = [
5165 "about" ,
5266 "add" ,
@@ -110,6 +124,63 @@ def __init__(self) -> None:
110124 command_loader = CommandLoader ({name : load_command (name ) for name in COMMANDS })
111125 self .set_command_loader (command_loader )
112126
127+ @property
128+ def _default_definition (self ) -> Definition :
129+ from cleo .io .inputs .option import Option
130+
131+ definition = super ()._default_definition
132+
133+ definition .add_option (
134+ Option ("--no-plugins" , flag = True , description = "Disables plugins." )
135+ )
136+
137+ definition .add_option (
138+ Option (
139+ "--no-cache" , flag = True , description = "Disables Poetry source caches."
140+ )
141+ )
142+
143+ definition .add_option (
144+ Option (
145+ "--project" ,
146+ "-P" ,
147+ flag = False ,
148+ description = (
149+ "Specify another path as the project root."
150+ " All command-line arguments will be resolved relative to the current working directory."
151+ ),
152+ )
153+ )
154+
155+ definition .add_option (
156+ Option (
157+ "--directory" ,
158+ "-C" ,
159+ flag = False ,
160+ description = (
161+ "The working directory for the Poetry command (defaults to the"
162+ " current working directory). All command-line arguments will be"
163+ " resolved relative to the given directory."
164+ ),
165+ )
166+ )
167+
168+ return definition
169+
170+ @cached_property
171+ def _project_directory (self ) -> Path :
172+ if self ._io and self ._io .input .option ("project" ):
173+ return Path (self ._io .input .option ("project" )).absolute ()
174+
175+ return self ._working_directory
176+
177+ @cached_property
178+ def _working_directory (self ) -> Path :
179+ if self ._io and self ._io .input .option ("directory" ):
180+ return Path (self ._io .input .option ("directory" )).absolute ()
181+
182+ return Path .cwd ()
183+
113184 @property
114185 def poetry (self ) -> Poetry :
115186 from poetry .factory import Factory
@@ -118,7 +189,7 @@ def poetry(self) -> Poetry:
118189 return self ._poetry
119190
120191 self ._poetry = Factory ().create_poetry (
121- cwd = self ._directory ,
192+ cwd = self ._project_directory ,
122193 io = self ._io ,
123194 disable_plugins = self ._disable_plugins ,
124195 disable_cache = self ._disable_cache ,
@@ -171,7 +242,9 @@ def _run(self, io: IO) -> int:
171242
172243 self ._load_plugins (io )
173244
174- exit_code : int = super ()._run (io )
245+ with switch_working_directory (self ._working_directory ):
246+ exit_code : int = super ()._run (io )
247+
175248 return exit_code
176249
177250 def _configure_io (self , io : IO ) -> None :
@@ -331,49 +404,13 @@ def _load_plugins(self, io: IO) -> None:
331404 from poetry .plugins .application_plugin import ApplicationPlugin
332405 from poetry .plugins .plugin_manager import PluginManager
333406
334- PluginManager .add_project_plugin_path (self ._directory )
407+ PluginManager .add_project_plugin_path (self ._project_directory )
335408 manager = PluginManager (ApplicationPlugin .group )
336409 manager .load_plugins ()
337410 manager .activate (self )
338411
339412 self ._plugins_loaded = True
340413
341- @property
342- def _default_definition (self ) -> Definition :
343- from cleo .io .inputs .option import Option
344-
345- definition = super ()._default_definition
346-
347- definition .add_option (
348- Option ("--no-plugins" , flag = True , description = "Disables plugins." )
349- )
350-
351- definition .add_option (
352- Option (
353- "--no-cache" , flag = True , description = "Disables Poetry source caches."
354- )
355- )
356-
357- definition .add_option (
358- Option (
359- "--project" ,
360- "-P" ,
361- flag = False ,
362- description = (
363- "Specify another path as the project root."
364- " All command-line arguments will be resolved relative to the current working directory."
365- ),
366- )
367- )
368-
369- return definition
370-
371- @cached_property
372- def _directory (self ) -> Path :
373- if self ._io and self ._io .input .option ("project" ):
374- return Path (self ._io .input .option ("project" )).absolute ()
375- return Path .cwd ()
376-
377414
378415def main () -> int :
379416 exit_code : int = Application ().run ()
0 commit comments