Exemplo n.º 1
0
    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(CondaBootstrapEnvProvider,
                             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)

        prefix = os.path.join(project_dir, 'envs', 'bootstrap-env')

        # 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
            try:
                conda.fix_environment_deviations(prefix, env_spec, create=True)
            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
    def prepare_project_scoped_env(dirname):
        project = Project(dirname)
        fake_old_path = "foo" + os.pathsep + "bar"
        environ = dict(PROJECT_DIR=dirname, PATH=fake_old_path)
        result = prepare_without_interaction(project, environ=environ)
        assert result
        expected_env = os.path.join(dirname, "envs", "bootstrap-env")
        if platform.system() == 'Windows':
            expected_new_path = expected_env + os.pathsep + os.path.join(
                expected_env, script_dir) + os.pathsep + os.path.join(
                    expected_env, "Library",
                    "bin") + os.pathsep + "foo" + os.pathsep + "bar"
        else:
            expected_new_path = os.path.join(
                expected_env,
                script_dir) + os.pathsep + "foo" + os.pathsep + "bar"
        expected = dict(PROJECT_DIR=project.directory_path,
                        PATH=expected_new_path,
                        BOOTSTRAP_ENV_PREFIX=expected_env)
        conda_api.environ_set_prefix(expected, expected_env)

        expected == result.environ
        assert os.path.exists(os.path.join(expected_env, "conda-meta"))
        conda_meta_mtime = os.path.getmtime(
            os.path.join(expected_env, "conda-meta"))

        # bare minimum bootstrap-env env shouldn't include these
        # (contrast with the test later where we list them in
        # requirements)
        installed = conda_api.installed(expected_env)
        assert 'ipython' not in installed
        assert 'numpy' not in installed

        # Prepare it again should no-op (use the already-existing environment)
        environ = dict(PROJECT_DIR=dirname, PATH=fake_old_path)
        result = prepare_without_interaction(project, environ=environ)
        assert result
        expected = dict(PROJECT_DIR=project.directory_path,
                        PATH=expected_new_path)
        conda_api.environ_set_prefix(expected, expected_env)
        assert conda_meta_mtime == os.path.getmtime(
            os.path.join(expected_env, "conda-meta"))

        # Now unprepare
        status = unprepare(project, result)
        assert status

        # todo: this differs from standard CondaEnvProvider
        assert status.status_description == 'Success.'
        assert status.errors == []
        assert not os.path.exists(expected_env)
def test_environ_set_prefix_to_root():
    prefix = conda_api.resolve_env_to_prefix('root')
    environ = dict()
    conda_api.environ_set_prefix(environ, prefix, varname='CONDA_PREFIX')
    assert environ['CONDA_PREFIX'] == prefix
    assert environ['CONDA_DEFAULT_ENV'] == 'root'
Exemplo n.º 4
0
    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