Skip to content

Commit

Permalink
Fix running console scripts of editable dependencies on Windows (#3339)
Browse files Browse the repository at this point in the history
* Fix running scripts of editable deps on Windows
* Add Windows-specific logic to fix existing test

Co-authored-by: Kevin Conley <kevincon@users.noreply.github.com>
  • Loading branch information
kevincon and kevincon committed Jun 4, 2022
1 parent 7ab0699 commit 53e50d9
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/poetry/utils/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -1491,6 +1491,7 @@ def execute(self, bin: str, *args: str, **kwargs: Any) -> int:
if not self._is_windows:
return os.execvpe(command[0], command, env=env)

kwargs["shell"] = True
exe = subprocess.Popen([command[0]] + command[1:], env=env, **kwargs)
exe.communicate()
return exe.returncode
Expand Down
57 changes: 55 additions & 2 deletions tests/console/commands/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@

import pytest

from poetry.utils._compat import WINDOWS


if TYPE_CHECKING:
from cleo.testers.application_tester import ApplicationTester
from cleo.testers.command_tester import CommandTester
from pytest_mock import MockerFixture

from poetry.utils.env import MockEnv
from poetry.utils.env import VirtualEnv
from tests.types import CommandTesterFactory


Expand Down Expand Up @@ -42,11 +45,61 @@ def test_run_keeps_options_passed_before_command(


def test_run_has_helpful_error_when_command_not_found(
app_tester: ApplicationTester, env: MockEnv
app_tester: ApplicationTester, env: MockEnv, capfd: pytest.CaptureFixture[str]
):
env._execute = True
app_tester.execute("run nonexistent-command")

assert env.executed == [["nonexistent-command"]]
assert app_tester.status_code == 1
assert app_tester.io.fetch_error() == "Command not found: nonexistent-command\n"
if WINDOWS:
# On Windows we use a shell to run commands which provides its own error
# message when a command is not found that is not captured by the
# ApplicationTester but is captured by pytest, and we can access it via capfd.
# The expected string in this assertion assumes Command Prompt (cmd.exe) is the
# shell used.
assert capfd.readouterr().err.splitlines() == [
"'nonexistent-command' is not recognized as an internal or external"
" command,",
"operable program or batch file.",
]
else:
assert app_tester.io.fetch_error() == "Command not found: nonexistent-command\n"


@pytest.mark.skipif(
not WINDOWS,
reason=(
"Poetry only installs CMD script files for console scripts of editable"
" dependencies on Windows"
),
)
def test_run_console_scripts_of_editable_dependencies_on_windows(
tmp_venv: VirtualEnv,
command_tester_factory: CommandTesterFactory,
):
"""
On Windows, Poetry installs console scripts of editable dependencies by creating
in the environment's `Scripts/` directory both:
A) a Python file named after the console script (no `.py` extension) which
imports and calls the console script using Python code
B) a CMD script file also named after the console script
(with `.cmd` extension) which calls `python.exe` to execute (A)
This configuration enables calling the console script by name from `cmd.exe`
because the `.cmd` file extension appears by default in the PATHEXT environment
variable that `cmd.exe` uses to determine which file should be executed if a
filename without an extension is executed as a command.
This test validates that you can also run such a CMD script file via `poetry run`
just by providing the script's name without the `.cmd` extension.
"""
tester = command_tester_factory("run", environment=tmp_venv)

cmd_script_file = tmp_venv._bin_dir / "quix.cmd"
# `/b` ensures we only exit the script instead of any cmd.exe proc that called it
cmd_script_file.write_text("exit /b 123")
# We prove that the CMD script executed successfully by verifying the exit code
# matches what we wrote in the script
assert tester.execute("quix") == 123

0 comments on commit 53e50d9

Please sign in to comment.