Пример #1
0
    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()))
Пример #2
0
 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)
Пример #3
0
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
Пример #4
0
    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()))
Пример #5
0
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