コード例 #1
0
    def fix_environment_deviations(self, prefix, spec, deviations=None, create=True):
        if deviations is None:
            deviations = self.find_environment_deviations(prefix, spec)

        if deviations.unfixable:
            raise CondaManagerError("Unable to update environment at %s" % prefix)

        if os.path.isdir(os.path.join(prefix, 'conda-meta')):
            to_update = list(set(deviations.missing_packages + deviations.wrong_version_packages))
            if len(to_update) > 0:
                specs = spec.specs_for_conda_package_names(to_update)
                assert len(specs) == len(to_update)
                spec.apply_pins(prefix, specs)
                try:
                    conda_api.install(
                        prefix=prefix,
                        pkgs=specs,
                        channels=spec.channels,
                        stdout_callback=self._on_stdout,
                        stderr_callback=self._on_stderr)
                except conda_api.CondaError as e:
                    raise CondaManagerError("Failed to install packages: {}: {}".format(", ".join(specs), str(e)))
                finally:
                    spec.remove_pins(prefix)
        elif create:
            # Create environment from scratch

            command_line_packages = set(spec.conda_packages_for_create)
            # conda won't let us create a completely empty environment
            if len(command_line_packages) == 0:
                command_line_packages = set(['python'])

            try:
                conda_api.create(
                    prefix=prefix,
                    pkgs=list(command_line_packages),
                    channels=spec.channels,
                    stdout_callback=self._on_stdout,
                    stderr_callback=self._on_stderr)
            except conda_api.CondaError as e:
                raise CondaManagerError("Failed to create environment at %s: %s" % (prefix, str(e)))
        else:
            raise CondaManagerError("Conda environment at %s does not exist" % (prefix))

        # now add pip if needed
        missing = list(deviations.missing_pip_packages)
        if len(missing) > 0:
            specs = spec.specs_for_pip_package_names(missing)
            assert len(specs) == len(missing)
            try:
                pip_api.install(prefix=prefix, pkgs=specs)
            except pip_api.PipError as e:
                raise CondaManagerError("Failed to install missing pip packages: {}: {}".format(
                    ", ".join(missing), str(e)))

        # write a file to tell us we can short-circuit next time
        self._write_timestamp_file(prefix, spec)
コード例 #2
0
    def resolve_dependencies(self, package_specs, channels, platforms):
        by_platform = {}

        current = conda_api.current_platform()
        resolve_for_platforms = list(platforms)
        # always resolve "current" first because it's confusing if
        # an error says resolution failed on another platform when
        # the real issue is that resolution will fail on all platforms.
        if current in resolve_for_platforms:
            resolve_for_platforms.remove(current)
            resolve_for_platforms = [current] + resolve_for_platforms
        for conda_platform in resolve_for_platforms:
            try:
                self._log_info("Resolving conda packages for %s" %
                               conda_platform)
                deps = conda_api.resolve_dependencies(pkgs=package_specs,
                                                      platform=conda_platform,
                                                      channels=channels)
            except conda_api.CondaError as e:
                raise CondaManagerError("Error resolving for {}: {}".format(
                    conda_platform, str(e)))
            locked_specs = ["%s=%s=%s" % dep for dep in deps]
            by_platform[conda_platform] = sorted(locked_specs)

        by_platform = _extract_common(by_platform)

        lock_set = CondaLockSet(package_specs_by_platform=by_platform,
                                platforms=resolve_for_platforms)
        return lock_set
コード例 #3
0
    def _find_conda_deviations(self, prefix, env_spec):
        try:
            installed = conda_api.installed(prefix)
        except conda_api.CondaError as e:
            raise CondaManagerError("Conda failed while listing installed packages in %s: %s" % (prefix, str(e)))

        missing = set()
        wrong_version = set()

        for spec_string in env_spec.conda_packages_for_create:
            spec = conda_api.parse_spec(spec_string)
            name = spec.name

            if name not in installed:
                missing.add(name)
            else:

                def version_match(wanted, installed):
                    if wanted == installed:
                        return True
                    else:
                        return installed.startswith(wanted + ".")

                # The only constraint we are smart enough to understand is
                # the one we put in the lock file, which is plain =.
                # We can't do version comparisons, which is a bug.
                # We won't notice if non-= constraints are unmet.
                (_, installed_version, installed_build) = installed[name]
                if spec.exact_version is not None and not version_match(spec.exact_version, installed_version):
                    wrong_version.add(name)
                elif spec.exact_build_string is not None and not version_match(spec.exact_build_string,
                                                                               installed_build):
                    wrong_version.add(name)

        return (sorted(list(missing)), sorted(list(wrong_version)))
コード例 #4
0
 def remove_packages(self, prefix, packages):
     try:
         conda_api.remove(prefix,
                          packages,
                          stdout_callback=self._on_stdout,
                          stderr_callback=self._on_stderr)
     except conda_api.CondaError as e:
         raise CondaManagerError("Failed to remove packages from %s: %s" %
                                 (prefix, str(e)))
コード例 #5
0
 def remove_packages(self, prefix, packages, pip=False):
     if pip:
         try:
             pip_api.remove(prefix,
                            packages,
                            stdout_callback=self._on_stdout,
                            stderr_callback=self._on_stderr)
         except pip_api.PipError as e:
             raise CondaManagerError(
                 'Failed to remove pip packages from {}: {}'.format(
                     prefix, str(e)))
     else:
         try:
             conda_api.remove(prefix,
                              packages,
                              stdout_callback=self._on_stdout,
                              stderr_callback=self._on_stderr)
         except conda_api.CondaError as e:
             raise CondaManagerError(
                 "Failed to remove packages from %s: %s" % (prefix, str(e)))
コード例 #6
0
    def _find_conda_missing(self, prefix, spec):
        try:
            installed = conda_api.installed(prefix)
        except conda_api.CondaError as e:
            raise CondaManagerError("Conda failed while listing installed packages in %s: %s" % (prefix, str(e)))

        # TODO: we don't verify that the environment contains the right versions
        # https://github.com/Anaconda-Server/anaconda-project/issues/77

        missing = set()

        for name in spec.conda_package_names_set:
            if name not in installed:
                missing.add(name)

        return sorted(list(missing))
コード例 #7
0
    def _find_pip_missing(self, prefix, spec):
        # this is an important optimization to avoid a slow "pip
        # list" operation if the project has no pip packages
        if len(spec.pip_package_names_set) == 0:
            return []

        try:
            installed = pip_api.installed(prefix)
        except pip_api.PipError as e:
            raise CondaManagerError("pip failed while listing installed packages in %s: %s" % (prefix, str(e)))

        # TODO: we don't verify that the environment contains the right versions
        # https://github.com/Anaconda-Server/anaconda-project/issues/77

        missing = set()

        for name in spec.pip_package_names_set:
            if name not in installed:
                missing.add(name)

        return sorted(list(missing))
コード例 #8
0
    def fix_environment_deviations(self,
                                   prefix,
                                   spec,
                                   deviations=None,
                                   create=True):
        if deviations is None:
            deviations = self.find_environment_deviations(prefix, spec)

        if deviations.unfixable:
            raise CondaManagerError("Unable to update environment at %s" %
                                    prefix)

        conda_meta = os.path.join(prefix, 'conda-meta')
        packed = os.path.join(conda_meta, '.packed')
        install_pip = True

        if os.path.isdir(conda_meta) and os.path.exists(packed):
            with open(packed) as f:
                packed_arch = f.read().strip()

            matched = packed_arch == conda_api.current_platform()
            if matched:
                if 'win' in conda_api.current_platform():
                    unpack_script = [
                        'python',
                        os.path.join(prefix, 'Scripts',
                                     'conda-unpack-script.py')
                    ]

                else:
                    unpack_script = os.path.join(prefix, 'bin', 'conda-unpack')

                try:
                    subprocess.check_call(unpack_script)
                    os.remove(packed)
                    install_pip = False
                except (subprocess.CalledProcessError, OSError) as e:
                    self._log_info(
                        'Warning: conda-unpack could not be run: \n{}\n'
                        'The environment will be recreated.'.format(str(e)))
                    create = True
                    shutil.rmtree(prefix)

            else:
                self._log_info(
                    'Warning: The unpacked env does not match the current architecture. '
                    'It will be recreated.')
                create = True
                shutil.rmtree(prefix)

        if os.path.isdir(conda_meta):
            to_update = list(
                set(deviations.missing_packages +
                    deviations.wrong_version_packages))
            if len(to_update) > 0:
                specs = spec.specs_for_conda_package_names(to_update)
                assert len(specs) == len(to_update)
                spec.apply_pins(prefix, specs)
                try:
                    conda_api.install(prefix=prefix,
                                      pkgs=specs,
                                      channels=spec.channels,
                                      stdout_callback=self._on_stdout,
                                      stderr_callback=self._on_stderr)
                except conda_api.CondaError as e:
                    raise CondaManagerError(
                        "Failed to install packages: {}: {}".format(
                            ", ".join(specs), str(e)))
                finally:
                    spec.remove_pins(prefix)
        elif create:
            # Create environment from scratch

            command_line_packages = set(spec.conda_packages_for_create)

            try:
                conda_api.create(prefix=prefix,
                                 pkgs=list(command_line_packages),
                                 channels=spec.channels,
                                 stdout_callback=self._on_stdout,
                                 stderr_callback=self._on_stderr)
            except conda_api.CondaError as e:
                raise CondaManagerError(
                    "Failed to create environment at %s: %s" %
                    (prefix, str(e)))
        else:
            raise CondaManagerError("Conda environment at %s does not exist" %
                                    (prefix))

        # now add pip if needed
        missing = list(deviations.missing_pip_packages)
        if (len(missing) > 0) and install_pip:
            specs = spec.specs_for_pip_package_names(missing)
            assert len(specs) == len(missing)
            try:
                pip_api.install(prefix=prefix,
                                pkgs=specs,
                                stdout_callback=self._on_stdout,
                                stderr_callback=self._on_stderr)
            except pip_api.PipError as e:
                raise CondaManagerError(
                    "Failed to install missing pip packages: {}: {}".format(
                        ", ".join(missing), str(e)))

        # write a file to tell us we can short-circuit next time
        self._write_timestamp_file(prefix, spec)
コード例 #9
0
 def remove_packages(self, prefix, packages):
     try:
         conda_api.remove(prefix, packages)
     except conda_api.CondaError as e:
         raise CondaManagerError("Failed to remove packages from %s: %s" % (prefix, str(e)))