def do_test(dirname): readonly = os.path.join(dirname, "readonly") print('CONDA_EXE: {}'.format(os.environ.get('CONDA_EXE'))) # originally we did not specify a python version here, but we # needed to add it with python 3.8 was released because a compatible # version of ipython had not been created yet. conda_api.create(prefix=readonly, pkgs=['python<3.8']) assert os.path.isdir(readonly) assert os.path.isdir(os.path.join(readonly, "conda-meta")) assert os.path.exists(os.path.join(readonly, PYTHON_BINARY)) readonly_mode = stat.S_IREAD | stat.S_IRGRP | stat.S_IROTH | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH os.chmod(readonly, readonly_mode) os.chmod(os.path.join(readonly, 'conda-meta'), readonly_mode) cloned = os.path.join(dirname, 'cloned') conda_api.clone(cloned, readonly) assert os.path.isdir(cloned) assert os.path.isdir(os.path.join(cloned, "conda-meta")) assert os.path.exists(os.path.join(cloned, PYTHON_BINARY)) write_mode = (stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) ^ readonly_mode os.chmod(readonly, write_mode) os.chmod(os.path.join(readonly, 'conda-meta'), write_mode)
def do_test(dirname): missing = os.path.join(dirname, "missing") print('CONDA_EXE: {}'.format(os.environ.get('CONDA_EXE'))) with pytest.raises(conda_api.CondaEnvMissingError) as excinfo: cloned = os.path.join(dirname, 'cloned') conda_api.clone(cloned, missing) assert 'missing' in repr(excinfo.value)
def provide(self, requirement, context): """Override superclass to create or update our environment.""" assert 'PATH' in context.environ conda = new_conda_manager(context.frontend) # set from the inherited vale if necessary if context.status.analysis.config['source'] == 'inherited': context.environ[ requirement.env_var] = context.status.analysis.config['value'] # set the env var (but not PATH, etc. to fully activate, that's done below) super_result = super(CondaEnvProvider, self).provide(requirement, context) project_dir = context.environ['PROJECT_DIR'] env_name = context.status.analysis.config.get( 'env_name', context.default_env_spec_name) env_spec = requirement.env_specs.get(env_name) if env_name == 'bootstrap-env': # The bootstrap environment is always stored in the project directory # TODO: have this respect ANACONDA_PROJECT_ENVS_PATH prefix = os.path.join(project_dir, 'envs', 'bootstrap-env') elif context.status.analysis.config['source'] == 'inherited': prefix = context.environ.get(requirement.env_var, None) inherited = True else: prefix = None inherited = False if prefix is None: # use the default environment prefix = env_spec.path(project_dir) assert prefix is not None # if the value has changed, choose the matching env spec # (something feels wrong here; should this be in read_config? # or not at all?) for env in requirement.env_specs.values(): if env.path(project_dir) == prefix: env_spec = env break if context.mode != PROVIDE_MODE_CHECK: # we update the environment in both prod and dev mode # TODO if not creating a named env, we could use the # shared packages, but for now we leave it alone assert env_spec is not None deviations = conda.find_environment_deviations(prefix, env_spec) readonly_policy = os.environ.get( 'ANACONDA_PROJECT_READONLY_ENVS_POLICY', 'fail').lower() if deviations.unfixable and readonly_policy in ('clone', 'replace'): # scan for writable path destination = env_spec.path(project_dir, reset=True, force_writable=True) if destination != prefix: if readonly_policy == 'replace': print('Replacing the readonly environment {}'.format( prefix)) deviations = conda.find_environment_deviations( destination, env_spec) else: print('Cloning the readonly environment {}'.format( prefix)) conda_api.clone( destination, prefix, stdout_callback=context.frontend.partial_info, stderr_callback=context.frontend.partial_error) prefix = destination try: conda.fix_environment_deviations(prefix, env_spec, create=(not inherited)) except CondaManagerError as e: return super_result.copy_with_additions(errors=[str(e)]) conda_api.environ_set_prefix(context.environ, prefix, varname=requirement.env_var) path = context.environ.get("PATH", "") context.environ["PATH"] = conda_api.set_conda_env_in_path(path, prefix) # Some stuff can only be done when a shell is launched: # - we can't set PS1 because it shouldn't be exported. # - we can't run conda activate scripts because they are sourced. # We can do these in the output of our activate command, but not here. return super_result