Example #1
0
    def _list_config(self, project: Project, options: argparse.Namespace) -> None:
        stream.echo(
            "Home configuration ({}):".format(project.global_config._config_file)
        )
        with stream.indent("  "):
            for key in sorted(project.global_config):
                stream.echo(
                    stream.yellow(
                        "# " + project.global_config._config_map[key].description
                    ),
                    verbosity=stream.DETAIL,
                )
                stream.echo(f"{stream.cyan(key)} = {project.global_config[key]}")

        stream.echo()
        stream.echo(
            "Project configuration ({}):".format(project.project_config._config_file)
        )
        with stream.indent("  "):
            for key in sorted(project.project_config):
                stream.echo(
                    stream.yellow(
                        "# " + project.project_config._config_map[key].description
                    ),
                    verbosity=stream.DETAIL,
                )
                stream.echo(f"{stream.cyan(key)} = {project.project_config[key]}")
Example #2
0
    def synchronize(self, clean: bool = True, dry_run: bool = False) -> None:
        """Synchronize the working set with pinned candidates.

        :param clean: Whether to remove unneeded packages, defaults to True.
        :param dry_run: If set to True, only prints actions without actually do them.
        """
        to_add, to_update, to_remove = self.compare_with_working_set()
        if not clean:
            to_remove = []
        if not any([to_add, to_update, to_remove]):
            stream.echo(
                stream.yellow(
                    "All packages are synced to date, nothing to do."))
            if not dry_run:
                with stream.logging("install"):
                    self.update_project_egg_info()
            return
        to_do = {"remove": to_remove, "update": to_update, "add": to_add}
        self._show_headline(to_do)

        if dry_run:
            self._show_summary(to_do)
            return

        handlers = {
            "add": self.install_candidate,
            "update": self.update_candidate,
            "remove": self.remove_distribution,
        }

        sequential_jobs = []
        parallel_jobs = []
        # Self package will be installed after all other dependencies are installed.
        install_self = None
        for kind in to_do:
            for key in to_do[kind]:
                if (key == self.environment.project.meta.name and
                        self.environment.project.meta.project_name.lower()):
                    install_self = (kind, key)
                elif key in self.SEQUENTIAL_PACKAGES:
                    sequential_jobs.append((kind, key))
                elif key in self.candidates and self.candidates[
                        key].req.editable:
                    # Editable packages are installed sequentially.
                    sequential_jobs.append((kind, key))
                else:
                    parallel_jobs.append((kind, key))

        errors: List[str] = []
        failed_jobs: List[Tuple[str, str]] = []

        def update_progress(future, kind, key):
            if future.exception():
                failed_jobs.append((kind, key))
                error = future.exception()
                errors.extend([f"{kind} {stream.green(key)} failed:\n"] +
                              traceback.format_exception(
                                  type(error), error, error.__traceback__))

        with stream.logging("install"), self.environment.activate():
            with stream.indent("  "):
                for job in sequential_jobs:
                    kind, key = job
                    handlers[kind](key)
                for i in range(self.retry_times + 1):
                    with self.create_executor() as executor:
                        for job in parallel_jobs:
                            kind, key = job
                            future = executor.submit(handlers[kind], key)
                            future.add_done_callback(
                                functools.partial(update_progress,
                                                  kind=kind,
                                                  key=key))
                    if not failed_jobs or i == self.retry_times:
                        break
                    parallel_jobs, failed_jobs = failed_jobs, []
                    errors.clear()
                    stream.echo("Retry failed jobs")

            if errors:
                stream.echo(stream.red("\nERRORS:"))
                stream.echo("".join(errors), err=True)
                raise InstallationError(
                    "Some package operations are not complete yet")

            if install_self:
                stream.echo("Installing the project as an editable package...")
                with stream.indent("  "):
                    handlers[install_self[0]](install_self[1])
            else:
                self.update_project_egg_info()
            stream.echo(f"\n{CELE} All complete!")