Exemplo n.º 1
0
    def handle(self, project: Project, options: argparse.Namespace) -> None:
        groups: list[str] = list(options.groups)
        if options.pyproject:
            options.hashes = False
        groups = translate_groups(
            project,
            options.default,
            options.dev,
            options.groups or (),
        )
        requirements: dict[str, Requirement] = {}
        packages: Iterable[Requirement] | Iterable[Candidate]
        for group in groups:
            requirements.update(project.get_dependencies(group))
        if options.pyproject:
            packages = requirements.values()
        else:
            project.core.ui.echo(
                "The exported requirements file is no longer cross-platform. "
                "Using it on other platforms may cause unexpected result.",
                fg="yellow",
                err=True,
            )
            candidates = resolve_candidates_from_lockfile(
                project, requirements.values()
            )
            packages = candidates.values()

        content = FORMATS[options.format].export(
            project, packages, options
        )  # type: ignore
        if options.output:
            Path(options.output).write_text(content)
        else:
            project.core.ui.echo(content)
Exemplo n.º 2
0
def do_sync(
    project: Project,
    *,
    groups: Sequence[str] = (),
    dev: bool = True,
    default: bool = True,
    dry_run: bool = False,
    clean: bool = False,
    requirements: list[Requirement] | None = None,
    tracked_names: Sequence[str] | None = None,
    no_editable: bool = False,
    no_self: bool = False,
    reinstall: bool = False,
) -> None:
    """Synchronize project"""
    if requirements is None:
        if not project.lockfile_file.exists():
            raise ProjectError("Lock file does not exist, nothing to sync")
        elif not project.is_lockfile_compatible():
            project.core.ui.echo(
                "Lock file version is not compatible with PDM, "
                "install may fail, please regenerate the pdm.lock",
                err=True,
            )
        elif not project.is_lockfile_hash_match():
            project.core.ui.echo(
                "Lock file hash doesn't match pyproject.toml, packages may be outdated",
                err=True,
            )
        groups = translate_groups(project, default, dev, groups or ())
        requirements = []
        for group in groups:
            requirements.extend(project.get_dependencies(group).values())
    candidates = resolve_candidates_from_lockfile(project, requirements)
    if tracked_names and dry_run:
        candidates = {
            name: c
            for name, c in candidates.items() if name in tracked_names
        }

    handler = project.core.synchronizer_class(
        candidates,
        project.environment,
        clean,
        dry_run,
        no_editable=no_editable,
        install_self=not no_self and "default" in groups
        and bool(project.meta.name),
        use_install_cache=project.config["feature.install_cache"],
        reinstall=reinstall,
    )
    handler.synchronize()
Exemplo n.º 3
0
def do_sync(
    project: Project,
    *,
    groups: Collection[str] = (),
    dev: bool = True,
    default: bool = True,
    dry_run: bool = False,
    clean: bool = False,
    requirements: list[Requirement] | None = None,
    tracked_names: Collection[str] | None = None,
    no_editable: bool | Collection[str] = False,
    no_self: bool = False,
    reinstall: bool = False,
) -> None:
    """Synchronize project"""
    if requirements is None:
        groups = translate_groups(project, default, dev, groups or ())
        requirements = []
        for group in groups:
            requirements.extend(project.get_dependencies(group).values())
    candidates = resolve_candidates_from_lockfile(project, requirements)
    if tracked_names and dry_run:
        candidates = {
            name: c for name, c in candidates.items() if name in tracked_names
        }
    handler = project.core.synchronizer_class(
        candidates,
        project.environment,
        clean,
        dry_run,
        no_editable=no_editable,
        install_self=not no_self and "default" in groups and bool(project.name),
        use_install_cache=project.config["install.cache"],
        reinstall=reinstall,
    )
    signals.pre_install.send(project, candidates=candidates, dry_run=dry_run)
    handler.synchronize()
    signals.post_install.send(project, candidates=candidates, dry_run=dry_run)
Exemplo n.º 4
0
def do_update(
    project: Project,
    *,
    dev: bool | None = None,
    groups: Sequence[str] = (),
    default: bool = True,
    strategy: str = "reuse",
    save: str = "compatible",
    unconstrained: bool = False,
    top: bool = False,
    dry_run: bool = False,
    packages: Collection[str] = (),
    sync: bool = True,
    no_editable: bool = False,
    no_self: bool = False,
    prerelease: bool = False,
) -> None:
    """Update specified packages or all packages"""
    check_project_file(project)
    if len(packages) > 0 and (top or len(groups) > 1 or not default):
        raise PdmUsageError(
            "packages argument can't be used together with multiple -G or "
            "--no-default and --top."
        )
    all_dependencies = project.all_dependencies
    updated_deps: dict[str, dict[str, Requirement]] = defaultdict(dict)
    install_dev = True if dev is None else dev
    if not packages:
        if prerelease:
            raise PdmUsageError("--prerelease must be used with packages given")
        groups = translate_groups(project, default, install_dev, groups or ())
        for group in groups:
            updated_deps[group] = all_dependencies[group]
    else:
        group = groups[0] if groups else ("dev" if dev else "default")
        dependencies = all_dependencies[group]
        for name in packages:
            matched_name = next(
                filter(
                    lambda k: normalize_name(strip_extras(k)[0])
                    == normalize_name(name),
                    dependencies.keys(),
                ),
                None,
            )
            if not matched_name:
                raise ProjectError(
                    "{} does not exist in {} {}dependencies.".format(
                        termui.green(name, bold=True), group, "dev-" if dev else ""
                    )
                )
            dependencies[matched_name].prerelease = prerelease
            updated_deps[group][matched_name] = dependencies[matched_name]
        project.core.ui.echo(
            "Updating packages: {}.".format(
                ", ".join(
                    termui.green(v, bold=True)
                    for v in chain.from_iterable(updated_deps.values())
                )
            )
        )
    if unconstrained:
        for deps in updated_deps.values():
            for dep in deps.values():
                dep.specifier = get_specifier("")
    reqs = [r for deps in all_dependencies.values() for r in deps.values()]
    resolved = do_lock(
        project,
        strategy,
        chain.from_iterable(updated_deps.values()),
        reqs,
        dry_run=dry_run,
    )
    if sync or dry_run:
        do_sync(
            project,
            groups=groups,
            dev=install_dev,
            default=default,
            clean=False,
            dry_run=dry_run,
            requirements=[r for deps in updated_deps.values() for r in deps.values()],
            tracked_names=list(chain.from_iterable(updated_deps.values()))
            if top
            else None,
            no_editable=no_editable,
            no_self=no_self,
        )
    if unconstrained and not dry_run:
        # Need to update version constraints
        save_version_specifiers(updated_deps, resolved, save)
        for group, deps in updated_deps.items():
            project.add_dependencies(deps, group, dev or False)
        lockfile = project.lockfile
        project.write_lockfile(lockfile, False)
Exemplo n.º 5
0
def test_prod_should_not_be_with_dev(project):
    setup_dependencies(project)
    with pytest.raises(PdmUsageError):
        cli_utils.translate_groups(project, True, False, ("test", ))
Exemplo n.º 6
0
def test_dependency_group_selection(project, args, golden):
    setup_dependencies(project)
    target = cli_utils.translate_groups(project, *args)
    assert sorted(golden) == sorted(target)