From bbe9ff5adda2cec5a09c6d189d2747d5ddc14bf0 Mon Sep 17 00:00:00 2001 From: Nat Noordanus Date: Mon, 24 Feb 2025 21:39:02 +0100 Subject: [PATCH] fix: issues with argument parsing in poetry 2.0 plugin Fixes #270 - Create a PoeConfig once on plugin initialization, and reuse it in the command. This allows the plugin to find the config before the working directory is updated as a result of including the `--directory` option. - Update the cleo monkeypatch to account for --directory and --project options taking an argument and being rewritten to precede the command. Also: - disable poetry plugins when calling the poetry CLI inside PoetryExecutor - Duplicate poetry plugin tests to run with two poetry versions --- poethepoet/config/config.py | 11 +- poethepoet/executor/poetry.py | 4 +- poethepoet/plugin.py | 84 ++++--- pyproject.toml | 2 +- tests/conftest.py | 21 +- ...try_plugin.py => test_poetry_plugin_v1.py} | 76 ++++--- tests/test_poetry_plugin_v2.py | 206 ++++++++++++++++++ 7 files changed, 325 insertions(+), 79 deletions(-) rename tests/{test_poetry_plugin.py => test_poetry_plugin_v1.py} (74%) create mode 100644 tests/test_poetry_plugin_v2.py diff --git a/poethepoet/config/config.py b/poethepoet/config/config.py index 1520197d..1578abc1 100644 --- a/poethepoet/config/config.py +++ b/poethepoet/config/config.py @@ -177,9 +177,14 @@ def load(self, target_path: Optional[Union[Path, str]] = None, strict: bool = Tr break else: - raise PoeException( - f"No poe configuration found from location {target_path}" - ) + if target_path is not None: + raise PoeException( + f"No poe configuration found from location {target_path}" + ) + else: + raise PoeException( + f"No poe configuration found from location {self._project_dir}" + ) self._load_includes(strict=strict) diff --git a/poethepoet/executor/poetry.py b/poethepoet/executor/poetry.py index f1336a66..d15ff4ad 100644 --- a/poethepoet/executor/poetry.py +++ b/poethepoet/executor/poetry.py @@ -52,7 +52,7 @@ def execute( # Run this task with `poetry run` return self._execute_cmd( - (self._poetry_cmd(), "run", *cmd), + (self._poetry_cmd(), "--no-plugins", "run", *cmd), input=input, use_exec=use_exec, ) @@ -88,7 +88,7 @@ def _get_poetry_virtualenv(self, force: bool = True): exec_cache["poetry_virtualenv"] = ( Popen( - (self._poetry_cmd(), "env", "info", "-p"), + (self._poetry_cmd(), "--no-plugins", "env", "info", "-p"), stdout=PIPE, cwd=self.context.config.project_dir, env=clean_env, diff --git a/poethepoet/plugin.py b/poethepoet/plugin.py index 8621684b..c3ba904a 100644 --- a/poethepoet/plugin.py +++ b/poethepoet/plugin.py @@ -1,23 +1,26 @@ -from pathlib import Path +from __future__ import annotations + from typing import TYPE_CHECKING, Any from cleo.commands.command import Command -from cleo.events.console_command_event import ConsoleCommandEvent from cleo.events.console_events import COMMAND, TERMINATE -from cleo.events.event_dispatcher import EventDispatcher -from cleo.io.io import IO from poetry.console.application import COMMANDS, Application from poetry.plugins.application_plugin import ApplicationPlugin from .exceptions import PoePluginException if TYPE_CHECKING: + from cleo.events.console_command_event import ConsoleCommandEvent + from cleo.events.event_dispatcher import EventDispatcher + from cleo.io.io import IO + from .config import PoeConfig class PoeCommand(Command): prefix: str command_prefix: str = "poe" + poe_config: PoeConfig def __init__(self): super().__init__() @@ -45,9 +48,10 @@ def handle(self): raise SystemExit(task_status) @classmethod - def get_poe(cls, application: Application, io: IO): + def get_poe( + cls, application: Application, io: IO, poe_config: PoeConfig | None = None + ): from .app import PoeThePoet - from .config import PoeConfig try: from poetry.utils.env import EnvManager @@ -56,23 +60,17 @@ def get_poe(cls, application: Application, io: IO): except: # noqa: E722 poetry_env_path = None - # Get the cwd from poetry to ensure '--directory subdir' usage - try: - cwd = application.poetry.pyproject_path - except AttributeError: - cwd = Path().resolve() - config = PoeConfig(cwd=cwd) + poe_config = poe_config or cls.poe_config if io.output.is_quiet(): - config._baseline_verbosity = -1 + poe_config._baseline_verbosity = -1 elif io.is_very_verbose(): - config._baseline_verbosity = 2 + poe_config._baseline_verbosity = 2 elif io.is_verbose(): - config._baseline_verbosity = 1 + poe_config._baseline_verbosity = 1 return PoeThePoet( - cwd=cwd, - config=config, + config=poe_config, output=io.output.stream, poetry_env_path=poetry_env_path, program_name=f"poetry {cls.command_prefix}", @@ -126,10 +124,11 @@ def _activate(self, application: Application) -> None: f"Poe task {task_name!r} conflicts with a poetry command. " "Please rename the task or the configure a command prefix." ) - self._register_command(application, task_name, task) + self._register_command(application, poe_config, task_name, task) else: self._register_command( application, + poe_config, "", {"help": "Run poe tasks defined for this project"}, command_prefix, @@ -138,23 +137,23 @@ def _activate(self, application: Application) -> None: if task_name.startswith("_"): continue self._register_command( - application, task_name, task, f"{command_prefix} " + application, poe_config, task_name, task, f"{command_prefix} " ) self._monkey_patch_cleo(command_prefix, list(poe_tasks.keys())) self._register_command_event_handler( - application, poe_config._project_config.get("poetry_hooks", {}) + application, poe_config._project_config.get("poetry_hooks", {}), poe_config ) @classmethod - def _get_config(cls, application: Application) -> "PoeConfig": + def _get_config(cls, application: Application) -> PoeConfig: from .config import PoeConfig # Try respect poetry's '--directory' if set try: pyproject_dir = application.poetry.pyproject_path.parent - except (AttributeError, RuntimeError): + except AttributeError: pyproject_dir = None poe_config = PoeConfig(cwd=pyproject_dir) @@ -169,7 +168,12 @@ def _validate_command_prefix(self, command_prefix: str): ) def _register_command( - self, application: Application, task_name: str, task: Any, prefix: str = "" + self, + application: Application, + poe_config: PoeConfig, + task_name: str, + task: Any, + prefix: str = "", ): command_name = prefix + task_name task_help = task.get("help", "") if isinstance(task, dict) else "" @@ -178,12 +182,17 @@ def _register_command( type( (task_name or prefix).replace("-", "").capitalize() + "Command", (PoeCommand,), - {"name": command_name, "description": task_help, "prefix": prefix}, + { + "name": command_name, + "description": task_help, + "prefix": prefix, + "poe_config": poe_config, + }, ), ) def _register_command_event_handler( - self, application: Application, hooks: dict[str, str] + self, application: Application, hooks: dict[str, str], poe_config: PoeConfig ): if not hooks: return @@ -201,16 +210,16 @@ def _register_command_event_handler( if pre_hooks: application.event_dispatcher.add_listener( COMMAND, - self._get_command_event_handler(pre_hooks, application), + self._get_command_event_handler(pre_hooks, application, poe_config), ) if post_hooks: application.event_dispatcher.add_listener( TERMINATE, - self._get_command_event_handler(post_hooks, application), + self._get_command_event_handler(post_hooks, application, poe_config), ) def _get_command_event_handler( - self, hooks: dict[str, str], application: Application + self, hooks: dict[str, str], application: Application, poe_config: PoeConfig ): def command_event_handler( event: ConsoleCommandEvent, @@ -223,7 +232,7 @@ def command_event_handler( import shlex - task_status = PoeCommand.get_poe(application, event.io)( + task_status = PoeCommand.get_poe(application, event.io, poe_config)( cli_args=shlex.split(task), internal=True ) @@ -281,10 +290,17 @@ def _run(self, io): def _index_of_first_non_option(tokens: list[str]): """ - Find the index of the first token that doesn't start with `-` + Find the index of the first token that doesn't start with `-`, and isn't directly + preceded by either `--project` or `--directory`. + Returns len(tokens) if none is found. """ - return next( - (index for index, token in enumerate(tokens) if token[0] != "-"), - len(tokens), - ) + + options_with_args = ("--project", "--directory") + previous_token = "" + for index, token in enumerate(tokens): + if token[0] != "-" and previous_token not in options_with_args: + return index + previous_token = token + else: + return len(tokens) diff --git a/pyproject.toml b/pyproject.toml index c89c220e..b7e506e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -129,7 +129,7 @@ sequence = ["docs-check", "style", "types", "lint", "test"] [tool.poe.tasks.install-poetry-plugin] help = "Install or update this project as a plugin in poetry" sequence = [ - { cmd = "poetry self remove poethepoet"}, + { cmd = "poetry --no-plugins self remove poethepoet"}, { cmd = "poetry self add \"${POE_ROOT}[poetry_plugin]\""} ] ignore_fail = true diff --git a/tests/conftest.py b/tests/conftest.py index ed766e47..21e74a58 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -244,11 +244,14 @@ def run_poe_main( return run_poe_main -@pytest.fixture(scope="session") -def run_poetry(use_venv, poe_project_path, version: str = "2.0.0"): - venv_location = poe_project_path / "tests" / "temp" / "poetry_venv" +def run_poetry(use_venv, poe_project_path, version): + venv_location = poe_project_path / "tests" / "temp" / f"poetry_venv_{version}" - def run_poetry(args: list[str], cwd: str, env: Optional[dict[str, str]] = None): + def run_poetry( + args: list[str], + cwd: str, + env: Optional[dict[str, str]] = None, + ): venv = Virtualenv(venv_location) cmd = (venv.resolve_executable("python"), "-m", "poetry", *args) @@ -282,6 +285,16 @@ def run_poetry(args: list[str], cwd: str, env: Optional[dict[str, str]] = None): yield run_poetry +@pytest.fixture(scope="session") +def run_poetry_1(use_venv, poe_project_path): + yield from run_poetry(use_venv, poe_project_path, version="1.8.2") + + +@pytest.fixture(scope="session") +def run_poetry_2(use_venv, poe_project_path): + yield from run_poetry(use_venv, poe_project_path, version="2.0.0") + + @pytest.fixture(scope="session") def esc_prefix(is_windows): """ diff --git a/tests/test_poetry_plugin.py b/tests/test_poetry_plugin_v1.py similarity index 74% rename from tests/test_poetry_plugin.py rename to tests/test_poetry_plugin_v1.py index 2c6fd9c8..3aafd3ff 100644 --- a/tests/test_poetry_plugin.py +++ b/tests/test_poetry_plugin_v1.py @@ -4,24 +4,30 @@ import pytest -@pytest.fixture(scope="session") -def _setup_poetry_project(run_poetry, projects): - run_poetry(["install"], cwd=projects["poetry_plugin"]) +@pytest.fixture(scope="module") +def _setup_poetry_project(run_poetry_1, projects): + run_poetry_1(["install"], cwd=projects["poetry_plugin"]) -@pytest.fixture(scope="session") -def _setup_poetry_project_empty_prefix(run_poetry, projects): - run_poetry(["install"], cwd=projects["poetry_plugin/empty_prefix"].parent) +@pytest.fixture(scope="module") +def _setup_poetry_project_empty_prefix(run_poetry_1, projects): + run_poetry_1( + ["install"], + cwd=projects["poetry_plugin/empty_prefix"].parent, + ) -@pytest.fixture(scope="session") -def _setup_poetry_project_with_prefix(run_poetry, projects): - run_poetry(["install"], cwd=projects["poetry_plugin/with_prefix"].parent) +@pytest.fixture(scope="module") +def _setup_poetry_project_with_prefix(run_poetry_1, projects): + run_poetry_1( + ["install"], + cwd=projects["poetry_plugin/with_prefix"].parent, + ) @pytest.mark.slow -def test_poetry_help(run_poetry, projects): - result = run_poetry([], cwd=projects["poetry_plugin"]) +def test_poetry_help(run_poetry_1, projects): + result = run_poetry_1([], cwd=projects["poetry_plugin"]) assert result.stdout.startswith("Poetry (version ") assert "poe cow-greet" in result.stdout assert re.search(r"\n poe echo\s+It's like echo\n", result.stdout) @@ -35,8 +41,8 @@ def test_poetry_help(run_poetry, projects): ) @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project") -def test_task_with_cli_dependency(run_poetry, projects, is_windows): - result = run_poetry( +def test_task_with_cli_dependency(run_poetry_1, projects, is_windows): + result = run_poetry_1( ["poe", "cow-greet", "yo yo yo"], cwd=projects["poetry_plugin"], ) @@ -60,8 +66,8 @@ def test_task_with_cli_dependency(run_poetry, projects, is_windows): ) @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project") -def test_task_with_lib_dependency(run_poetry, projects): - result = run_poetry(["poe", "cow-cheese"], cwd=projects["poetry_plugin"]) +def test_task_with_lib_dependency(run_poetry_1, projects): + result = run_poetry_1(["poe", "cow-cheese"], cwd=projects["poetry_plugin"]) assert result.stdout == ( "Poe => from cowpy import cow; print(list(cow.COWACTERS)[5])\ncheese\n" ) @@ -70,8 +76,8 @@ def test_task_with_lib_dependency(run_poetry, projects): @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project") -def test_task_accepts_any_args(run_poetry, projects): - result = run_poetry( +def test_task_accepts_any_args(run_poetry_1, projects): + result = run_poetry_1( ["poe", "echo", "--lol=:D", "--version", "--help"], cwd=projects["poetry_plugin"], ) @@ -83,8 +89,8 @@ def test_task_accepts_any_args(run_poetry, projects): @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") -def test_poetry_help_without_poe_command_prefix(run_poetry, projects): - result = run_poetry([], cwd=projects["poetry_plugin/empty_prefix"].parent) +def test_poetry_help_without_poe_command_prefix(run_poetry_1, projects): + result = run_poetry_1([], cwd=projects["poetry_plugin/empty_prefix"].parent) assert result.stdout.startswith("Poetry (version ") assert "\n cow-greet" in result.stdout assert "\n echo It's like echo\n" in result.stdout @@ -93,8 +99,8 @@ def test_poetry_help_without_poe_command_prefix(run_poetry, projects): @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") -def test_running_tasks_without_poe_command_prefix(run_poetry, projects): - result = run_poetry( +def test_running_tasks_without_poe_command_prefix(run_poetry_1, projects): + result = run_poetry_1( ["echo", "--lol=:D", "--version", "--help"], cwd=projects["poetry_plugin/empty_prefix"].parent, ) @@ -106,8 +112,8 @@ def test_running_tasks_without_poe_command_prefix(run_poetry, projects): @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") -def test_poetry_command_from_included_file_with_empty_prefix(run_poetry, projects): - result = run_poetry( +def test_poetry_command_from_included_file_with_empty_prefix(run_poetry_1, projects): + result = run_poetry_1( ["included-greeting"], cwd=projects["poetry_plugin/empty_prefix"].parent, ) @@ -117,8 +123,8 @@ def test_poetry_command_from_included_file_with_empty_prefix(run_poetry, project @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") -def test_poetry_help_with_poe_command_prefix(run_poetry, projects): - result = run_poetry([], cwd=projects["poetry_plugin/with_prefix"].parent) +def test_poetry_help_with_poe_command_prefix(run_poetry_1, projects): + result = run_poetry_1([], cwd=projects["poetry_plugin/with_prefix"].parent) assert result.stdout.startswith("Poetry (version ") assert "\n foo cow-greet" in result.stdout assert "\n foo echo It's like echo\n" in result.stdout @@ -127,8 +133,8 @@ def test_poetry_help_with_poe_command_prefix(run_poetry, projects): @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project_with_prefix") -def test_running_tasks_with_poe_command_prefix(run_poetry, projects): - result = run_poetry( +def test_running_tasks_with_poe_command_prefix(run_poetry_1, projects): + result = run_poetry_1( ["foo", "echo", "--lol=:D", "--version", "--help"], cwd=projects["poetry_plugin/with_prefix"].parent, ) @@ -140,8 +146,8 @@ def test_running_tasks_with_poe_command_prefix(run_poetry, projects): @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project_with_prefix") -def test_running_tasks_with_poe_command_prefix_missing_args(run_poetry, projects): - result = run_poetry( +def test_running_tasks_with_poe_command_prefix_missing_args(run_poetry_1, projects): + result = run_poetry_1( ["foo"], cwd=projects["poetry_plugin/with_prefix"].parent, ) @@ -151,8 +157,8 @@ def test_running_tasks_with_poe_command_prefix_missing_args(run_poetry, projects @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project") -def test_running_poetry_command_with_hooks(run_poetry, projects): - result = run_poetry(["env", "info"], cwd=projects["poetry_plugin"]) +def test_running_poetry_command_with_hooks(run_poetry_1, projects): + result = run_poetry_1(["env", "info"], cwd=projects["poetry_plugin"]) assert "THIS IS YOUR ENV!" in result.stdout assert "THAT WAS YOUR ENV!" in result.stdout # assert result.stderr == "" @@ -160,8 +166,8 @@ def test_running_poetry_command_with_hooks(run_poetry, projects): @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project") -def test_running_poetry_command_with_hooks_with_directory(run_poetry, projects): - result = run_poetry( +def test_running_poetry_command_with_hooks_with_directory(run_poetry_1, projects): + result = run_poetry_1( ["--directory=" + str(projects["poetry_plugin"]), "env", "info"], cwd=projects["poetry_plugin"].parent, ) @@ -177,8 +183,8 @@ def test_running_poetry_command_with_hooks_with_directory(run_poetry, projects): ) @pytest.mark.slow @pytest.mark.usefixtures("_setup_poetry_project") -def test_task_with_cli_dependency_with_directory(run_poetry, projects, is_windows): - result = run_poetry( +def test_task_with_cli_dependency_with_directory(run_poetry_1, projects, is_windows): + result = run_poetry_1( [ "--directory=" + str(projects["poetry_plugin"]), "poe", diff --git a/tests/test_poetry_plugin_v2.py b/tests/test_poetry_plugin_v2.py new file mode 100644 index 00000000..0f0e3055 --- /dev/null +++ b/tests/test_poetry_plugin_v2.py @@ -0,0 +1,206 @@ +import os +import re + +import pytest + + +@pytest.fixture(scope="module") +def _setup_poetry_project(run_poetry_2, projects): + run_poetry_2(["install"], cwd=projects["poetry_plugin"]) + + +@pytest.fixture(scope="module") +def _setup_poetry_project_empty_prefix(run_poetry_2, projects): + run_poetry_2( + ["install"], + cwd=projects["poetry_plugin/empty_prefix"].parent, + ) + + +@pytest.fixture(scope="module") +def _setup_poetry_project_with_prefix(run_poetry_2, projects): + run_poetry_2( + ["install"], + cwd=projects["poetry_plugin/with_prefix"].parent, + ) + + +@pytest.mark.slow +def test_poetry_help(run_poetry_2, projects): + result = run_poetry_2([], cwd=projects["poetry_plugin"]) + assert result.stdout.startswith("Poetry (version ") + assert "poe cow-greet" in result.stdout + assert re.search(r"\n poe echo\s+It's like echo\n", result.stdout) + # assert result.stderr == "" + + +# TODO: re-enable this test +@pytest.mark.skipif( + os.environ.get("GITHUB_ACTIONS", "false") == "true", + reason="Skipping test the doesn't seem to work in GitHub Actions lately", +) +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project") +def test_task_with_cli_dependency(run_poetry_2, projects, is_windows): + result = run_poetry_2( + ["poe", "cow-greet", "yo yo yo"], + cwd=projects["poetry_plugin"], + ) + if is_windows: + assert result.stdout.startswith("Poe => cowpy 'yo yo yo'") + assert "< yo yo yo >" in result.stdout + else: + # On POSIX cowpy expects notices its being called as a subprocess and tries + # unproductively to take input from stdin + assert result.stdout.startswith("Poe => cowpy 'yo yo yo'") + assert ( + "< Cowacter, eyes:default, tongue:False, thoughts:False >" in result.stdout + ) + # assert result.stderr == "" + + +# TODO: re-enable this test +@pytest.mark.skipif( + os.environ.get("GITHUB_ACTIONS", "false") == "true", + reason="Skipping test the doesn't seem to work in GitHub Actions lately", +) +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project") +def test_task_with_lib_dependency(run_poetry_2, projects): + result = run_poetry_2(["poe", "cow-cheese"], cwd=projects["poetry_plugin"]) + assert result.stdout == ( + "Poe => from cowpy import cow; print(list(cow.COWACTERS)[5])\ncheese\n" + ) + # assert result.stderr == "" + + +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project") +def test_task_accepts_any_args(run_poetry_2, projects): + result = run_poetry_2( + ["poe", "echo", "--lol=:D", "--version", "--help"], + cwd=projects["poetry_plugin"], + ) + assert result.stdout == ( + "Poe => poe_test_echo --lol=:D --version --help\n--lol=:D --version --help\n" + ) + # assert result.stderr == "" + + +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") +def test_poetry_help_without_poe_command_prefix(run_poetry_2, projects): + result = run_poetry_2([], cwd=projects["poetry_plugin/empty_prefix"].parent) + assert result.stdout.startswith("Poetry (version ") + assert "\n cow-greet" in result.stdout + assert "\n echo It's like echo\n" in result.stdout + # assert result.stderr == "" + + +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") +def test_running_tasks_without_poe_command_prefix(run_poetry_2, projects): + result = run_poetry_2( + ["echo", "--lol=:D", "--version", "--help"], + cwd=projects["poetry_plugin/empty_prefix"].parent, + ) + assert result.stdout == ( + "Poe => poe_test_echo --lol=:D --version --help\n--lol=:D --version --help\n" + ) + # assert result.stderr == "" + + +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") +def test_poetry_command_from_included_file_with_empty_prefix(run_poetry_2, projects): + result = run_poetry_2( + ["included-greeting"], + cwd=projects["poetry_plugin/empty_prefix"].parent, + ) + assert result.stdout.startswith("Poe => echo 'Greetings from another file!'") + # assert result.stderr == "" + + +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") +def test_poetry_help_with_poe_command_prefix(run_poetry_2, projects): + result = run_poetry_2([], cwd=projects["poetry_plugin/with_prefix"].parent) + assert result.stdout.startswith("Poetry (version ") + assert "\n foo cow-greet" in result.stdout + assert "\n foo echo It's like echo\n" in result.stdout + # assert result.stderr == "" + + +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project_with_prefix") +def test_running_tasks_with_poe_command_prefix(run_poetry_2, projects): + result = run_poetry_2( + ["foo", "echo", "--lol=:D", "--version", "--help"], + cwd=projects["poetry_plugin/with_prefix"].parent, + ) + assert result.stdout == ( + "Poe => poe_test_echo --lol=:D --version --help\n--lol=:D --version --help\n" + ) + # assert result.stderr == "" + + +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project_with_prefix") +def test_running_tasks_with_poe_command_prefix_missing_args(run_poetry_2, projects): + result = run_poetry_2( + ["foo"], + cwd=projects["poetry_plugin/with_prefix"].parent, + ) + assert "Usage:\n poetry foo [global options]" in result.stdout + # assert result.stderr == "" + + +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project") +def test_running_poetry_command_with_hooks(run_poetry_2, projects): + result = run_poetry_2(["env", "info"], cwd=projects["poetry_plugin"]) + assert "THIS IS YOUR ENV!" in result.stdout + assert "THAT WAS YOUR ENV!" in result.stdout + # assert result.stderr == "" + + +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project") +def test_running_poetry_command_with_hooks_with_directory(run_poetry_2, projects): + result = run_poetry_2( + ["--directory=" + str(projects["poetry_plugin"]), "env", "info"], + cwd=projects["poetry_plugin"].parent, + ) + assert "THIS IS YOUR ENV!" in result.stdout + assert "THAT WAS YOUR ENV!" in result.stdout + # assert result.stderr == "" + + +# TODO: re-enable this test +@pytest.mark.skipif( + os.environ.get("GITHUB_ACTIONS", "false") == "true", + reason="Skipping test the doesn't seem to work in GitHub Actions lately", +) +@pytest.mark.slow +@pytest.mark.usefixtures("_setup_poetry_project") +def test_task_with_cli_dependency_with_directory(run_poetry_2, projects, is_windows): + result = run_poetry_2( + [ + "--directory=" + str(projects["poetry_plugin"]), + "poe", + "cow-greet", + "yo yo yo", + ], + cwd=projects["poetry_plugin"].parent, + ) + if is_windows: + assert result.stdout.startswith("Poe => cowpy 'yo yo yo'") + assert "< yo yo yo >" in result.stdout + else: + # On POSIX cowpy expects notices its being called as a subprocess and tries + # unproductively to take input from stdin + assert result.stdout.startswith("Poe => cowpy 'yo yo yo'") + assert ( + "< Cowacter, eyes:default, tongue:False, thoughts:False >" in result.stdout + ) + # assert result.stderr == ""