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)
def supports_color() -> bool: """ Returns True if the running system's terminal supports color, and False otherwise. """ supported_platform = is_posix_os() or (is_win_os() and load_colorama()) is_a_tty = hasattr( sys.stdout, 'isatty') and sys.stdout.isatty() # isatty is not always present return supported_platform and is_a_tty
def test_update_command(self): exit_code: int = command_init.entry_point(args=[]) self.assertEqual(0, exit_code) if is_win_os(): self.assertTrue(os.path.isfile(PYTHON_PATH_VENV_WIN)) self.assertTrue(os.path.isfile(PIP_PATH_VENV_WIN)) python_path = PYTHON_PATH_VENV_WIN elif is_posix_os(): self.assertTrue(os.path.isfile(PYTHON_PATH_VENV_POSIX)) self.assertTrue(os.path.isfile(PIP_PATH_VENV_POSIX)) python_path = PYTHON_PATH_VENV_POSIX self.assertTrue( os.path.isfile(os.path.abspath(_CURRENT_DIR + "/caos.yml"))) with open(os.path.abspath(_CURRENT_DIR + "/caos.yml"), "w") as file: file.write(""" virtual_environment: "venv" dependencies: pip: "latest" requests: "2.0.0" numpy: "^1.18.2" flask: "~1.1.0" """) exit_code: int = command_update.entry_point(args=[]) self.assertEqual(0, exit_code) messages: str = escape_ansi(self.new_stdout.getvalue()) self.assertIn("INFO: Updating PIP...", messages) self.assertIn("SUCCESS: PIP was successfully updated", messages) self.assertIn("INFO: Installing dependencies...", messages) self.assertIn("SUCCESS: All dependencies have been installed", messages) 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: self.fail("pip list failed") output: str = pip_list_process.stdout.lower() self.assertIn("pip", output) self.assertIn("requests", output) self.assertIn("numpy", output) self.assertIn("flask", output)
def test_pip_command_missing_binary(self): exit_code: int = command_init.entry_point(args=[]) self.assertEqual(0, exit_code) if is_win_os(): self.assertTrue(os.path.isfile(PIP_PATH_VENV_WIN)) os.remove(PIP_PATH_VENV_WIN) elif is_posix_os(): self.assertTrue(os.path.isfile(PIP_PATH_VENV_POSIX)) os.remove(PIP_PATH_VENV_POSIX) with self.assertRaises(MissingBinaryException) as context: command_pip.entry_point(args=["search", "caos"]) self.assertIn(_MISSING_PIP_BINARY_MESSAGE, str(context.exception))
def test_python_command_missing_binary(self): exit_code: int = command_init.entry_point(args=[]) self.assertEqual(0, exit_code) if is_win_os(): self.assertTrue(os.path.isfile(PYTHON_PATH_VENV_WIN)) os.remove(PYTHON_PATH_VENV_WIN) elif is_posix_os(): self.assertTrue(os.path.isfile(PYTHON_PATH_VENV_POSIX)) os.remove(PYTHON_PATH_VENV_POSIX) with self.assertRaises(MissingBinaryException) as context: command_python.entry_point(args=["-c", "print('Hello World')"]) self.assertIn(_MISSING_PYTHON_BINARY_MESSAGE, str(context.exception))
def test_init_command_venv_binaries(self): exit_code: int = command_init.entry_point(args=[""]) self.assertEqual(0, exit_code) if is_win_os(): self.assertTrue(os.path.isfile(PYTHON_PATH_VENV_WIN)) self.assertTrue(os.path.isfile(PIP_PATH_VENV_WIN)) os.remove(PYTHON_PATH_VENV_WIN) os.remove(PIP_PATH_VENV_WIN) elif is_posix_os(): self.assertTrue(os.path.isfile(PYTHON_PATH_VENV_POSIX)) self.assertTrue(os.path.isfile(PIP_PATH_VENV_POSIX)) os.remove(PYTHON_PATH_VENV_POSIX) os.remove(PIP_PATH_VENV_POSIX) self._restore_stdout() self._redirect_stdout() with self.assertRaises(MissingBinaryException) as context: command_init.entry_point(args=[]) self.assertIn(_MISSING_PYTHON_ERROR_MESSAGE, str(context.exception))
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)
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)
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)