def handle(self, project: Project, options: argparse.Namespace) -> None: package = options.package req = parse_requirement(package) repository = project.get_repository() # reverse the result so that latest is at first. matches = repository.find_candidates( req, project.environment.python_requires, True) latest = next(iter(matches), None) if not latest: stream.echo( stream.yellow(f"No match found for the package {package!r}"), err=True) return latest_stable = next(filter(filter_stable, matches), None) installed = project.environment.get_working_set().get(package) metadata = latest.get_metadata() if metadata._legacy: result = ProjectInfo(dict(metadata._legacy.items()), True) else: result = ProjectInfo(dict(metadata._data), False) if latest_stable: result.latest_stable_version = str(latest_stable.version) if installed: result.installed_version = str(installed.version) stream.display_columns(list(result.generate_rows()))
def handle(self, project: Project, options: argparse.Namespace) -> None: project.environment = BareEnvironment(project) result = project.get_repository().search(options.query) terminal_width = None if sys.stdout.isatty(): terminal_width = get_terminal_size()[0] working_set = project.environment.get_working_set() print_results(project.core.ui, result, working_set, terminal_width)
def do_lock( project: Project, strategy: str = "all", tracked_names: Optional[Iterable[str]] = None, requirements: Optional[Dict[str, Dict[str, 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. repository = project.get_repository() requirements = requirements or project.all_dependencies allow_prereleases = project.allow_prereleases requires_python = project.python_requires if strategy == "all": provider = BaseProvider(repository, requires_python, allow_prereleases) else: provider_class = (ReusePinProvider if strategy == "reuse" else EagerUpdateProvider) preferred_pins = project.get_locked_candidates("__all__") provider = provider_class( preferred_pins, tracked_names or (), repository, requires_python, allow_prereleases, ) flat_reqs = list( itertools.chain(*[deps.values() for _, deps in requirements.items()])) # TODO: switch reporter at io level. with halo.Halo(text="Resolving dependencies", spinner="dots") as spin: reporter = SpinnerReporter(flat_reqs, spin) mapping, dependencies, summaries = resolve(provider, reporter, requirements, requires_python) data = format_lockfile(mapping, dependencies, summaries) spin.succeed("Resolution success") project.write_lockfile(data) return mapping
def handle(self, project: Project, options: argparse.Namespace) -> None: package = options.package if package: req = parse_requirement(package) repository = project.get_repository() # reverse the result so that latest is at first. matches = repository.find_candidates( req, project.environment.python_requires, True ) latest = next(iter(matches), None) if not latest: project.core.ui.echo( termui.yellow(f"No match found for the package {package!r}"), err=True, ) return latest_stable = next(filter(filter_stable, matches), None) metadata = latest.metadata else: if not project.meta.name: raise PdmUsageError("This project is not a package") metadata = project.meta package = normalize_name(metadata.name) latest_stable = None assert metadata project_info = ProjectInfo(metadata) if any(getattr(options, key, None) for key in self.metadata_keys): for key in self.metadata_keys: if getattr(options, key, None): project.core.ui.echo(project_info[key]) return installed = project.environment.get_working_set().get(package) if latest_stable: project_info.latest_stable_version = str(latest_stable.version) if installed: project_info.installed_version = str(installed.version) project.core.ui.display_columns(list(project_info.generate_rows()))
def do_lock( project: Project, strategy: str = "all", tracked_names: Iterable[str] | None = None, requirements: list[Requirement] | None = None, dry_run: bool = False, refresh: bool = False, ) -> dict[str, Candidate]: """Performs the locking process and update lockfile.""" check_project_file(project) if refresh: locked_repo = project.locked_repository repo = project.get_repository() mapping: dict[str, Candidate] = {} dependencies: dict[str, list[Requirement]] = {} with project.core.ui.open_spinner("Re-calculating hashes..."): for key, candidate in locked_repo.packages.items(): reqs, python_requires, summary = locked_repo.candidate_info[key] candidate.hashes = repo.get_hashes(candidate) candidate.summary = summary candidate.requires_python = python_requires ident = cast(str, key[0]) mapping[ident] = candidate dependencies[ident] = list(map(parse_requirement, reqs)) lockfile = format_lockfile(project, mapping, dependencies) project.write_lockfile(lockfile) return mapping # 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"]) ui = project.core.ui with ui.logging("lock"): # The context managers are nested to ensure the spinner is stopped before # any message is thrown to the output. with ui.open_spinner(title="Resolving dependencies", spinner="dots") as spin: reporter = project.get_reporter(requirements, tracked_names, spin) resolver: Resolver = project.core.resolver_class(provider, reporter) signals.pre_lock.send(project, requirements=requirements, dry_run=dry_run) try: mapping, dependencies = resolve( resolver, requirements, project.environment.python_requires, resolve_max_rounds, ) except ResolutionTooDeep: spin.fail(f"{termui.Emoji.LOCK} Lock failed") ui.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"{termui.green('`strategy.resolve_max_rounds`')} config.", err=True, ) raise except ResolutionImpossible as err: spin.fail(f"{termui.Emoji.LOCK} Lock failed") ui.echo(format_resolution_impossible(err), err=True) raise ResolutionImpossible("Unable to find a resolution") from None else: data = format_lockfile(project, mapping, dependencies) spin.succeed(f"{termui.Emoji.LOCK} Lock successful") signals.post_lock.send(project, resolution=mapping, dry_run=dry_run) project.write_lockfile(data, write=not dry_run) return mapping