Пример #1
0
    def test_yaml_util_get_virtual_environment_from_yaml_custom(self):
        test_caos_yaml = "virtual_environment: 'custom_venv'"
        with open(file=os.path.abspath(get_current_dir() + "/" + "caos.yml"),
                  mode="w") as file:
            file.write(test_caos_yaml)

        self.assertEqual("custom_venv", get_virtual_environment_from_yaml())
Пример #2
0
def create_virtual_env(current_dir: str):
    """
    Raises:
        OpenCaosFileException
        InvalidCaosFileFormat
        WrongKeyTypeInYamlFile
        CreateVirtualEnvironmentException
        MissingBinaryException
    """
    env_name = get_virtual_environment_from_yaml()
    env_path: str = os.path.abspath(current_dir + "/" + env_name)
    if os.path.isdir(env_path):
        caos_command_print(
            command=NAME,
            message=INFO_MESSAGE(
                "The virtual environment already exists so a new one won't be created"
            ))

    else:
        caos_command_print(
            command=NAME,
            message=INFO_MESSAGE("Creating a new virtual environment..."))
        create_env_process: subprocess.CompletedProcess = subprocess.run(
            [
                sys.executable, "-m", DEFAULT_VIRTUAL_ENVIRONMENT_NAME,
                os.path.abspath(get_current_dir() + "/" + env_name)
            ],
            stderr=subprocess.PIPE,
            stdout=subprocess.PIPE,
            universal_newlines=True)

        if create_env_process.returncode != 0:
            raise CreateVirtualEnvironmentException(create_env_process.stderr)

        caos_command_print(
            command=NAME,
            message=SUCCESS_MESSAGE("A new virtual environment was created"))

    if is_win_os():
        pip_path: str = PIP_PATH_VENV_WIN.replace(
            DEFAULT_VIRTUAL_ENVIRONMENT_NAME, env_name)
        python_path: str = PYTHON_PATH_VENV_WIN.replace(
            DEFAULT_VIRTUAL_ENVIRONMENT_NAME, env_name)

    if is_posix_os():
        pip_path: str = PIP_PATH_VENV_POSIX.replace(
            DEFAULT_VIRTUAL_ENVIRONMENT_NAME, env_name)
        python_path: str = PYTHON_PATH_VENV_POSIX.replace(
            DEFAULT_VIRTUAL_ENVIRONMENT_NAME, env_name)

    if not os.path.isfile(pip_path):
        caos_command_print(
            command=NAME,
            message=WARNING_MESSAGE(
                "The virtual environment does not have a 'pip' binary"))

    if not os.path.isfile(python_path):
        raise_missing_python_binary_exception(env_name=env_name)
Пример #3
0
def main(args: List[str]) -> ExitCode:
    current_dir: str = get_current_dir()
    if not os.path.isfile(
            os.path.abspath(current_dir + "/" + CAOS_YAML_FILE_NAME)):
        raise MissingYamlException(
            "No '{}' file found. Try running first 'caos init'".format(
                CAOS_YAML_FILE_NAME))

    if len(args) < 1:
        raise MissingTaskArgument("No task name to execute was given")

    task_name: str = args[0]

    available_tasks: Tasks = get_tasks_from_yaml()

    if not task_name in available_tasks:
        raise TaskNotFound("No task named '{}' was found".format(task_name))

    if len(args) > 1:
        caos_command_print(
            command=NAME,
            message=WARNING_MESSAGE("The tasks can't receive arguments"))

    steps: List[str] = available_tasks[task_name]

    is_unittest: bool = True if isinstance(sys.stdout, StringIO) else False
    for step in steps:
        if step in available_tasks:
            main(args=[step])
            continue

        # The current Unittest for this redirects the stdout to a StringIO() buffer, which is not compatible with
        # subprocess, so for this scenario a subprocess.PIPE is used instead of the sys.stdout to be able to capture
        # the output in the unittests
        step_process: subprocess.CompletedProcess = subprocess.run(
            step,
            stdout=subprocess.PIPE if is_unittest else sys.stdout,
            stderr=subprocess.STDOUT,
            stdin=sys.stdin,
            universal_newlines=True,
            shell=True)

        if is_unittest and step_process.stdout:
            print(step_process.stdout, end="")

        if step_process.returncode != 0:
            raise StepExecutionError(
                "Within the task '{}' the step '{}' returned a non zero exit code"
                .format(task_name, step))

    return ExitCode(0)
Пример #4
0
def main(args: List[str]) -> ExitCode:
    virtual_env_name: str = args[0] if len(args) >= 1 else None
    current_dir: str = get_current_dir()

    simple_yaml_template = None
    simple_init_args = ('--simple', '-s', '-S')
    if virtual_env_name in simple_init_args:
        simple_yaml_template = _CAOS_YAML_TEMPLATE_SIMPLE
        virtual_env_name = None
    create_caos_yaml(current_dir=current_dir,
                     env_name=virtual_env_name,
                     caos_yaml_template=simple_yaml_template)
    if not simple_yaml_template:
        create_virtual_env(current_dir=current_dir)
    return ExitCode(0)
Пример #5
0
    def test_yaml_util_get_dependencies_from_yaml(self):
        test_caos_yaml = """\
        dependencies:
            dep1: "latest"
            dep2: "^1.5.0"
            dep3: "~2"
            dep4: "./dep4-1.0.0-py3-none-any.whl"
            dep5: "./dep5-1.0.0-py3-none-any.dist-info"
        """
        with open(file=os.path.abspath(get_current_dir() + "/" + "caos.yml"),
                  mode="w") as file:
            file.write(test_caos_yaml)

        dependencies = get_dependencies_from_yaml()
        expected_result = {
            "dep1": "dep1",
            "dep2": "~=1.5",
            "dep3": "~=2.0.0",
            "dep4": "./dep4-1.0.0-py3-none-any.whl",
            "dep5": "./dep5-1.0.0-py3-none-any.dist-info"
        }
        self.assertEqual(expected_result, dependencies)
Пример #6
0
    def test_yaml_util_get_tasks_from_yaml(self):
        test_caos_yaml = """\
        tasks:
          test:
            - "caos unittest ./"
          run:
            - "caos python ./main.py"
          test_and_run:
            - test
            - run
            - "echo 'Done'"
        """
        with open(file=os.path.abspath(get_current_dir() + "/" + "caos.yml"),
                  mode="w") as file:
            file.write(test_caos_yaml)

        tasks = get_tasks_from_yaml()
        expected_result = {
            'test': ['caos unittest ./'],
            'run': ['caos python ./main.py'],
            'test_and_run': ['test', 'run', "echo 'Done'"]
        }
        self.assertEqual(expected_result, tasks)
Пример #7
0
def main(args: List[str]) -> ExitCode:
    current_dir: str = get_current_dir()
    if not os.path.isfile(
            os.path.abspath(current_dir + "/" + CAOS_YAML_FILE_NAME)):
        raise_missing_yaml_exception()

    venv_name: str = get_virtual_environment_from_yaml()

    if not os.path.isdir(os.path.abspath(current_dir + "/" + venv_name)):
        raise_missing_virtual_environment_exception(env_name=venv_name)

    if is_win_os():
        python_path: str = PYTHON_PATH_VENV_WIN.replace(
            DEFAULT_VIRTUAL_ENVIRONMENT_NAME, venv_name)
    elif is_posix_os():
        python_path: str = PYTHON_PATH_VENV_POSIX.replace(
            DEFAULT_VIRTUAL_ENVIRONMENT_NAME, venv_name)

    if not os.path.isfile(python_path):
        raise_missing_python_binary_exception(env_name=venv_name)

    # The current Unittest for this redirects the stdout to a StringIO() buffer, which is not compatible with
    # subprocess, so for this scenario a subprocess.PIPE is used instead of the sys.stdout to be able to capture
    # the output in the unittests
    is_unittest: bool = True if isinstance(sys.stdout, StringIO) else False
    python_process: subprocess.CompletedProcess = subprocess.run(
        [python_path] + args,
        stdout=subprocess.PIPE if is_unittest else sys.stdout,
        stderr=subprocess.STDOUT,
        stdin=sys.stdin,
        universal_newlines=True)

    if is_unittest and python_process.stdout:
        print(python_process.stdout)

    return ExitCode(python_process.returncode)
Пример #8
0
def read_caos_yaml() -> CaosYaml:
    """
    Raises:
        OpenCaosFileException
        InvalidCaosFileFormat
    """
    try:
        yaml_path: str = os.path.abspath(get_current_dir() + "/" +
                                         CAOS_YAML_FILE_NAME)
        with open(file=yaml_path, mode="r") as caos_file:
            caos_file_content: str = caos_file.read()
    except Exception as e:
        raise OpenCaosFileException(str(e))

    try:
        caos_yaml: CaosYaml = yaml.load(stream=caos_file_content,
                                        Loader=yaml.FullLoader)
    except RecursionError as e:
        raise RecursionError("Maximum recursion depth exceeded")
    except Exception as e:
        raise InvalidCaosFileFormat(
            "The file does not contain valid YAML syntax: " + str(e))

    return caos_yaml
Пример #9
0
def main(args: List[str]) -> ExitCode:
    current_dir: str = get_current_dir()
    if not os.path.isfile(os.path.abspath(current_dir + "/" + CAOS_YAML_FILE_NAME)):
        raise_missing_yaml_exception()

    venv_name: str = get_virtual_environment_from_yaml()

    if not os.path.isdir(os.path.abspath(current_dir + "/" + venv_name)):
        raise_missing_virtual_environment_exception(env_name=venv_name)

    if is_win_os():
        pip_path: str = PIP_PATH_VENV_WIN.replace(DEFAULT_VIRTUAL_ENVIRONMENT_NAME, venv_name)
        python_path: str = PYTHON_PATH_VENV_WIN.replace(DEFAULT_VIRTUAL_ENVIRONMENT_NAME, venv_name)
    elif is_posix_os():
        pip_path: str = PIP_PATH_VENV_POSIX.replace(DEFAULT_VIRTUAL_ENVIRONMENT_NAME, venv_name)
        python_path: str = PYTHON_PATH_VENV_POSIX.replace(DEFAULT_VIRTUAL_ENVIRONMENT_NAME, venv_name)

    if not os.path.isfile(pip_path):
        raise_missing_pip_binary_exception(env_name=venv_name)
    if not os.path.isfile(python_path):
        raise_missing_python_binary_exception(env_name=venv_name)

    if args:
        caos_command_print(
            command=NAME,
            message=WARNING_MESSAGE("The update command does not support arguments")
        )

    dependencies: Dependencies = get_dependencies_from_yaml()

    is_unittest: bool = True if isinstance(sys.stdout, StringIO) else False

    if "pip" in dependencies:
        if "pip" == dependencies.get("pip"):
            dep: str = "pip"
        else:
            dep: str = "pip{}".format(dependencies.get("pip"))

        caos_command_print(
            command=NAME,
            message=INFO_MESSAGE("Updating PIP...")
        )

        del dependencies["pip"]

        install_pip_process: subprocess.CompletedProcess = subprocess.run(
            [python_path, "-m", "pip", "install", "--force-reinstall", dep],
            stdout=subprocess.PIPE if is_unittest else sys.stdout,
            stderr=subprocess.STDOUT,
            universal_newlines=True
        )

        if install_pip_process.returncode != 0:
            caos_command_print(
                command=NAME,
                message=WARNING_MESSAGE("PIP could not be updated")
            )
        else:
            caos_command_print(
                command=NAME,
                message=SUCCESS_MESSAGE("PIP was successfully updated")
            )

    if not dependencies:
        caos_command_print(
            command=NAME,
            message=INFO_MESSAGE("No dependencies to install")
        )
        return ExitCode(0)

    deps: List[str] = []
    for dep_name, dep_version in dependencies.items():
        if dep_name == dep_version:
            dep = dep_name
        elif dep_version.endswith(".whl") or dep_version.endswith(".dist-info") or dep_version.endswith(".tar.gz"):
            dep = dep_version
        else:
            dep = "{}{}".format(dep_name, dep_version)

        deps.append(dep)

    caos_command_print(
        command=NAME,
        message=INFO_MESSAGE("Installing dependencies...")
    )

    install_deps_process: subprocess.CompletedProcess = subprocess.run(
        [python_path, "-m", "pip", "install", "--force-reinstall"] + deps,
        stdout=subprocess.PIPE if is_unittest else sys.stdout,
        stderr=subprocess.STDOUT,
        universal_newlines=True
    )

    if install_deps_process.returncode != 0:
        caos_command_print(
            command=NAME,
            message=ERROR_MESSAGE("It was not possible to install the dependencies")
        )

        return ExitCode(install_deps_process.returncode)

    caos_command_print(
        command=NAME,
        message=SUCCESS_MESSAGE("All dependencies have been installed")
    )

    return ExitCode(0)
Пример #10
0
import os
import sys
import shutil
import unittest
from io import StringIO
from caos._cli_commands import command_init, command_pip
from caos._internal.console.tools import escape_ansi
from caos._internal.exceptions import MissingBinaryException, MissingVirtualEnvironmentException
from caos._internal.utils.os import is_posix_os, is_win_os
from caos._internal.utils.working_directory import get_current_dir
from caos._internal.constants import DEFAULT_VIRTUAL_ENVIRONMENT_NAME, PIP_PATH_VENV_POSIX, PIP_PATH_VENV_WIN

_CURRENT_DIR = get_current_dir()
_MISSING_PIP_BINARY_MESSAGE = "The virtual environment does not have a 'pip' binary. "\
                              "Try deleting the folder 'venv' and run 'caos init'"
_MISSING_VIRTUAL_ENVIRONMENT_MESSAGE = "No virtual environment 'venv' could be found. Try running first 'caos init'"


class TestCommandPip(unittest.TestCase):
    def _redirect_stdout(self):
        self.new_stdout, self.old_stdout = StringIO(), sys.stdout
        self.new_stderr, self.old_stderr = StringIO(), sys.stderr
        sys.stdout, sys.stderr = self.new_stdout, self.new_stderr

    def _restore_stdout(self):
        sys.stdout, sys.stderr = self.old_stdout, self.old_stderr

    def setUp(self) -> None:
        self._redirect_stdout()
        if os.path.isdir("tmp"):
            shutil.rmtree("tmp")
Пример #11
0
def main(args: List[str]) -> ExitCode:
    current_dir: str = get_current_dir()
    if not os.path.isfile(
            os.path.abspath(current_dir + "/" + CAOS_YAML_FILE_NAME)):
        raise_missing_yaml_exception()

    venv_name: str = get_virtual_environment_from_yaml()

    if not os.path.isdir(os.path.abspath(current_dir + "/" + venv_name)):
        raise_missing_virtual_environment_exception(env_name=venv_name)

    if is_win_os():
        pip_path: str = PIP_PATH_VENV_WIN.replace(
            DEFAULT_VIRTUAL_ENVIRONMENT_NAME, venv_name)
        python_path: str = PYTHON_PATH_VENV_WIN.replace(
            DEFAULT_VIRTUAL_ENVIRONMENT_NAME, venv_name)
    elif is_posix_os():
        pip_path: str = PIP_PATH_VENV_POSIX.replace(
            DEFAULT_VIRTUAL_ENVIRONMENT_NAME, venv_name)
        python_path: str = PYTHON_PATH_VENV_POSIX.replace(
            DEFAULT_VIRTUAL_ENVIRONMENT_NAME, venv_name)

    if not os.path.isfile(pip_path):
        raise_missing_pip_binary_exception(env_name=venv_name)

    if not os.path.isfile(python_path):
        raise_missing_python_binary_exception(env_name=venv_name)

    if args:
        caos_command_print(command=NAME,
                           message=WARNING_MESSAGE(
                               "The check command does not support arguments"))

    yaml_deps: Dependencies = get_dependencies_from_yaml()
    if not yaml_deps:
        caos_command_print(
            command=NAME,
            message=WARNING_MESSAGE(
                "There are no dependencies defined in the '{}' file".format(
                    CAOS_YAML_FILE_NAME)))
        return ExitCode(0)

    pip_list_process: subprocess.CompletedProcess = subprocess.run(
        [python_path, "-m", "pip", "list"],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True)

    if pip_list_process.returncode != 0 and pip_list_process.stderr:
        caos_command_print(
            command=NAME,
            message=ERROR_MESSAGE(
                "It was not possible to check the virtual environment dependencies"
            ))
        return ExitCode(1)

    pip_list_dependency_regex = re.compile(
        "^(?P<name>.+)(( )+)(\()?(?P<version>((\d+)(\.\d+)?(\.\d+)?))(\))?$")
    pip_list_output_by_lines = [
        line.strip() for line in pip_list_process.stdout.split("\n")
    ]

    installed_deps: Dependencies = {}
    for line in pip_list_output_by_lines:
        dep = pip_list_dependency_regex.match(line)
        if dep:
            installed_deps[dep.group("name").strip().lower()] = dep.group(
                "version").strip()

    not_installed_deps: List[str] = []
    for dep in yaml_deps:
        pip_dep = dep.replace("_", "-")
        if pip_dep not in installed_deps:
            not_installed_deps.append(dep)

    if not_installed_deps:
        not_installed_deps = ["'{}'".format(dep) for dep in not_installed_deps]
        caos_command_print(
            command=NAME,
            message=ERROR_MESSAGE(
                "The following dependencies are not installed in the virtual environment: {}"
                .format(", ".join(not_installed_deps))))
        return ExitCode(1)

    caos_command_print(
        command=NAME,
        message=SUCCESS_MESSAGE(
            "All dependencies are installed in the virtual environment"))

    return ExitCode(0)
Пример #12
0
 def test_working_directory_util_current_directory(self):
     self.assertTrue(is_dev_environment())
     self.assertIn("tmp", get_current_dir())