def detect_windows_subsystem_test(self): # Dont raise test result = OSInfo.detect_windows_subsystem() if not OSInfo.bash_path() or platform.system() != "Windows": self.assertEqual(None, result) else: self.assertEqual(str, type(result))
def unix_path(path, path_flavor=None): """"Used to translate windows paths to MSYS unix paths like c/users/path/to/file. Not working in a regular console or MinGW!""" if not path: return None if not OSInfo().is_windows: return path if os.path.exists(path): path = get_cased_path( path ) # if the path doesn't exist (and abs) we cannot guess the casing path_flavor = path_flavor or OSInfo.detect_windows_subsystem() or MSYS2 path = path.replace(":/", ":\\") pattern = re.compile(r'([a-z]):\\', re.IGNORECASE) path = pattern.sub('/\\1/', path).replace('\\', '/') if path_flavor in (MSYS, MSYS2): return path.lower() elif path_flavor == CYGWIN: return '/cygdrive' + path.lower() elif path_flavor == WSL: return '/mnt' + path[0:2].lower() + path[2:] elif path_flavor == SFU: path = path.lower() return '/dev/fs' + path[0] + path[1:].capitalize() return None
def content(self): os_info = OSInfo() result = {} if os_info.is_windows and not os_info.is_posix: activate, deactivate, envfile = self._cmd_lines() result["activate{}.bat".format( self.suffix)] = os.linesep.join(activate) result["deactivate{}.bat".format( self.suffix)] = os.linesep.join(deactivate) result["environment{}.bat.env".format( self.suffix)] = os.linesep.join(envfile) activate, deactivate, envfile = self._ps1_lines() result["activate{}.ps1".format( self.suffix)] = os.linesep.join(activate) result["deactivate{}.ps1".format( self.suffix)] = os.linesep.join(deactivate) result["environment{}.ps1.env".format( self.suffix)] = os.linesep.join(envfile) activate, deactivate, envfile = self._sh_lines() result["activate{}.sh".format(self.suffix)] = os.linesep.join(activate) result["deactivate{}.sh".format( self.suffix)] = os.linesep.join(deactivate) result["environment{}.sh.env".format( self.suffix)] = os.linesep.join(envfile) return result
def run(self, command, output=True, cwd=None, win_bash=False, subsystem=None, msys_mingw=True, ignore_errors=False, run_environment=False): def _run(): if not win_bash: return self._conan_runner(command, output, os.path.abspath(RUN_LOG_NAME), cwd) # FIXME: run in windows bash is not using output return tools.run_in_windows_bash(self, bashcmd=command, cwd=cwd, subsystem=subsystem, msys_mingw=msys_mingw) if run_environment: with tools.run_environment(self): if OSInfo().is_macos: command = 'DYLD_LIBRARY_PATH="%s" %s' % (os.environ.get( 'DYLD_LIBRARY_PATH', ''), command) retcode = _run() else: retcode = _run() if not ignore_errors and retcode != 0: raise ConanException("Error %d while executing %s" % (retcode, command)) return retcode
def __init__(self, runner=None, os_info=None, tool=None, recommends=False): os_info = os_info or OSInfo() self._is_up_to_date = False self._tool = tool or self._create_tool(os_info) self._tool._sudo_str = "sudo " if self._is_sudo_enabled() else "" self._tool._runner = runner or ConanRunner() self._tool._recommends = recommends
def content(self): result = {} def _call_files(flavor, activate_tpl, deactivate_tpl, file_ext=None): file_ext = file_ext or flavor environment_filename = "environment{}.{}.env".format( self.suffix, file_ext) activate, deactivate, envfile = self._files( flavor, activate_tpl, deactivate_tpl, environment_filename) result["activate{}.{}".format(self.suffix, file_ext)] = activate result["deactivate{}.{}".format(self.suffix, file_ext)] = deactivate result[environment_filename] = envfile os_info = OSInfo() if os_info.is_windows and not os_info.is_posix: _call_files(VirtualEnvGenerator.CMD_FLAVOR, cmd_activate_tpl, cmd_deactivate_tpl, 'bat') _call_files(VirtualEnvGenerator.PS1_FLAVOR, ps1_activate_tpl, ps1_deactivate_tpl) _call_files(VirtualEnvGenerator.SH_FLAVOR, sh_activate_tpl, sh_deactivate_tpl) return result
def __init__(self, conanfile): super(CustomRunEnvGenerator, self).__init__(conanfile) run_env = RunEnvironment(conanfile) self.env = run_env.vars os_info = OSInfo() if os_info.is_posix: self.env['FONTCONFIG_PATH'] = "/etc/fonts"
def __init__(self, conanfile, win_bash=False): self._conanfile = conanfile self._win_bash = win_bash self.subsystem = OSInfo().detect_windows_subsystem( ) if self._win_bash else None self._deps_cpp_info = conanfile.deps_cpp_info self._arch = conanfile.settings.get_safe("arch") self._build_type = conanfile.settings.get_safe("build_type") self._compiler = conanfile.settings.get_safe("compiler") self._libcxx = conanfile.settings.get_safe("compiler.libcxx") # Set the generic objects before mapping to env vars to let the user # alter some value self.libs = copy.copy(self._deps_cpp_info.libs) self.include_paths = copy.copy(self._deps_cpp_info.include_paths) self.library_paths = copy.copy(self._deps_cpp_info.lib_paths) self.defines = self._configure_defines() # Will go to CFLAGS and CXXFLAGS ["-m64" "-m32", "-g", "-s"] self.flags = self._configure_flags() # Only c++ flags [-stdlib, -library], will go to CXXFLAGS self.cxx_flags = self._configure_cxx_flags() # Not -L flags, ["-m64" "-m32"] self.link_flags = self._configure_link_flags() # TEST! # Not declared by default self.fpic = None
def run(self, command, output=True, cwd=None, win_bash=False, subsystem=None, msys_mingw=True, ignore_errors=False, run_environment=False, with_login=True, env="conanbuildenv"): command = environment_wrap_command(env, command, cwd=self.generators_folder) def _run(): if not win_bash: return self._conan_runner(command, output, os.path.abspath(RUN_LOG_NAME), cwd) # FIXME: run in windows bash is not using output return tools.run_in_windows_bash(self, bashcmd=command, cwd=cwd, subsystem=subsystem, msys_mingw=msys_mingw, with_login=with_login) if run_environment: # When using_build_profile the required environment is already applied through # 'conanfile.env' in the contextmanager 'get_env_context_manager' with tools.run_environment(self) if not self._conan_using_build_profile else no_op(): if OSInfo().is_macos and isinstance(command, string_types): # Security policy on macOS clears this variable when executing /bin/sh. To # keep its value, set it again inside the shell when running the command. command = 'DYLD_LIBRARY_PATH="%s" DYLD_FRAMEWORK_PATH="%s" %s' % \ (os.environ.get('DYLD_LIBRARY_PATH', ''), os.environ.get("DYLD_FRAMEWORK_PATH", ''), command) retcode = _run() else: retcode = _run() if not ignore_errors and retcode != 0: raise ConanException("Error %d while executing %s" % (retcode, command)) return retcode
def run(self, command, output=True, cwd=None, win_bash=False, subsystem=None, msys_mingw=True, ignore_errors=False, run_environment=False, with_login=True, env=None): # NOTE: "self.win_bash" is the new parameter "win_bash" for Conan 2.0 def _run(cmd, _env): # FIXME: run in windows bash is not using output if platform.system() == "Windows": if win_bash: return tools.run_in_windows_bash(self, bashcmd=cmd, cwd=cwd, subsystem=subsystem, msys_mingw=msys_mingw, with_login=with_login) elif self.win_bash: # New, Conan 2.0 from conan.tools.microsoft.subsystems import run_in_windows_bash return run_in_windows_bash(self, command=cmd, cwd=cwd, env=_env) if _env is None: _env = "conanbuild" wrapped_cmd = environment_wrap_command(self, _env, cmd, cwd=self.generators_folder) return self._conan_runner(wrapped_cmd, output, os.path.abspath(RUN_LOG_NAME), cwd) if run_environment: # When using_build_profile the required environment is already applied through # 'conanfile.env' in the contextmanager 'get_env_context_manager' with tools.run_environment( self) if not self._conan_using_build_profile else no_op(): if OSInfo().is_macos and isinstance(command, string_types): # Security policy on macOS clears this variable when executing /bin/sh. To # keep its value, set it again inside the shell when running the command. command = 'DYLD_LIBRARY_PATH="%s" DYLD_FRAMEWORK_PATH="%s" %s' % \ (os.environ.get('DYLD_LIBRARY_PATH', ''), os.environ.get("DYLD_FRAMEWORK_PATH", ''), command) retcode = _run(command, env) else: retcode = _run(command, env) if not ignore_errors and retcode != 0: raise ConanException("Error %d while executing %s" % (retcode, command)) return retcode
def __init__(self, runner=None, os_info=None, tool=None): env_sudo = os.environ.get("CONAN_SYSREQUIRES_SUDO", None) self._sudo = (env_sudo != "False" and env_sudo != "0") os_info = os_info or OSInfo() self._is_up_to_date = False self._tool = tool or self._create_tool(os_info) self._tool._sudo_str = "sudo " if self._sudo else "" self._tool._runner = runner or ConanRunner()
def __init__(self, runner=None, os_info=None, tool=None, recommends=False, output=None, conanfile=None): output = output if output else conanfile.output if conanfile else None self._output = default_output(output, 'conans.client.tools.system_pm.SystemPackageTool') os_info = os_info or OSInfo() self._is_up_to_date = False self._tool = tool or self._create_tool(os_info, output=self._output) self._tool._sudo_str = self._get_sudo_str() self._tool._runner = runner or ConanRunner(output=self._output) self._tool._recommends = recommends self._conanfile = conanfile
def content(self): result = {} os_info = OSInfo() if os_info.is_windows and not os_info.is_posix: result.update(env_files(self.env, self.append_with_spaces, BAT_FLAVOR, self.output_path, self.suffix, self.venv_name)) result.update(env_files(self.env, self.append_with_spaces, PS1_FLAVOR, self.output_path, self.suffix, self.venv_name)) result.update(env_files(self.env, self.append_with_spaces, SH_FLAVOR, self.output_path, self.suffix, self.venv_name)) return result
def short_path(func): if platform.system() == "Windows" or OSInfo().is_cygwin: # Not for other subsystems from conans.util.windows import path_shortener def wrap(self, *args, **kwargs): p = func(self, *args, **kwargs) return path_shortener(p, self._short_paths) return wrap else: return func
def _run_add_repository_test(repository, gpg_key, sudo, isatty, update): sudo_cmd = "" if sudo: sudo_cmd = "sudo " if isatty else "sudo -A " runner = RunnerOrderedMock() runner.commands.append( ("{}apt-add-repository {}".format(sudo_cmd, repository), 0)) if gpg_key: runner.commands.append( ("wget -qO - {} | {}apt-key add -".format( gpg_key, sudo_cmd), 0)) if update: runner.commands.append( ("{}apt-get update".format(sudo_cmd), 0)) with tools.environment_append( {"CONAN_SYSREQUIRES_SUDO": str(sudo)}): os_info = OSInfo() os_info.is_macos = False os_info.is_linux = True os_info.is_windows = False os_info.linux_distro = "debian" patched_with_apt.return_value = True new_out = StringIO() spt = SystemPackageTool(runner=runner, os_info=os_info, output=ConanOutput(new_out)) spt.add_repository(repository=repository, repo_key=gpg_key, update=update) self.assertEqual(len(runner.commands), 0)
def __init__(self, conanfile, win_bash=False, include_rpath_flags=False): """ FIXME: include_rpath_flags CONAN 2.0 to default True? Could break many packages in center """ self._conanfile = conanfile self._win_bash = win_bash self._include_rpath_flags = include_rpath_flags self.subsystem = OSInfo().detect_windows_subsystem( ) if self._win_bash else None self._deps_cpp_info = conanfile.deps_cpp_info self._os = conanfile.settings.get_safe("os") self._os_version = conanfile.settings.get_safe("os.version") self._os_sdk = conanfile.settings.get_safe("os.sdk") self._os_subsystem = conanfile.settings.get_safe("os.subsystem") self._arch = conanfile.settings.get_safe("arch") self._os_target, self._arch_target = get_target_os_arch(conanfile) self._build_type = conanfile.settings.get_safe("build_type") self._compiler = conanfile.settings.get_safe("compiler") conan_v2_error("compiler setting should be defined.", not self._compiler) self._compiler_version = conanfile.settings.get_safe( "compiler.version") self._compiler_runtime = conanfile.settings.get_safe( "compiler.runtime") self._libcxx = conanfile.settings.get_safe("compiler.libcxx") self._cppstd = cppstd_from_settings(conanfile.settings) # Set the generic objects before mapping to env vars to let the user # alter some value self.libs = list(self._deps_cpp_info.libs) self.libs.extend(list(self._deps_cpp_info.system_libs)) self.include_paths = list(self._deps_cpp_info.include_paths) self.library_paths = list(self._deps_cpp_info.lib_paths) self.defines = self._configure_defines() # Will go to CFLAGS and CXXFLAGS ["-m64" "-m32", "-g", "-s"] self.flags = self._configure_flags() # Only c++ flags [-stdlib, -library], will go to CXXFLAGS self.cxx_flags = self._configure_cxx_flags() # cpp standard self.cppstd_flag = cppstd_flag(conanfile.settings) # Not -L flags, ["-m64" "-m32"] self.link_flags = self._configure_link_flags() # TEST! # Precalculate -fPIC self.fpic = self._configure_fpic() # Precalculate build, host, target triplets self.build, self.host, self.target = self._get_host_build_target_flags( )
def __init__(self, runner=None, os_info=None, tool=None, recommends=False): env_sudo = os.environ.get("CONAN_SYSREQUIRES_SUDO", None) self._sudo = (env_sudo != "False" and env_sudo != "0") if env_sudo is None and os.name == 'posix' and os.geteuid() == 0: self._sudo = False if env_sudo is None and os.name == 'nt': self._sudo = False os_info = os_info or OSInfo() self._is_up_to_date = False self._tool = tool or self._create_tool(os_info) self._tool._sudo_str = "sudo " if self._sudo else "" self._tool._runner = runner or ConanRunner() self._tool._recommends = recommends
def conditional_parameter_expansion_test(self): # https://github.com/conan-io/conan/issues/3911 client = TestClient() client.save({"conanfile.txt": ""}) client.run("profile new default --detect") client.run("profile update env.PREPEND_VAR=[1,2,three] default") client.run("install . -g virtualenv") activate = load(os.path.join(client.current_folder, "activate.sh")) self.assertIn( "PREPEND_VAR=\"1\":\"2\":\"three\"${PREPEND_VAR+:$PREPEND_VAR}", activate) client.runner("%s -c 'source \"%s/activate.sh\" && env'" % (OSInfo.bash_path(), client.current_folder)) # Check no trailing path separator ":" self.assertNotIn("PREPEND_VAR=1:2:three:", client.out) self.assertIn("PREPEND_VAR=1:2:three", client.out) # Check correct value # Check old value is preserved client.runner( "%s -c 'export PREPEND_VAR=kk && source \"%s/activate.sh\" && env'" % (OSInfo.bash_path(), client.current_folder)) self.assertIn("PREPEND_VAR=1:2:three:kk", client.out)
def test_opensuse_zypper_aptitude(self): # https://github.com/conan-io/conan/issues/8737 os_info = OSInfo() os_info.is_linux = True os_info.is_solaris = False os_info.is_macos = False os_info.is_windows = False os_info.linux_distro = "opensuse" runner = RunnerMock() with tools.environment_append({"CONAN_SYSREQUIRES_SUDO": "False"}): spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "zypper --non-interactive ref")
def content(self): os_info = OSInfo() result = {} if os_info.is_windows and not os_info.is_posix: activate, deactivate = self._cmd_lines() result["activate.bat"] = os.linesep.join(activate) result["deactivate.bat"] = os.linesep.join(deactivate) activate, deactivate = self._ps1_lines() result["activate.ps1"] = os.linesep.join(activate) result["deactivate.ps1"] = os.linesep.join(deactivate) activate, deactivate = self._sh_lines() result["activate.sh"] = os.linesep.join(activate) result["deactivate.sh"] = os.linesep.join(deactivate) return result
def get_linux_error_message(): """ Get error message for Linux platform if distro is supported, None otherwise """ os_info = OSInfo() update_command = None if os_info.with_apt: update_command = "sudo -A apt-get update" elif os_info.with_yum: update_command = "sudo -A yum update -y" elif os_info.with_zypper: update_command = "sudo -A zypper --non-interactive ref" elif os_info.with_pacman: update_command = "sudo -A pacman -Syyu --noconfirm" return ("Command '{0}' failed".format(update_command) if update_command is not None else None)
def add_repositories_exception_cases_test(self): os_info = OSInfo() os_info.is_macos = False os_info.is_linux = True os_info.is_windows = False os_info.linux_distro = "fedora" # Will instantiate DnfTool with six.assertRaisesRegex(self, ConanException, "add_repository not implemented"): new_out = StringIO() spt = SystemPackageTool(os_info=os_info, output=ConanOutput(new_out)) spt.add_repository(repository="deb http://repo/url/ saucy universe multiverse", repo_key=None)
def run(self, command, output=True, cwd=None, win_bash=False, subsystem=None, msys_mingw=True, ignore_errors=False, run_environment=False, with_login=True): def _run(): if not win_bash: return self._conan_runner(command, output, os.path.abspath(RUN_LOG_NAME), cwd) # FIXME: run in windows bash is not using output return tools.run_in_windows_bash(self, bashcmd=command, cwd=cwd, subsystem=subsystem, msys_mingw=msys_mingw, with_login=with_login) if run_environment: # When using_build_profile the required environment is already applied through 'conanfile.env' # in the contextmanager 'get_env_context_manager' with tools.run_environment( self) if not self._conan_using_build_profile else no_op(): if OSInfo().is_macos: command = 'DYLD_LIBRARY_PATH="%s" DYLD_FRAMEWORK_PATH="%s" %s' % \ (os.environ.get('DYLD_LIBRARY_PATH', ''), os.environ.get("DYLD_FRAMEWORK_PATH", ''), command) retcode = _run() else: retcode = _run() if not ignore_errors and retcode != 0: raise ConanException("Error %d while executing %s" % (retcode, command)) return retcode
def __init__(self, conanfile, win_bash=False, include_rpath_flags=False): """ FIXME: include_rpath_flags CONAN 2.0 to default True? Could break many packages in center """ self._conanfile = conanfile self._win_bash = win_bash self._include_rpath_flags = include_rpath_flags self.subsystem = OSInfo().detect_windows_subsystem( ) if self._win_bash else None self._deps_cpp_info = conanfile.deps_cpp_info self._arch = conanfile.settings.get_safe("arch") self._build_type = conanfile.settings.get_safe("build_type") self._compiler = conanfile.settings.get_safe("compiler") self._compiler_version = conanfile.settings.get_safe( "compiler.version") self._libcxx = conanfile.settings.get_safe("compiler.libcxx") self._cppstd = conanfile.settings.get_safe("cppstd") # Set the generic objects before mapping to env vars to let the user # alter some value self.libs = copy.copy(self._deps_cpp_info.libs) self.include_paths = copy.copy(self._deps_cpp_info.include_paths) self.library_paths = copy.copy(self._deps_cpp_info.lib_paths) self.defines = self._configure_defines() # Will go to CFLAGS and CXXFLAGS ["-m64" "-m32", "-g", "-s"] self.flags = self._configure_flags() # Only c++ flags [-stdlib, -library], will go to CXXFLAGS self.cxx_flags = self._configure_cxx_flags() # cpp standard self.cppstd_flag = cppstd_flag(self._compiler, self._compiler_version, self._cppstd) # Not -L flags, ["-m64" "-m32"] self.link_flags = self._configure_link_flags() # TEST! # Not declared by default self.fpic = None # Precalculate build, host, target triplets self.build, self.host, self.target = self._get_host_build_target_flags( )
def verify_update_test(self): # https://github.com/conan-io/conan/issues/3142 with tools.environment_append({"CONAN_SYSREQUIRES_SUDO": "False", "CONAN_SYSREQUIRES_MODE": "Verify"}): runner = RunnerMock() # fake os info to linux debian, default sudo os_info = OSInfo() os_info.is_macos = False os_info.is_linux = True os_info.is_windows = False os_info.linux_distro = "debian" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, None) self.assertIn('Not updating system_requirements. CONAN_SYSREQUIRES_MODE=verify', self.out)
def path_shortener(path, short_paths): """ short_paths is 4-state: False: Never shorten the path True: Always shorten the path, create link if not existing None: Use shorten path only if already exists, not create """ use_always_short_paths = get_env("CONAN_USE_ALWAYS_SHORT_PATHS", False) short_paths = use_always_short_paths or short_paths if short_paths is False or os.getenv("CONAN_USER_HOME_SHORT") == "None": return path link = os.path.join(path, CONAN_LINK) if os.path.exists(link): return load(link) elif short_paths is None: return path if os.path.exists(path): rmdir(path) short_home = os.getenv("CONAN_USER_HOME_SHORT") if not short_home: if OSInfo().is_cygwin: try: cmd = ['cygpath', path, '--unix'] out, _ = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=False).communicate() out = decode_text(out) if out.startswith('/cygdrive/'): # It was a Windows 'path' _, _, drive, _ = out.split('/', 3) short_home = os.path.join('/cygdrive', drive, '.conan') else: # It was a cygwin path, use a path inside the user home short_home = os.path.join(os.path.expanduser("~"), '.conan_short') except Exception: raise ConanException( "Conan failed to create the short_paths home for path '{}'" " in Cygwin. Please report this issue. You can use environment" " variable 'CONAN_USER_HOME_SHORT' to set the short_paths" " home.".format(path)) else: drive = os.path.splitdrive(path)[0] short_home = os.path.join(drive, os.sep, ".conan") mkdir(short_home) # Workaround for short_home living in NTFS file systems. Give full control permission # to current user to avoid # access problems in cygwin/msys2 windows subsystems when using short_home folder try: userdomain, username = os.getenv("USERDOMAIN"), os.environ["USERNAME"] domainname = "%s\%s" % (userdomain, username) if userdomain else username cmd = r'cacls %s /E /G "%s":F' % (short_home, domainname) subprocess.check_output( cmd, stderr=subprocess.STDOUT) # Ignoring any returned output, quiet except (subprocess.CalledProcessError, EnvironmentError): # cmd can fail if trying to set ACL in non NTFS drives, ignoring it. pass redirect = hashed_redirect(short_home, path) if not redirect: logger.warning("Failed to create a deterministic short path in %s", short_home) redirect = tempfile.mkdtemp(dir=short_home, prefix="") # Save the full path of the local cache directory where the redirect is from. # This file is for debugging purposes and not used by Conan. save(os.path.join(redirect, CONAN_REAL_PATH), path) # This "1" is the way to have a non-existing directory, so commands like # shutil.copytree() to it, works. It can be removed without compromising the # temp folder generator and conan-links consistency redirect = os.path.join(redirect, "1") save(link, redirect) return redirect
def system_package_tool_test(self, patched_with_apt): with tools.environment_append({"CONAN_SYSREQUIRES_SUDO": "True"}): runner = RunnerMock() # fake os info to linux debian, default sudo os_info = OSInfo() os_info.is_macos = False os_info.is_linux = True os_info.is_windows = False patched_with_apt.return_value = True os_info.linux_distro = "debian" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A apt-get update") os_info.linux_distro = "ubuntu" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A apt-get update") os_info.linux_distro = "knoppix" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A apt-get update") os_info.linux_distro = "neon" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A apt-get update") # We'll be testing non-Ubuntu and non-Debian-based distros. patched_with_apt.return_value = False with mock.patch("conans.client.tools.oss.which", return_value=True): os_info.linux_distro = "fedora" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A dnf check-update -y") # Without DNF in the path, os_info.linux_distro = "fedora" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A yum check-update -y") os_info.linux_distro = "opensuse" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A zypper --non-interactive ref") os_info.linux_distro = "redhat" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.install("a_package", force=False) self.assertEqual(runner.command_called, "rpm -q a_package") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "sudo -A yum install -y a_package") settings = MockSettings({ "arch": "x86", "arch_build": "x86_64", "os": "Linux", "os_build": "Linux" }) conanfile = MockConanfile(settings) spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out, conanfile=conanfile) spt.install("a_package", force=False) self.assertEqual(runner.command_called, "rpm -q a_package.i?86") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "sudo -A yum install -y a_package.i?86") os_info.linux_distro = "debian" patched_with_apt.return_value = True spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) with self.assertRaises(ConanException): runner.return_ok = False spt.install("a_package") self.assertEqual( runner.command_called, "sudo -A apt-get install -y --no-install-recommends a_package" ) runner.return_ok = True spt.install("a_package", force=False) self.assertEqual( runner.command_called, 'dpkg-query -W -f=\'${Status}\' a_package | grep -q "ok installed"' ) os_info.is_macos = True os_info.is_linux = False os_info.is_windows = False patched_with_apt.return_value = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "brew update") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "brew install a_package") os_info.is_freebsd = True os_info.is_macos = False patched_with_apt.return_value = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A pkg update") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "sudo -A pkg install -y a_package") spt.install("a_package", force=False) self.assertEqual(runner.command_called, "pkg info a_package") # Chocolatey is an optional package manager on Windows if platform.system() == "Windows" and which("choco.exe"): os_info.is_freebsd = False os_info.is_windows = True patched_with_apt.return_value = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out, tool=ChocolateyTool(output=self.out)) spt.update() self.assertEqual(runner.command_called, "choco outdated") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "choco install --yes a_package") spt.install("a_package", force=False) self.assertEqual( runner.command_called, 'choco search --local-only --exact a_package | ' 'findstr /c:"1 packages installed."') with tools.environment_append({"CONAN_SYSREQUIRES_SUDO": "False"}): os_info = OSInfo() os_info.is_linux = True os_info.linux_distro = "redhat" patched_with_apt.return_value = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.install("a_package", force=True) self.assertEqual(runner.command_called, "yum install -y a_package") spt.update() self.assertEqual(runner.command_called, "yum check-update -y") os_info.linux_distro = "ubuntu" patched_with_apt.return_value = True spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.install("a_package", force=True) self.assertEqual( runner.command_called, "apt-get install -y --no-install-recommends a_package") spt.update() self.assertEqual(runner.command_called, "apt-get update") for arch, distro_arch in { "x86_64": "", "x86": ":i386", "ppc32": ":powerpc", "ppc64le": ":ppc64el", "armv7": ":arm", "armv7hf": ":armhf", "armv8": ":arm64", "s390x": ":s390x" }.items(): settings = MockSettings({ "arch": arch, "arch_build": "x86_64", "os": "Linux", "os_build": "Linux" }) conanfile = MockConanfile(settings) spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out, conanfile=conanfile) spt.install("a_package", force=True) self.assertEqual( runner.command_called, "apt-get install -y --no-install-recommends a_package%s" % distro_arch) for arch, distro_arch in {"x86_64": "", "x86": ":all"}.items(): settings = MockSettings({ "arch": arch, "arch_build": "x86_64", "os": "Linux", "os_build": "Linux" }) conanfile = MockConanfile(settings) spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out, conanfile=conanfile) spt.install("a_package", force=True, arch_names={"x86": "all"}) self.assertEqual( runner.command_called, "apt-get install -y --no-install-recommends a_package%s" % distro_arch) os_info.is_macos = True os_info.is_linux = False os_info.is_windows = False patched_with_apt.return_value = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "brew update") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "brew install a_package") os_info.is_freebsd = True os_info.is_macos = False os_info.is_windows = False patched_with_apt.return_value = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "pkg update") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "pkg install -y a_package") spt.install("a_package", force=False) self.assertEqual(runner.command_called, "pkg info a_package") os_info.is_solaris = True os_info.is_freebsd = False os_info.is_windows = False patched_with_apt.return_value = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "pkgutil --catalog") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "pkgutil --install --yes a_package") with tools.environment_append({"CONAN_SYSREQUIRES_SUDO": "True"}): # Chocolatey is an optional package manager on Windows if platform.system() == "Windows" and which("choco.exe"): os_info.is_solaris = False os_info.is_windows = True patched_with_apt.return_value = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out, tool=ChocolateyTool(output=self.out)) spt.update() self.assertEqual(runner.command_called, "choco outdated") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "choco install --yes a_package") spt.install("a_package", force=False) self.assertEqual( runner.command_called, 'choco search --local-only --exact a_package | ' 'findstr /c:"1 packages installed."')
def basic_test(self, posix_empty_vars=True): env = copy.deepcopy(os.environ) client = TestClient() dep1 = """ import os from conans import ConanFile class BaseConan(ConanFile): name = "base" version = "0.1" def package_info(self): self.env_info.PATH.extend([os.path.join("basedir", "bin"),"samebin"]) self.env_info.LD_LIBRARY_PATH.append(os.path.join("basedir", "lib")) self.env_info.BASE_VAR = "baseValue" self.env_info.SPECIAL_VAR = "baseValue" self.env_info.BASE_LIST = ["baseValue1", "baseValue2"] self.env_info.CPPFLAGS = ["-baseFlag1", "-baseFlag2"] self.env_info.BCKW_SLASH = r"base\\value" """ dep2 = """ import os from conans import ConanFile class DummyConan(ConanFile): name = "dummy" version = "0.1" requires = "base/0.1@lasote/testing" def package_info(self): self.env_info.PATH = [os.path.join("dummydir", "bin"),"samebin"] self.env_info.LD_LIBRARY_PATH.append(os.path.join("dummydir", "lib")) self.env_info.SPECIAL_VAR = "dummyValue" self.env_info.BASE_LIST = ["dummyValue1", "dummyValue2"] self.env_info.CPPFLAGS = ["-flag1", "-flag2"] self.env_info.BCKW_SLASH = r"dummy\\value" """ base = ''' [requires] dummy/0.1@lasote/testing [generators] virtualenv ''' client.save({"conanfile.py": dep1}) client.run("export . lasote/testing") client.save({"conanfile.py": dep2}, clean_first=True) client.run("export . lasote/testing") client.save({"conanfile.txt": base}, clean_first=True) client.run("install . --build") os_info = OSInfo() if os_info.is_windows and not os_info.is_posix: activate = load(os.path.join(client.current_folder, "activate.bat")) self.assertIn('SET PROMPT=(conanenv) %PROMPT%', activate) self.assertIn( 'SET BASE_LIST=dummyValue1;dummyValue2;baseValue1;baseValue2;%BASE_LIST%', activate) self.assertIn('SET BASE_VAR=baseValue', activate) self.assertIn( 'SET CPPFLAGS=-flag1 -flag2 -baseFlag1 -baseFlag2 %CPPFLAGS%', activate) self.assertIn( 'SET LD_LIBRARY_PATH=dummydir\\lib;basedir\\lib;%LD_LIBRARY_PATH%', activate) self.assertIn('SET PATH=dummydir\\bin;basedir\\bin;samebin;%PATH%', activate) self.assertIn('SET SPECIAL_VAR=dummyValue', activate) self.assertIn('SET BCKW_SLASH=dummy\\value', activate) activate = load(os.path.join(client.current_folder, "activate.ps1")) self.assertIn( '$env:BASE_LIST = "dummyValue1;dummyValue2;baseValue1;baseValue2;$env:BASE_LIST"', activate) self.assertIn('$env:BASE_VAR = "baseValue"', activate) self.assertIn( '$env:CPPFLAGS = "-flag1 -flag2 -baseFlag1 -baseFlag2 $env:CPPFLAGS"', activate) self.assertIn( '$env:LD_LIBRARY_PATH = "dummydir\\lib;basedir\\lib;$env:LD_LIBRARY_PATH"', activate) self.assertIn( '$env:PATH = "dummydir\\bin;basedir\\bin;samebin;$env:PATH"', activate) self.assertIn('$env:SPECIAL_VAR = "dummyValue"', activate) self.assertIn('$env:BCKW_SLASH = "dummy\\value"', activate) deactivate = load( os.path.join(client.current_folder, "deactivate.bat")) self.assertIn('SET PROMPT=%s' % env.setdefault('PROMPT', ''), deactivate) self.assertIn('SET BASE_LIST=%s' % env.setdefault('BASE_LIST', ''), deactivate) self.assertIn('SET BASE_VAR=%s' % env.setdefault('BASE_VAR', ''), deactivate) self.assertIn('SET CPPFLAGS=%s' % env.setdefault('CPPFLAGS', ''), deactivate) self.assertIn( 'SET LD_LIBRARY_PATH=%s' % env.setdefault('LD_LIBRARY_PATH', ''), deactivate) self.assertIn('SET PATH=%s' % env.setdefault('PATH', ''), deactivate) self.assertIn( 'SET SPECIAL_VAR=%s' % env.setdefault('SPECIAL_VAR', ''), deactivate) self.assertIn( 'SET BCKW_SLASH=%s' % env.setdefault('BCKW_SLASH', ''), deactivate) deactivate = load( os.path.join(client.current_folder, "deactivate.ps1")) self.assertIn( '$env:BASE_LIST = "%s"' % env.setdefault('BASE_LIST', ''), deactivate) self.assertIn( '$env:BASE_VAR = "%s"' % env.setdefault('BASE_VAR', ''), deactivate) self.assertIn( '$env:CPPFLAGS = "%s"' % env.setdefault('CPPFLAGS', ''), deactivate) self.assertIn( '$env:LD_LIBRARY_PATH = "%s"' % env.setdefault('LD_LIBRARY_PATH', ''), deactivate) self.assertIn('$env:PATH = "%s"' % env.setdefault('PATH', ''), deactivate) self.assertIn( '$env:SPECIAL_VAR = "%s"' % env.setdefault('SPECIAL_VAR', ''), deactivate) self.assertIn( '$env:BCKW_SLASH = "%s"' % env.setdefault('BCKW_SLASH', ''), deactivate) activate = load(os.path.join(client.current_folder, "activate.sh")) self.assertIn('OLD_PS1="$PS1"', activate) self.assertIn('export OLD_PS1', activate) self.assertIn('PS1="(conanenv) $PS1"', activate) self.assertIn('export PS1', activate) self.assertIn( 'BASE_LIST="dummyValue1":"dummyValue2":"baseValue1":"baseValue2"${' 'BASE_LIST+:$BASE_LIST}', activate) self.assertIn('export BASE_LIST', activate) self.assertIn('BASE_VAR="baseValue"', activate) self.assertIn('export BASE_VAR', activate) self.assertIn( 'CPPFLAGS="-flag1 -flag2 -baseFlag1 -baseFlag2 ${CPPFLAGS+ $CPPFLAGS}"', activate) self.assertIn('export CPPFLAGS', activate) self.assertIn('SPECIAL_VAR="dummyValue"', activate) self.assertIn('export SPECIAL_VAR', activate) self.assertIn('BCKW_SLASH="dummy\\value"', activate) self.assertIn('export BCKW_SLASH', activate) if os_info.is_windows: self.assertIn( 'LD_LIBRARY_PATH="dummydir\\lib":"basedir\\lib"${' 'LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}', activate) self.assertIn( 'PATH="dummydir\\bin":"basedir\\bin":"samebin"${PATH+:$PATH}', activate) else: self.assertIn( 'LD_LIBRARY_PATH="dummydir/lib":"basedir/lib"${' 'LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}', activate) self.assertIn( 'PATH="dummydir/bin":"basedir/bin":"samebin"${PATH+:$PATH}', activate) self.assertIn('export LD_LIBRARY_PATH', activate) self.assertIn('export PATH', activate) deactivate = load(os.path.join(client.current_folder, "deactivate.sh")) if posix_empty_vars: self.assertNotIn('unset PS1', deactivate) self.assertIn('unset OLD_PS1', deactivate) self.assertIn('unset BASE_LIST', deactivate) self.assertIn('unset BASE_VAR', deactivate) self.assertIn('unset CPPFLAGS', deactivate) self.assertIn('unset LD_LIBRARY_PATH', deactivate) self.assertIn('PATH="%s"' % env.setdefault('PATH', ''), deactivate) self.assertIn('export PATH', deactivate) self.assertIn('unset SPECIAL_VAR', deactivate) self.assertIn('unset BCKW_SLASH', deactivate) else: self.assertIn('OLD_PS1="%s"' % env.setdefault('OLD_PS1', ''), deactivate) self.assertIn('PS1=$OLD_PS1', deactivate) self.assertIn('export OLD_PS1', deactivate) self.assertNotIn('PS1="%s"' % env.setdefault('PS1', ''), deactivate) self.assertIn('export PS1', deactivate) self.assertIn('BASE_LIST="%s"' % env.setdefault('BASE_LIST', ''), deactivate) self.assertIn('export BASE_LIST', deactivate) self.assertIn('BASE_VAR="%s"' % env.setdefault('BASE_VAR', ''), deactivate) self.assertIn('export BASE_VAR', deactivate) self.assertIn('CPPFLAGS="%s"' % env.setdefault('CPPFLAGS', ''), deactivate) self.assertIn('export CPPFLAGS', deactivate) self.assertIn( 'LD_LIBRARY_PATH="%s"' % env.setdefault('LD_LIBRARY_PATH', ''), deactivate) self.assertIn('export LD_LIBRARY_PATH', deactivate) self.assertIn('PATH="%s"' % env.setdefault('PATH', ''), deactivate) self.assertIn('export PATH', deactivate) self.assertIn( 'SPECIAL_VAR="%s"' % env.setdefault('SPECIAL_VAR', ''), deactivate) self.assertIn('export SPECIAL_VAR', deactivate) self.assertIn('BCKW_SLASH="%s"' % env.setdefault('BCKW_SLASH', ''), deactivate) self.assertIn('export BCKW_SLASH', deactivate)
def run_in_windows_bash(conanfile, bashcmd, cwd=None, subsystem=None, msys_mingw=True, env=None): """ Will run a unix command inside a bash terminal It requires to have MSYS2, CYGWIN, or WSL """ env = env or {} if platform.system() != "Windows": raise ConanException("Command only for Windows operating system") subsystem = subsystem or OSInfo.detect_windows_subsystem() if not subsystem: raise ConanException( "Cannot recognize the Windows subsystem, install MSYS2/cygwin " "or specify a build_require to apply it.") if subsystem == MSYS2 and msys_mingw: # This needs to be set so that msys2 bash profile will set up the environment correctly. env_vars = { "MSYSTEM": ("MINGW32" if conanfile.settings.get_safe("arch") == "x86" else "MINGW64"), "MSYS2_PATH_TYPE": "inherit" } else: env_vars = {} with environment_append(env_vars): hack_env = "" # In the bash.exe from WSL this trick do not work, always the /usr/bin etc at first place if subsystem != WSL: def get_path_value(container, subsystem_name): """Gets the path from the container dict and returns a string with the path for the subsystem_name""" _path_key = next( (name for name in container.keys() if "path" == name.lower()), None) if _path_key: _path_value = container.get(_path_key) if isinstance(_path_value, list): return ":".join([ unix_path(path, path_flavor=subsystem_name) for path in _path_value ]) else: return unix_path(_path_value, path_flavor=subsystem_name) # First get the PATH from the conanfile.env inherited_path = get_path_value(conanfile.env, subsystem) # Then get the PATH from the real env env_path = get_path_value(env, subsystem) # Both together full_env = ":".join(v for v in [env_path, inherited_path] if v) # Put the build_requires and requires path at the first place inside the shell hack_env = ' && PATH="%s:$PATH"' % full_env if full_env else "" for var_name, value in env.items(): if var_name == "PATH": continue hack_env += ' && %s=%s' % (var_name, value) # Needed to change to that dir inside the bash shell if cwd and not os.path.isabs(cwd): cwd = os.path.join(get_cwd(), cwd) curdir = unix_path(cwd or get_cwd(), path_flavor=subsystem) to_run = 'cd "%s"%s && %s ' % (curdir, hack_env, bashcmd) bash_path = OSInfo.bash_path() bash_path = '"%s"' % bash_path if " " in bash_path else bash_path wincmd = '%s --login -c %s' % (bash_path, escape_windows_cmd(to_run)) conanfile.output.info('run_in_windows_bash: %s' % wincmd) # If is there any other env var that we know it contains paths, convert it to unix_path used_special_vars = [ var for var in ["AR", "AS", "RANLIB", "LD", "STRIP", "CC", "CXX"] if var in conanfile.env.keys() ] normalized_env = { p: unix_path(conanfile.env[p], path_flavor=subsystem) for p in used_special_vars } # https://github.com/conan-io/conan/issues/2839 (subprocess=True) with environment_append(normalized_env): return conanfile._conan_runner(wincmd, output=conanfile.output, subprocess=True)
def system_package_tool_test(self): with tools.environment_append({"CONAN_SYSREQUIRES_SUDO": "True"}): runner = RunnerMock() # fake os info to linux debian, default sudo os_info = OSInfo() os_info.is_macos = False os_info.is_linux = True os_info.is_windows = False os_info.linux_distro = "debian" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A apt-get update") os_info.linux_distro = "ubuntu" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A apt-get update") os_info.linux_distro = "knoppix" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A apt-get update") os_info.linux_distro = "neon" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A apt-get update") os_info.linux_distro = "fedora" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A yum update -y") os_info.linux_distro = "opensuse" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A zypper --non-interactive ref") os_info.linux_distro = "redhat" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.install("a_package", force=False) self.assertEqual(runner.command_called, "rpm -q a_package") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "sudo -A yum install -y a_package") os_info.linux_distro = "debian" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) with self.assertRaises(ConanException): runner.return_ok = False spt.install("a_package") self.assertEqual(runner.command_called, "sudo -A apt-get install -y --no-install-recommends a_package") runner.return_ok = True spt.install("a_package", force=False) self.assertEqual(runner.command_called, 'dpkg-query -W -f=\'${Status}\' a_package | grep -q "ok installed"') os_info.is_macos = True os_info.is_linux = False os_info.is_windows = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "brew update") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "brew install a_package") os_info.is_freebsd = True os_info.is_macos = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "sudo -A pkg update") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "sudo -A pkg install -y a_package") spt.install("a_package", force=False) self.assertEqual(runner.command_called, "pkg info a_package") # Chocolatey is an optional package manager on Windows if platform.system() == "Windows" and which("choco.exe"): os_info.is_freebsd = False os_info.is_windows = True spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out, tool=ChocolateyTool(output=self.out)) spt.update() self.assertEqual(runner.command_called, "choco outdated") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "choco install --yes a_package") spt.install("a_package", force=False) self.assertEqual(runner.command_called, 'choco search --local-only --exact a_package | ' 'findstr /c:"1 packages installed."') with tools.environment_append({"CONAN_SYSREQUIRES_SUDO": "False"}): os_info = OSInfo() os_info.is_linux = True os_info.linux_distro = "redhat" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.install("a_package", force=True) self.assertEqual(runner.command_called, "yum install -y a_package") spt.update() self.assertEqual(runner.command_called, "yum update -y") os_info.linux_distro = "ubuntu" spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.install("a_package", force=True) self.assertEqual(runner.command_called, "apt-get install -y --no-install-recommends a_package") spt.update() self.assertEqual(runner.command_called, "apt-get update") os_info.is_macos = True os_info.is_linux = False os_info.is_windows = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "brew update") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "brew install a_package") os_info.is_freebsd = True os_info.is_macos = False os_info.is_windows = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "pkg update") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "pkg install -y a_package") spt.install("a_package", force=False) self.assertEqual(runner.command_called, "pkg info a_package") os_info.is_solaris = True os_info.is_freebsd = False os_info.is_windows = False spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out) spt.update() self.assertEqual(runner.command_called, "pkgutil --catalog") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "pkgutil --install --yes a_package") with tools.environment_append({"CONAN_SYSREQUIRES_SUDO": "True"}): # Chocolatey is an optional package manager on Windows if platform.system() == "Windows" and which("choco.exe"): os_info.is_solaris = False os_info.is_windows = True spt = SystemPackageTool(runner=runner, os_info=os_info, output=self.out, tool=ChocolateyTool(output=self.out)) spt.update() self.assertEqual(runner.command_called, "choco outdated") spt.install("a_package", force=True) self.assertEqual(runner.command_called, "choco install --yes a_package") spt.install("a_package", force=False) self.assertEqual(runner.command_called, 'choco search --local-only --exact a_package | ' 'findstr /c:"1 packages installed."')