def subprocess_info(self, shell, env, view_settings, window_settings, sublime_settings, executable_temp_files, temp_dirs, executable_name, required_vars, optional_vars, expected_result): with GolangConfigMock(shell, env, view_settings, window_settings, sublime_settings) as mock_context: mock_context.replace_tempdir_env() mock_context.replace_tempdir_view_settings() mock_context.replace_tempdir_window_settings() mock_context.replace_tempdir_sublime_settings() mock_context.make_executable_files(executable_temp_files) mock_context.make_dirs(temp_dirs) if isinstance(expected_result, tuple): tempdir = mock_context.tempdir + os.sep executable_path = expected_result[0].replace('{tempdir}', tempdir) executable_path = shellenv.path_encode(executable_path) env_vars = {} for name, value in expected_result[1].items(): value = value.replace('{tempdir}', tempdir) name = shellenv.env_encode(name) value = shellenv.env_encode(value) env_vars[name] = value expected_result = (executable_path, env_vars) self.assertEquals( expected_result, golangconfig.subprocess_info( executable_name, required_vars, optional_vars=optional_vars, view=mock_context.view, window=mock_context.window ) ) self.assertEqual('', sys.stdout.getvalue()) else: def do_test(): golangconfig.subprocess_info( executable_name, required_vars, optional_vars=optional_vars, view=mock_context.view, window=mock_context.window ) self.assertRaises(expected_result, do_test)
def subprocess_info(self, shell, env, view_settings, window_settings, sublime_settings, executable_temp_files, temp_dirs, executable_name, required_vars, optional_vars, expected_result): with GolangConfigMock(shell, env, view_settings, window_settings, sublime_settings) as mock_context: mock_context.replace_tempdir_env() mock_context.replace_tempdir_view_settings() mock_context.replace_tempdir_window_settings() mock_context.replace_tempdir_sublime_settings() mock_context.make_executable_files(executable_temp_files) mock_context.make_dirs(temp_dirs) if isinstance(expected_result, tuple): tempdir = mock_context.tempdir + os.sep executable_path = expected_result[0].replace( '{tempdir}', tempdir) executable_path = shellenv.path_encode(executable_path) env_vars = {} for name, value in expected_result[1].items(): value = value.replace('{tempdir}', tempdir) name = shellenv.env_encode(name) value = shellenv.env_encode(value) env_vars[name] = value expected_result = (executable_path, env_vars) self.assertEquals( expected_result, golangconfig.subprocess_info(executable_name, required_vars, optional_vars=optional_vars, view=mock_context.view, window=mock_context.window)) self.assertEqual('', sys.stdout.getvalue()) else: def do_test(): golangconfig.subprocess_info(executable_name, required_vars, optional_vars=optional_vars, view=mock_context.view, window=mock_context.window) self.assertRaises(expected_result, do_test)
def subprocess_info(executable_name, required_vars, optional_vars=None, view=None, window=None): """ Gathers and formats information necessary to use subprocess.Popen() to run one of the go executables, with details pulled from setting_value() and executable_path(). Ensures that the executable path and env dictionary are properly encoded for Sublime Text 2, where byte strings are necessary. :param executable_name: A unicode string of the executable to locate, e.g. "go" or "gofmt" :param required_vars: A list of unicode strings of the environment variables that are required, e.g. "GOPATH". Obtains values from setting_value(). :param optional_vars: A list of unicode strings of the environment variables that are optional, but should be pulled from setting_value() if available - e.g. "GOOS", "GOARCH". Obtains values from setting_value(). :param view: A sublime.View object to use in finding project-specific settings. This should be passed whenever available. :param window: A sublime.Window object to use in finding project-specific settings. This should be passed whenever available. :raises: RuntimeError When the function is called from any thread but the UI thread TypeError When any of the parameters are of the wrong type golangconfig.ExecutableError When the executable requested could not be located. The .name attribute contains the name of the executable that could not be located. The .dirs attribute contains a list of unicode strings of the directories searched. golangconfig.EnvVarError When one or more required_vars are not available. The .missing attribute will be a list of the names of missing environment variables. :return: A two-element tuple. - [0] A unicode string (byte string for ST2) of the path to the executable - [1] A dict to pass to the env parameter of subprocess.Popen() """ path, _ = executable_path(executable_name, view=view, window=window) if path is None: name = executable_name if sys.platform == 'win32': name += '.exe' dirs = [] settings_path, _ = _get_most_specific_setting('PATH', view=view, window=window) if settings_path and settings_path != _NO_VALUE: dirs.extend(settings_path.split(os.pathsep)) _, shell_dirs = shellenv.get_path() for shell_dir in shell_dirs: if shell_dir not in dirs: dirs.append(shell_dir) exception = ExecutableError( 'The executable "%s" could not be located in any of the following locations: "%s"' % (name, '", "'.join(dirs))) exception.name = name exception.dirs = dirs raise exception path = shellenv.path_encode(path) _, env = shellenv.get_env(for_subprocess=True) var_groups = [required_vars] if optional_vars: var_groups.append(optional_vars) missing_vars = [] for var_names in var_groups: for var_name in var_names: value, _ = setting_value(var_name, view=view, window=window) var_key = var_name if value is not None: value = str_cls(value) value = shellenv.env_encode(value) var_key = shellenv.env_encode(var_key) if value is None: if var_key in env: del env[var_key] continue env[var_key] = value for required_var in required_vars: var_key = shellenv.env_encode(required_var) if var_key not in env: missing_vars.append(required_var) if missing_vars: missing_vars = sorted(missing_vars, key=lambda s: s.lower()) exception = EnvVarError( 'The following environment variable%s currently unset: %s' % ('s are' if len(missing_vars) > 1 else ' is', ', '.join(missing_vars))) exception.missing = missing_vars raise exception encoded_goroot = shellenv.env_encode('GOROOT') if encoded_goroot in env: unicode_sep = shellenv.path_decode(os.sep) name = executable_name if sys.platform == 'win32': name += '.exe' relative_executable_path = shellenv.path_encode('bin%s%s' % (unicode_sep, name)) goroot_executable_path = os.path.join(env[encoded_goroot], relative_executable_path) if goroot_executable_path != path: print( 'golangconfig: warning - binary %s was found at "%s", which is not inside of the GOROOT "%s"' % (executable_name, path, shellenv.path_decode(env[encoded_goroot]))) return (path, env)
def subprocess_info(executable_name, required_vars, optional_vars=None, view=None, window=None): """ Gathers and formats information necessary to use subprocess.Popen() to run one of the go executables, with details pulled from setting_value() and executable_path(). Ensures that the executable path and env dictionary are properly encoded for Sublime Text 2, where byte strings are necessary. :param executable_name: A unicode string of the executable to locate, e.g. "go" or "gofmt" :param required_vars: A list of unicode strings of the environment variables that are required, e.g. "GOPATH". Obtains values from setting_value(). :param optional_vars: A list of unicode strings of the environment variables that are optional, but should be pulled from setting_value() if available - e.g. "GOOS", "GOARCH". Obtains values from setting_value(). :param view: A sublime.View object to use in finding project-specific settings. This should be passed whenever available. :param window: A sublime.Window object to use in finding project-specific settings. This should be passed whenever available. :raises: RuntimeError When the function is called from any thread but the UI thread TypeError When any of the parameters are of the wrong type golangconfig.ExecutableError When the executable requested could not be located. The .name attribute contains the name of the executable that could not be located. The .dirs attribute contains a list of unicode strings of the directories searched. golangconfig.EnvVarError When one or more required_vars are not available. The .missing attribute will be a list of the names of missing environment variables. golangconfig.GoPathNotFoundError When one or more directories specified by the GOPATH environment variable could not be found on disk. The .directories attribute will be a list of the directories that could not be found. golangconfig.GoRootNotFoundError When the directory specified by GOROOT environment variable could not be found on disk. The .directory attribute will be the path to the directory that could not be found. golangconfig.EnvVarError When one or more required_vars are not available. The .missing attribute will be a list of the names of missing environment variables. :return: A two-element tuple. - [0] A unicode string (byte string for ST2) of the path to the executable - [1] A dict to pass to the env parameter of subprocess.Popen() """ path, _ = executable_path(executable_name, view=view, window=window) if path is None: name = executable_name if sys.platform == 'win32': name += '.exe' dirs = [] settings_path, _ = _get_most_specific_setting('PATH', view=view, window=window) if settings_path and settings_path != _NO_VALUE: dirs.extend(settings_path.split(os.pathsep)) _, shell_dirs = shellenv.get_path() for shell_dir in shell_dirs: if shell_dir not in dirs: dirs.append(shell_dir) exception = ExecutableError( 'The executable "%s" could not be located in any of the following locations: "%s"' % ( name, '", "'.join(dirs) ) ) exception.name = name exception.dirs = dirs raise exception path = shellenv.path_encode(path) _, env = shellenv.get_env(for_subprocess=True) var_groups = [required_vars] if optional_vars: var_groups.append(optional_vars) missing_vars = [] for var_names in var_groups: for var_name in var_names: value, _ = setting_value(var_name, view=view, window=window) var_key = var_name if value is not None: value = str_cls(value) value = shellenv.env_encode(value) var_key = shellenv.env_encode(var_key) if value is None: if var_key in env: del env[var_key] continue env[var_key] = value for required_var in required_vars: var_key = shellenv.env_encode(required_var) if var_key not in env: missing_vars.append(required_var) if missing_vars: missing_vars = sorted(missing_vars, key=lambda s: s.lower()) exception = EnvVarError( 'The following environment variable%s currently unset: %s' % ( 's are' if len(missing_vars) > 1 else ' is', ', '.join(missing_vars) ) ) exception.missing = missing_vars raise exception encoded_goroot = shellenv.env_encode('GOROOT') if encoded_goroot in env: unicode_sep = shellenv.path_decode(os.sep) name = executable_name if sys.platform == 'win32': name += '.exe' relative_executable_path = shellenv.path_encode('bin%s%s' % (unicode_sep, name)) goroot_executable_path = os.path.join(env[encoded_goroot], relative_executable_path) if goroot_executable_path != path: print( 'golangconfig: warning - binary %s was found at "%s", which is not inside of the GOROOT "%s"' % ( executable_name, path, shellenv.path_decode(env[encoded_goroot]) ) ) return (path, env)
def test_env_encode(self): value = shellenv.env_encode('env value') if sys.version_info < (3,): self.assertEqual(b'env value', value) else: self.assertEqual('env value', value)
def test_env_encode(self): value = shellenv.env_encode('env value') if sys.version_info < (3, ): self.assertEqual(b'env value', value) else: self.assertEqual('env value', value)