Exemple #1
0
def do_lock(
    project: Project,
    strategy: str = "all",
    tracked_names: Optional[Iterable[str]] = None,
    requirements: Optional[List[Requirement]] = None,
) -> Dict[str, Candidate]:
    """Performs the locking process and update lockfile.

    :param project: the project instance
    :param strategy: update stratege: reuse/eager/all
    :param tracked_names: required when using eager strategy
    :param requirements: An optional dictionary of requirements, read from pyproject
        if not given.
    """
    check_project_file(project)
    # TODO: multiple dependency definitions for the same package.
    provider = project.get_provider(strategy, tracked_names)
    if not requirements:
        requirements = [
            r for deps in project.all_dependencies.values()
            for r in deps.values()
        ]

    with stream.open_spinner(title="Resolving dependencies",
                             spinner="dots") as spin, stream.logging("lock"):
        reporter = project.get_reporter(requirements, tracked_names, spin)
        resolver = project.core.resolver_class(provider, reporter)
        mapping, dependencies, summaries = resolve(
            resolver, requirements, project.environment.python_requires)
        data = format_lockfile(mapping, dependencies, summaries)
        spin.succeed("Resolution success")
    project.write_lockfile(data)

    return mapping
Exemple #2
0
def resolve_requirements(
    repository,
    lines,
    requires_python="",
    allow_prereleases=None,
    strategy="all",
    preferred_pins=None,
    tracked_names=None,
):
    requirements = []
    for line in lines:
        if line.startswith("-e "):
            requirements.append(parse_requirement(line[3:], True))
        else:
            requirements.append(parse_requirement(line))
    requires_python = PySpecSet(requires_python)
    if not preferred_pins:
        provider = BaseProvider(repository, requires_python, allow_prereleases)
    else:
        provider_class = (
            ReusePinProvider if strategy == "reuse" else EagerUpdateProvider
        )
        provider = provider_class(
            preferred_pins,
            tracked_names or (),
            repository,
            requires_python,
            allow_prereleases,
        )

    with stream.open_spinner("Resolving dependencies") as spin, stream.logging("lock"):
        reporter = SpinnerReporter(spin, requirements)
        resolver = Resolver(provider, reporter)
        mapping, *_ = resolve(resolver, requirements, requires_python)
        return mapping
Exemple #3
0
def do_lock(
    project: Project,
    strategy: str = "all",
    tracked_names: Optional[Iterable[str]] = None,
    requirements: Optional[List[Requirement]] = None,
) -> Dict[str, Candidate]:
    """Performs the locking process and update lockfile.

    :param project: the project instance
    :param strategy: update stratege: reuse/eager/all
    :param tracked_names: required when using eager strategy
    :param requirements: An optional dictionary of requirements, read from pyproject
        if not given.
    """
    check_project_file(project)
    # TODO: multiple dependency definitions for the same package.
    provider = project.get_provider(strategy, tracked_names)
    if not requirements:
        requirements = [
            r for deps in project.all_dependencies.values()
            for r in deps.values()
        ]
    resolve_max_rounds = int(project.config["strategy.resolve_max_rounds"])
    with stream.logging("lock"):
        # The context managers are nested to ensure the spinner is stopped before
        # any message is thrown to the output.
        with stream.open_spinner(title="Resolving dependencies",
                                 spinner="dots") as spin:
            reporter = project.get_reporter(requirements, tracked_names, spin)
            resolver = project.core.resolver_class(provider, reporter)
            try:
                mapping, dependencies, summaries = resolve(
                    resolver,
                    requirements,
                    project.environment.python_requires,
                    resolve_max_rounds,
                )
            except ResolutionTooDeep:
                spin.fail(f"{LOCK} Lock failed")
                stream.echo(
                    "The dependency resolution exceeds the maximum loop depth of "
                    f"{resolve_max_rounds}, there may be some circular dependencies "
                    "in your project. Try to solve them or increase the "
                    f"{stream.green('`strategy.resolve_max_rounds`')} config.",
                    err=True,
                )
                raise
            except ResolutionImpossible as err:
                spin.fail(f"{LOCK} Lock failed")
                stream.echo(format_resolution_impossible(err), err=True)
                raise
            else:
                data = format_lockfile(mapping, dependencies, summaries)
                spin.succeed(f"{LOCK} Lock successful")
    project.write_lockfile(data)

    return mapping
Exemple #4
0
    def install_candidate(self, key: str) -> Candidate:
        """Install candidate"""
        can = self.candidates[key]
        installer = self.get_installer()
        with stream.open_spinner(f"Installing {can.format()}...") as spinner:
            try:
                installer.install(can)
            except Exception:
                spinner.fail(f"Install {can.format()} failed")
                raise
            else:
                spinner.succeed(f"Install {can.format()} successful")

        return can
Exemple #5
0
 def update_candidate(self, key: str) -> Tuple[Distribution, Candidate]:
     """Update candidate"""
     can = self.candidates[key]
     dist = self.working_set[safe_name(can.name).lower()]
     installer = self.get_installer()
     with stream.open_spinner(
             f"Updating {stream.green(key, bold=True)} {stream.yellow(dist.version)} "
             f"-> {stream.yellow(can.version)}...") as spinner:
         try:
             installer.uninstall(dist)
             installer.install(can)
         except Exception:
             spinner.fail(f"Update {stream.green(key, bold=True)} "
                          f"-> {stream.yellow(can.version)} failed")
             raise
         else:
             spinner.succeed(f"Update {stream.green(key, bold=True)} "
                             f"-> {stream.yellow(can.version)} successful")
     return dist, can
Exemple #6
0
    def remove_distribution(self, key: str) -> Distribution:
        """Remove distributions with given names.

        :param distributions: a list of names to be removed.
        """
        installer = self.get_installer()
        dist = self.working_set[key]
        with stream.open_spinner(
                f"Removing {stream.green(key, bold=True)} {stream.yellow(dist.version)}..."
        ) as spinner:
            try:
                installer.uninstall(dist)
            except Exception:
                spinner.fail(f"Remove {stream.green(key, bold=True)} "
                             f"{stream.yellow(dist.version)} failed")
                raise
            else:
                spinner.succeed(f"Remove {stream.green(key, bold=True)} "
                                f"{stream.yellow(dist.version)} successful")
        return dist