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
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
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
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
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
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