Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions doc/tutorials/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ Create the environment

``ewoks install`` creates a python environment for the :term:`workflow`. It prints the python
interpreter of the environment it created, the command to execute the :term:`workflow` in it
and the command to remove it again
and the command to remove it again. These commands work from any terminal and directory

.. code-block:: text

Installed requirements for demo.json
Python : ewoks_envs/demo/bin/python
Execute: ewoks execute --env ewoks_envs/demo demo.json
Remove : rm -rf ewoks_envs/demo
Python : /home/user/ewoks_envs/demo/bin/python
Execute: /home/user/ewoks_envs/demo/bin/python -m ewoks execute /home/user/demo.json
Remove : rm -rf /home/user/ewoks_envs/demo

Without ``--yes`` you are asked to confirm after the packages have been listed. The
walk-throughs use ``--env-root`` to create the environment in the working directory. Without
Expand Down
66 changes: 53 additions & 13 deletions src/ewoks/__main__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import os
import re
import shlex
import subprocess
import sys
import traceback
Expand Down Expand Up @@ -207,27 +210,64 @@ def command_install(
print(f"Install aborted for {workflow}")
else:
print(f"Installed requirements for {workflow}")
print(f" Python : {environment.python}")
if environment.distribution_version("ewoks"):
execute = _shell_command(
[
str(environment.python),
"-m",
"ewoks",
"execute",
_absolute_workflow(workflow),
]
)
print(f" Execute: {execute}")
else:
print(
" Execute: the environment has no ewoks to execute the "
"workflow with (use '--with-ewoks')"
)
if not cli_args.in_place:
location = environment.location
print(f" Python : {environment.python}")
if environment.distribution_version("ewoks"):
print(f" Execute: ewoks execute --env {location} {workflow}")
else:
print(
" Execute: the environment has no ewoks to execute the "
"workflow with (use '--with-ewoks')"
)
print(f" Remove : {_remove_command(location)}")
print(f" Remove : {_remove_command(environment.location)}")
if shell:
return 0
return None


def _remove_command(location: Path) -> str:
"""Shell command that removes a python environment."""
"""Shell command that removes a python environment: PowerShell on Windows."""
if sys.platform == "win32":
return f"Remove-Item -Recurse -Force {_powershell_quote(str(location))}"
return f"rm -rf {shlex.quote(str(location))}"


def _shell_command(arguments: List[str]) -> str:
"""Command line for the shell of the platform: PowerShell on Windows."""
if sys.platform == "win32":
return f'rmdir /s /q "{location}"'
return f"rm -rf {location}"
command = " ".join(_powershell_quote(argument) for argument in arguments)
if command.startswith("'"):
# A quoted string is not a command in PowerShell
return f"& {command}"
return command
return shlex.join(arguments)


_POWERSHELL_SAFE = re.compile(r"[\w./\\:=+-]+")
Comment thread
woutdenolf marked this conversation as resolved.
Resolved
# Characters allowed in PowerShell arguments without quoting


def _powershell_quote(argument: str) -> str:
"""Argument quoted for PowerShell when needed."""
if _POWERSHELL_SAFE.fullmatch(argument):
return argument
return "'" + argument.replace("'", "''") + "'"


def _absolute_workflow(workflow: str) -> str:
"""Workflow that does not depend on the working directory."""
if os.path.isfile(workflow):
return os.path.abspath(workflow)
return workflow
Comment thread
woutdenolf marked this conversation as resolved.
Resolved


def command_in_environment(
Expand Down
14 changes: 14 additions & 0 deletions src/ewoks/tests/requirements/test_install_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

import pytest

from ...__main__ import _remove_command
from ...__main__ import _shell_command
from ..._requirements import environment_name
from ..._requirements.utils.environment import Environment
from ...bindings import load_graph
Expand All @@ -27,6 +29,18 @@
environment created for them."""


def test_printed_commands_with_spaces(tmp_path):
"""The printed commands work in the shell of the platform."""
location = tmp_path / "ewoks envs"
python = str(location / "python")
if sys.platform == "win32":
assert _shell_command([python, "-m", "ewoks"]) == f"& '{python}' -m ewoks"
assert _remove_command(location) == f"Remove-Item -Recurse -Force '{location}'"
else:
assert _shell_command([python, "-m", "ewoks"]) == f"'{python}' -m ewoks"
assert _remove_command(location) == f"rm -rf '{location}'"


def test_install_with_files(fast_manager_case, env_root):
files = fast_manager_case.native_files(DISTRIBUTIONS, PYTHON_VERSION)
if not files:
Expand Down
Loading