def _convert_req(name: str, req_dict: RequirementDict) -> str: if not getattr(req_dict, "items", None): assert isinstance(req_dict, str) return Requirement.from_req_dict( name, _convert_specifier(req_dict)).as_line() assert isinstance(req_dict, dict) req_dict = dict(req_dict) req_dict.pop("optional", None) # Ignore the 'optional' key if "version" in req_dict: req_dict["version"] = _convert_specifier(str(req_dict["version"])) markers: list[Marker] = [] if "markers" in req_dict: markers.append(Marker(req_dict.pop("markers"))) # type: ignore if "python" in req_dict: markers.append( Marker( _convert_python(str( req_dict.pop("python"))).as_marker_string())) if markers: req_dict["marker"] = str(functools.reduce(operator.and_, markers)).replace('"', "'") if "rev" in req_dict or "branch" in req_dict or "tag" in req_dict: req_dict["ref"] = req_dict.pop( "rev", req_dict.pop("tag", req_dict.pop("branch", None)) # type: ignore ) return Requirement.from_req_dict(name, req_dict).as_line()
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 optional_dependencies(self, source: Dict[str, Any]) -> Dict[str, List[str]]: extras = {} for key, reqs in list(source.items()): if key.endswith("-dependencies") and key != "dev-dependencies": reqs = cast(Dict[str, RequirementDict], reqs) extra_key = key.split("-", 1)[0] extras[extra_key] = [ Requirement.from_req_dict(name, req).as_line() for name, req in reqs.items() ] source.pop(key) for name in cast(List[str], source.pop("extras", [])): if name in extras: continue if "=" in name: key, others = name.split("=", 1) parts = others.split("|") extras[key] = list( functools.reduce( lambda x, y: cast(Set[str], x).union(extras[y]), parts, cast(Set[str], set()), )) return extras
def test_convert_req_dict_to_req_line(req, req_dict, result): r = parse_requirement(req) assert r.as_req_dict() == req_dict assert r.as_ireq() r = Requirement.from_req_dict(*req_dict) result = result or req assert r.as_line() == result
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") req = Requirement.from_req_dict(package_name, dict(package)) can = Candidate(req, self.environment, name=package_name, version=version) can.marker = req.marker can.hashes = { item["file"]: item["hash"] for item in self.lockfile["metadata"].get("files", {}).get( f"{req.key} {version}", []) } or None result[req.identify()] = can if section in ("default", "__all__") and self.meta.name and self.meta.version: result[self.meta.project_name.lower()] = self.make_self_candidate( True) return result
def _read_lockfile(self, lockfile: Mapping[str, Any]) -> None: for package in lockfile.get("package", []): version = package.get("version") if version: package["version"] = f"=={version}" package_name = package.pop("name") req_dict = { k: v for k, v in package.items() if k not in ("dependencies", "requires_python", "summary") } req = Requirement.from_req_dict(package_name, req_dict) can = Candidate(req, name=package_name, version=version) can_id = self._identify_candidate(can) self.packages[can_id] = can candidate_info: CandidateInfo = ( package.get("dependencies", []), package.get("requires_python", ""), package.get("summary", ""), ) self.candidate_info[can_id] = candidate_info for key, hashes in lockfile.get("metadata", {}).get("files", {}).items(): self.file_hashes[tuple(key.split(None, 1))] = { # type: ignore item["file"]: item["hash"] for item in hashes }
def get_requirements_from_dist(dist: EggInfoDistribution, extras: Sequence[str]) -> List[str]: """Get requirements of a distribution, with given extras.""" extras_in_metadata = [] result = [] dep_map = dist._build_dep_map() for extra, reqs in dep_map.items(): reqs = [Requirement.from_pkg_requirement(r) for r in reqs] if not extra: # requirements without extras are always required. result.extend(r.as_line() for r in reqs) else: new_extra, _, marker = extra.partition(":") extras_in_metadata.append(new_extra.strip()) # Only include requirements that match one of extras. if not new_extra.strip() or safe_extra( new_extra.strip()) in extras: marker = Marker(marker) if marker else None for r in reqs: r.marker = marker result.append(r.as_line()) extras_not_found = [e for e in extras if e not in extras_in_metadata] if extras_not_found: warnings.warn(ExtrasError(extras_not_found)) return result
def add_package(key: str, dist: Distribution) -> Package: 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[req.identify()] = 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 dev_dependencies(self, value): return make_array( [ Requirement.from_req_dict(name, req).as_line() for name, req in value.items() ], True, )
def dependencies(self, value: Dict[str, str]) -> List[str]: return make_array( [ Requirement.from_req_dict(name, req).as_line() for name, req in value.items() ], True, )
def dev_dependencies(self, value: Dict[str, RequirementDict]) -> None: self.settings["dev-dependencies"] = { "dev": make_array( [ Requirement.from_req_dict(name, req).as_line() for name, req in value.items() ], True, ) } raise Unset()
def _convert_req(name, req_dict): if not getattr(req_dict, "items", None): return Requirement.from_req_dict( name, _convert_specifier(req_dict)).as_line() req_dict = dict(req_dict) if "version" in req_dict: req_dict["version"] = _convert_specifier(req_dict["version"]) markers = [] if "markers" in req_dict: markers.append(Marker(req_dict.pop("markers"))) if "python" in req_dict: markers.append( Marker(_convert_python(req_dict.pop("python")).as_marker_string())) if markers: req_dict["marker"] = str(functools.reduce(operator.and_, markers)).replace('"', "'") if "rev" in req_dict or "branch" in req_dict or "tag" in req_dict: req_dict["ref"] = req_dict.pop( "rev", req_dict.pop("tag", req_dict.pop("branch", None))) return Requirement.from_req_dict(name, req_dict).as_line()
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 convert_pipfile_requirement(name, req): markers = [] if "markers" in req: markers.append(Marker(req["markers"])) for key in MARKER_KEYS: if key in req: marker = Marker(f"{key}{req[key]}") markers.append(marker) del req[key] if markers: marker = functools.reduce(operator.and_, markers) req["marker"] = str(marker).replace('"', "'") return Requirement.from_req_dict(name, req).as_line()
def convert_pipfile_requirement(name: str, req: RequirementDict) -> str: if isinstance(req, dict): markers: list[Marker] = [] if "markers" in req: markers.append(Marker(req["markers"])) # type: ignore for key in MARKER_KEYS: if key in req: marker = Marker(f"{key}{req[key]}") markers.append(marker) del req[key] if markers: marker = functools.reduce(operator.and_, markers) req["marker"] = str(marker).replace('"', "'") return Requirement.from_req_dict(name, req).as_line()
def find_candidates( self, requirement: Requirement, requires_python: PySpecSet = ALLOW_ALL_PYTHON, allow_prereleases: Optional[bool] = None, allow_all: bool = False, ) -> Iterable[Candidate]: for key, info in self.candidate_info.items(): if key[0] != requirement.identify(): continue if not (requires_python & PySpecSet(info[1])).contains( str(self.environment.interpreter.version)): continue can = self.packages[key] can.requires_python = info[1] yield can
def do_list( project: Project, graph: bool = False, reverse: bool = False, freeze: bool = False, json: bool = False, ) -> None: """Display a list of packages installed in the local packages directory.""" from pdm.cli.utils import build_dependency_graph, format_dependency_graph check_project_file(project) working_set = project.environment.get_working_set() if graph: dep_graph = build_dependency_graph( working_set, project.environment.marker_environment ) project.core.ui.echo( format_dependency_graph(project, dep_graph, reverse=reverse, json=json) ) else: if reverse: raise PdmUsageError("--reverse must be used with --graph") if json: raise PdmUsageError("--json must be used with --graph") if freeze: reqs = sorted( ( Requirement.from_dist(dist) .as_line() .replace( "${PROJECT_ROOT}", project.root.absolute().as_posix().lstrip("/"), ) for dist in sorted( working_set.values(), key=lambda d: d.metadata["Name"] ) ), key=lambda x: x.lower(), ) project.core.ui.echo("\n".join(reqs)) return rows = [ (termui.green(k, bold=True), termui.yellow(v.version), get_dist_location(v)) for k, v in sorted(working_set.items()) ] project.core.ui.display_columns(rows, ["Package", "Version", "Location"])
def find_candidates( self, requirement: Requirement, allow_prereleases: bool | None = None, ignore_requires_python: bool = False, ) -> Iterable[Candidate]: for key, info in self.candidate_info.items(): if key[0] != requirement.identify(): continue if not PySpecSet(info[1]).contains( str(self.environment.interpreter.version), True ): continue can = self.packages[key] can.requires_python = info[1] can.prepare(self.environment) can.req = requirement yield can
def optional_dependencies(self, source): extras = {} for key, reqs in list(source.items()): if key.endswith("-dependencies") and key != "dev-dependencies": extra_key = key.split("-", 1)[0] extras[extra_key] = [ Requirement.from_req_dict(name, req).as_line() for name, req in reqs.items() ] source.pop(key) for name in source.pop("extras", []): if name in extras: continue if "=" in name: key, parts = name.split("=", 1) parts = parts.split("|") extras[key] = list( functools.reduce(lambda x, y: x.union(extras[y]), parts, set()) ) return extras