def do_sync( project: Project, sections: Sequence[str] = (), dev: bool = False, default: bool = True, dry_run: bool = False, clean: Optional[bool] = None, ) -> None: """Synchronize project :param project: The project instance. :param sections: A tuple of optional sections to be synced. :param dev: whether to include dev-dependencies. :param default: whether to include default dependencies. :param dry_run: Print actions without actually running them. :param clean: whether to remove unneeded packages. """ if not project.lockfile_file.exists(): raise ProjectError("Lock file does not exist, nothing to sync") clean = default if clean is None else clean candidates = {} for section in sections: if section not in list(project.iter_sections()): raise PdmUsageError( f"Section {termui.green(repr(section))} doesn't exist " "in the pyproject.toml") candidates.update(project.get_locked_candidates(section)) if dev: candidates.update(project.get_locked_candidates("dev")) if default: candidates.update(project.get_locked_candidates()) handler = project.core.synchronizer_class(candidates, project.environment) handler.synchronize(clean=clean, dry_run=dry_run)
def translate_sections(project: Project, default: bool, dev: bool, sections: Iterable[str]) -> list[str]: """Translate default, dev and sections containing ":all" into a list of sections""" optional_groups = set(project.meta.optional_dependencies or []) dev_groups = set(project.tool_settings.get("dev-dependencies", [])) sections_set = set(sections) if dev is None: dev = True if sections_set & dev_groups: if not dev: raise PdmUsageError( "--prod is not allowed with dev sections and should be left") elif dev: sections_set.update(dev_groups) if ":all" in sections: sections_set.discard(":all") sections_set.update(optional_groups) if default: sections_set.add("default") # Sorts the result in ascending order instead of in random order # to make this function pure invalid_sections = sections_set - set(project.iter_sections()) if invalid_sections: project.core.ui.echo( f"Ignoring non-existing sections: {invalid_sections}", fg="yellow", err=True) sections_set -= invalid_sections return sorted(sections_set)
def do_sync( project: Project, sections: Sequence[str] = (), dev: bool = False, default: bool = True, dry_run: bool = False, clean: Optional[bool] = None, tracked_names: Optional[Sequence[str]] = None, ) -> None: """Synchronize project""" if not project.lockfile_file.exists(): raise ProjectError("Lock file does not exist, nothing to sync") clean = default if clean is None else clean if tracked_names and dry_run: candidates = { name: c for name, c in project.get_locked_candidates("__all__").items() if name in tracked_names } else: candidates = {} sections = translate_sections(project, default, dev, sections or ()) valid_sections = list(project.iter_sections()) for section in sections: if section not in valid_sections: raise PdmUsageError( f"Section {termui.green(repr(section))} doesn't exist " "in the pyproject.toml") candidates.update(project.get_locked_candidates(section)) handler = project.core.synchronizer_class(candidates, project.environment, clean, dry_run) handler.synchronize()
def do_remove( project: Project, dev: bool = False, section: Optional[str] = None, sync: bool = True, packages: Sequence[str] = (), ): """Remove packages from working set and pyproject.toml :param project: The project instance :param dev: Remove package from dev-dependencies :param section: Remove package from given section :param sync: Whether perform syncing action :param packages: Package names to be removed :return: None """ check_project_file(project) if not packages: raise PdmUsageError("Must specify at least one package to remove.") if not section: section = "dev" if dev else "default" if section not in list(project.iter_sections()): raise ProjectError(f"No-exist section {section}") deps = project.get_pyproject_dependencies(section, dev) project.core.ui.echo( f"Removing packages from {section} {'dev-' if dev else ''}dependencies: " + ", ".join(str(termui.green(name, bold=True)) for name in packages) ) for name in packages: req = parse_requirement(name) matched_indexes = sorted( (i for i, r in enumerate(deps) if req.matches(r, False)), reverse=True ) if not matched_indexes: raise ProjectError( "{} does not exist in {} dependencies.".format( termui.green(name, bold=True), section ) ) for i in matched_indexes: del deps[i] project.write_pyproject() do_lock(project, "reuse") if sync: do_sync(project, sections=(section,), default=False, clean=True)