def _choose_args_and_shell(self, environ, extra_args=None): assert extra_args is None or isinstance(extra_args, list) args = None shell = False if not self.supports_http_options and (self.notebook or self.bokeh_app): # drop the http arguments extra_args = _ArgsTransformer().transform_args(extra_args) if self.notebook is not None: path = os.path.join(environ['PROJECT_DIR'], self.notebook) args = ['jupyter-notebook', path] if self.supports_http_options: extra_args = _NotebookArgsTransformer(self).transform_args( extra_args) if self.bokeh_app is not None: path = os.path.join(environ['PROJECT_DIR'], self.bokeh_app) args = ['bokeh', 'serve', path] if self.supports_http_options: extra_args = _BokehArgsTransformer().transform_args(extra_args) if self.args is not None: args = self.args if args is not None: if extra_args is not None: args = args + extra_args return args, False command = self._attributes.get(self._shell_field(), None) if (command is not None) and self.supports_http_options: args = [_append_extra_args_to_command_line(command, extra_args)] shell = True elif command: shell = True args = _TemplateArgsTransformer().parse_and_template( command, environ, extra_args) if args is None: # see conda.misc::launch for what we're copying app_entry = self._attributes.get('conda_app_entry', None) if app_entry is not None: # conda.misc uses plain split and not shlex or # anything like that, we need to match its # interpretation parsed = app_entry.split() args = [] for arg in parsed: if '${PREFIX}' in arg: arg = arg.replace( '${PREFIX}', conda_api.environ_get_prefix(environ)) args.append(arg) if extra_args is not None: args = args + extra_args # args can be None if the command doesn't work on our platform return (args, shell)
def _minimal_environ_full(with_conda_env, **additions): minimal_environ = dict() for name in (system_vars_to_keep + conda_vars_to_keep): if name in os.environ: minimal_environ[name] = os.environ[name] env_prefix = conda_api.environ_get_prefix(minimal_environ) if len(additions) > 0 or not with_conda_env: if not with_conda_env: for name in conda_vars_to_keep: if name in minimal_environ: del minimal_environ[name] for (key, value) in additions.items(): minimal_environ[key] = value return (env_prefix, minimal_environ)
def prepare_with_app_entry(dirname): project = project_no_dedicated_env(dirname) environ = minimal_environ(FOO='bar') env_path = conda_api.environ_get_prefix(environ) result = prepare_without_interaction(project, environ=environ) assert result command = result.command_exec_info assert 'FOO' in command.env assert command.cwd == project.directory_path if platform.system() == 'Windows': commandpath = os.path.join(env_path, "python.exe") else: commandpath = os.path.join(env_path, "bin", "python") assert command.args == [commandpath, 'echo.py', env_path, 'foo', 'bar'] p = command.popen(stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err) = p.communicate() # strip is to pull off the platform-specific newline assert out.decode().strip() == ("['echo.py', '%s', 'foo', 'bar']" % (env_path.replace("\\", "\\\\"))) assert err.decode() == ""
def _prepare_environ_and_overrides(project, environ=None, env_spec_name=None): if environ is None: environ = os.environ assert 'PATH' in environ # we modify a copy, which 1) makes all our changes atomic and # 2) minimizes memory leaks on systems that use putenv(). # # On Linux, it appears we must use deepcopy (vs plain copy) or # we still modify os.environ somehow. # # On the Windows CI server, but NOT on my local Windows 10 # machine, deepcopy() didn't work but adding the extra .copy() # fixed it. The failure mode was that changes to PATH in the # copy were not visible via os.environ or os.getenv('PATH'), # but they DID affect what subprocess.Popen was able to see, # so that a test which modified PATH in this environ_copy # would break subsequent tests (such as test_conda_api which # tries to run conda). Anyway, presumably this is a bug in # something, but I'm not sure in what. If you can remove the # extra copy() and still pass all tests on all platforms at # some point in the future, feel free to clean up this # hackery. environ_copy = deepcopy(environ.copy()) # many requirements and providers might need this, plus # it's useful for scripts to find their source tree. environ_copy['PROJECT_DIR'] = project.directory_path # Save and then clear out any existing environment existing_env_prefix = conda_api.environ_get_prefix(environ_copy) conda_api.environ_delete_prefix_variables(environ_copy) overrides = UserConfigOverrides(env_spec_name=env_spec_name, inherited_env=existing_env_prefix) return (environ_copy, overrides)