def add_package(key, dist): name, extras = strip_extras(key) extras = extras or () reqs = {} if dist: requirements = [ Requirement.from_pkg_requirement(r) for r in dist.requires(extras) ] for req in requirements: reqs[identify(req)] = req version = dist.version else: version = None node = Package(key, version, reqs) if node not in graph: if extras: node_with_extras.add(name) graph.add(node) for k in reqs: child = add_package(k, working_set.get(strip_extras(k)[0])) graph.connect(node, child) return node
def get_locked_candidates( self, section: Optional[str] = None ) -> Dict[str, Candidate]: if not self.lockfile_file.is_file(): return {} section = section or "default" result = {} for package in [dict(p) for p in self.lockfile.get("package", [])]: if section != "__all__" and section not in package["sections"]: continue version = package.get("version") if version: package["version"] = f"=={version}" package_name = package.pop("name") summary = package.pop("summary", None) dependencies = [ Requirement.from_req_dict(k, v) for k, v in package.pop("dependencies", {}).items() ] req = Requirement.from_req_dict(package_name, dict(package)) can = Candidate(req, self.environment, name=package_name, version=version) can.marker = req.marker can.requires_python = str(req.requires_python) can.dependencies = dependencies can.summary = summary can.hashes = { item["file"]: item["hash"] for item in self.lockfile["metadata"].get( f"{package_name} {version}", [] ) } or None result[identify(req)] = can if section in ("default", "__all__") and self.meta.name: result[safe_name(self.meta.name).lower()] = self.make_self_candidate(True) return result
def resolve_requirements( repository, lines, requires_python="", allow_prereleases=None, strategy="reuse", preferred_pins=None, tracked_names=None, ): requirements = {} if isinstance(lines, list): lines = {"default": lines} for k, v in lines.items(): for line in v: req = parse_requirement(line) requirements.setdefault(k, {})[identify(req)] = req 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, ) flat_reqs = list( itertools.chain(*[deps.values() for _, deps in requirements.items()])) reporter = SimpleReporter(flat_reqs) resolver = Resolver(provider, reporter) mapping, *_ = resolve(resolver, requirements, requires_python) return mapping
def do_add( project: Project, dev: bool = False, section: Optional[str] = None, sync: bool = True, save: str = "compatible", strategy: str = "reuse", editables: Iterable[str] = (), packages: Iterable[str] = (), ) -> None: """Add packages and install :param project: the project instance :param dev: add to dev dependencies seciton :param section: specify section to be add to :param sync: whether to install added packages :param save: save strategy :param strategy: update strategy :param editables: editable requirements :param packages: normal requirements """ check_project_file(project) if not editables and not packages: raise click.BadParameter( "Must specify at least one package or editable package.") section = "dev" if dev else section or "default" tracked_names = set() requirements = {} for r in [parse_requirement(line, True) for line in editables ] + [parse_requirement(line) for line in packages]: key = identify(r) r.from_section = section tracked_names.add(key) requirements[key] = r context.io.echo(f"Adding packages to {section} dependencies: " + ", ".join( str(context.io.green(key, bold=True)) for key in requirements)) all_dependencies = project.all_dependencies all_dependencies.setdefault(section, {}).update(requirements) resolved = do_lock(project, strategy, tracked_names, all_dependencies) # Update dependency specifiers and lockfile hash. save_version_specifiers(requirements, resolved, save) project.add_dependencies(requirements) lockfile = project.lockfile lockfile["root"]["content_hash"] = "md5:" + project.get_content_hash("md5") project.write_lockfile(lockfile, False) if sync: do_sync( project, sections=(section, ), dev=False, default=False, dry_run=False, clean=False, )
def get_dependencies(self, section: Optional[str] = None) -> Dict[str, Requirement]: if section in (None, "default"): deps = self.tool_settings.get("dependencies", []) elif section == "dev": deps = self.tool_settings.get("dev-dependencies", []) else: deps = self.tool_settings[f"{section}-dependencies"] result = {} for name, dep in deps.items(): req = Requirement.from_req_dict(name, dep) req.from_section = section or "default" result[identify(req)] = req return result
def identify(self, req: Union[Requirement, Candidate]) -> Optional[str]: return identify(req)