def search_for_url(self, dependency: URLDependency) -> list[Package]: if dependency in self._deferred_cache: return [self._deferred_cache[dependency]] package = self.get_package_from_url(dependency.url) if dependency.name != package.name: # For now, the dependency's name must match the actual package's name raise RuntimeError( f"The dependency name for {dependency.name} does not match the actual" f" package's name: {package.name}") for extra in dependency.extras: if extra in package.extras: for dep in package.extras[extra]: dep.activate() for extra_dep in package.extras[extra]: package.add_dependency(extra_dep) dependency._constraint = package.version dependency._pretty_constraint = package.version.text self._deferred_cache[dependency] = package return [package]
def search_for_url(self, dependency: URLDependency) -> List[Package]: if dependency in self._deferred_cache: return [self._deferred_cache[dependency]] package = self.get_package_from_url(dependency.url) if dependency.name != package.name: # For now, the dependency's name must match the actual package's name raise RuntimeError( "The dependency name for {} does not match the actual package's name: {}" .format(dependency.name, package.name)) for extra in dependency.extras: if extra in package.extras: for dep in package.extras[extra]: dep.activate() package.requires += package.extras[extra] dependency._constraint = package.version dependency._pretty_constraint = package.version.text self._deferred_cache[dependency] = package return [package]
def test_to_pep_508(): dependency = URLDependency( "pytorch", "https://download.pytorch.org/whl/cpu/torch-1.5.1%2Bcpu-cp38-cp38-linux_x86_64.whl", ) expected = "pytorch @ https://download.pytorch.org/whl/cpu/torch-1.5.1%2Bcpu-cp38-cp38-linux_x86_64.whl" assert expected == dependency.to_pep_508()
def test_to_pep_508_with_marker(): dependency = URLDependency( "pytorch", "https://download.pytorch.org/whl/cpu/torch-1.5.1%2Bcpu-cp38-cp38-linux_x86_64.whl", ) dependency.marker = SingleMarker("sys.platform", "linux") expected = 'pytorch @ https://download.pytorch.org/whl/cpu/torch-1.5.1%2Bcpu-cp38-cp38-linux_x86_64.whl ; sys_platform == "linux"' assert expected == dependency.to_pep_508()
def test_to_pep_508() -> None: dependency = URLDependency( "pytorch", "https://download.pytorch.org/whl/cpu/torch-1.5.1%2Bcpu-cp38-cp38-linux_x86_64.whl", ) expected = ( "pytorch @" " https://download.pytorch.org/whl/cpu/torch-1.5.1%2Bcpu-cp38-cp38-linux_x86_64.whl" ) assert dependency.to_pep_508() == expected
def test_to_pep_508_with_extras() -> None: dependency = URLDependency( "pytorch", "https://download.pytorch.org/whl/cpu/torch-1.5.1%2Bcpu-cp38-cp38-linux_x86_64.whl", extras=["foo", "bar"], ) expected = ( "pytorch[bar,foo] @" " https://download.pytorch.org/whl/cpu/torch-1.5.1%2Bcpu-cp38-cp38-linux_x86_64.whl" ) assert expected == dependency.to_pep_508()
def search_for_url(self, dependency: URLDependency) -> list[Package]: if dependency in self._deferred_cache: return [self._deferred_cache[dependency]] package = self.get_package_from_url(dependency.url) self.validate_package_for_dependency(dependency=dependency, package=package) for extra in dependency.extras: if extra in package.extras: for dep in package.extras[extra]: dep.activate() for extra_dep in package.extras[extra]: package.add_dependency(extra_dep) dependency._constraint = package.version dependency._pretty_constraint = package.version.text self._deferred_cache[dependency] = package return [package]
def _export_requirements_txt( self, cwd, output, with_hashes=True, dev=False, extras=None, with_credentials=False, ): # type: (Path, Union[IO, str], bool, bool, bool) -> None indexes = set() content = "" packages = self._poetry.locker.locked_repository(dev).packages # Build a set of all packages required by our selected extras extra_package_names = set( get_extra_package_names( packages, self._poetry.locker.lock_data.get("extras", {}), extras or ())) for package in sorted(packages, key=lambda p: p.name): # If a package is optional and we haven't opted in to it, continue if package.optional and package.name not in extra_package_names: continue if package.source_type == "git": dependency = VCSDependency( package.name, package.source_type, package.source_url, package.source_reference, ) dependency.marker = package.marker line = "-e git+{}@{}#egg={}".format(package.source_url, package.source_reference, package.name) elif package.source_type in ["directory", "file", "url"]: url = package.source_url if package.source_type == "file": dependency = FileDependency( package.name, Path(package.source_url), base=self._poetry.locker.lock.path.parent, ) url = Path( os.path.relpath( url, self._poetry.locker.lock.path.parent.as_posix( ))).as_posix() elif package.source_type == "directory": dependency = DirectoryDependency( package.name, Path(package.source_url), base=self._poetry.locker.lock.path.parent, ) url = Path( os.path.relpath( url, self._poetry.locker.lock.path.parent.as_posix( ))).as_posix() else: dependency = URLDependency(package.name, package.source_url) dependency.marker = package.marker line = "{}".format(url) if package.develop and package.source_type == "directory": line = "-e " + line else: dependency = package.to_dependency() line = "{}=={}".format(package.name, package.version) requirement = dependency.to_pep_508() if ";" in requirement: line += "; {}".format(requirement.split(";")[1].strip()) if (package.source_type not in {"git", "directory", "file", "url"} and package.source_url): indexes.add(package.source_url) if package.files and with_hashes: hashes = [] for f in package.files: h = f["hash"] algorithm = "sha256" if ":" in h: algorithm, h = h.split(":") if algorithm not in self.ALLOWED_HASH_ALGORITHMS: continue hashes.append("{}:{}".format(algorithm, h)) if hashes: line += " \\\n" for i, h in enumerate(hashes): line += " --hash={}{}".format( h, " \\\n" if i < len(hashes) - 1 else "") line += "\n" content += line if indexes: # If we have extra indexes, we add them to the beginning of the output indexes_header = "" for index in sorted(indexes): repository = [ r for r in self._poetry.pool.repositories if r.url == index.rstrip("/") ][0] if (self._poetry.pool.has_default() and repository is self._poetry.pool.repositories[0]): url = (repository.authenticated_url if with_credentials else repository.url) indexes_header = "--index-url {}\n".format(url) continue url = (repository.authenticated_url if with_credentials else repository.url) indexes_header += "--extra-index-url {}\n".format(url) content = indexes_header + "\n" + content self._output(content, cwd, output)
def to_dependency(self) -> Dependency: from pathlib import Path from poetry.core.packages.dependency import Dependency from poetry.core.packages.directory_dependency import DirectoryDependency from poetry.core.packages.file_dependency import FileDependency from poetry.core.packages.url_dependency import URLDependency from poetry.core.packages.vcs_dependency import VCSDependency dep: Dependency if self.source_type == "directory": dep = DirectoryDependency( self._name, Path(cast(str, self._source_url)), groups=list(self._dependency_groups.keys()), optional=self.optional, base=self.root_dir, develop=self.develop, extras=self.features, ) elif self.source_type == "file": dep = FileDependency( self._name, Path(cast(str, self._source_url)), groups=list(self._dependency_groups.keys()), optional=self.optional, base=self.root_dir, extras=self.features, ) elif self.source_type == "url": dep = URLDependency( self._name, cast(str, self._source_url), groups=list(self._dependency_groups.keys()), optional=self.optional, extras=self.features, ) elif self.source_type == "git": dep = VCSDependency( self._name, self.source_type, cast(str, self.source_url), rev=self.source_reference, resolved_rev=self.source_resolved_reference, directory=self.source_subdirectory, groups=list(self._dependency_groups.keys()), optional=self.optional, develop=self.develop, extras=self.features, ) else: dep = Dependency(self._name, self._version, extras=self.features) if not self.marker.is_any(): dep.marker = self.marker if not self.python_constraint.is_any(): dep.python_versions = self.python_versions if not self.is_direct_origin(): return dep return dep.with_constraint(self._version)
def create_from_pep_508(cls, name: str, relative_to: Path | None = None) -> Dependency: """ Resolve a PEP-508 requirement string to a `Dependency` instance. If a `relative_to` path is specified, this is used as the base directory if the identified dependency is of file or directory type. """ from poetry.core.packages.url_dependency import URLDependency from poetry.core.packages.utils.link import Link from poetry.core.packages.utils.utils import is_archive_file from poetry.core.packages.utils.utils import is_installable_dir from poetry.core.packages.utils.utils import is_url from poetry.core.packages.utils.utils import path_to_url from poetry.core.packages.utils.utils import strip_extras from poetry.core.packages.utils.utils import url_to_path from poetry.core.packages.vcs_dependency import VCSDependency from poetry.core.utils.patterns import wheel_file_re from poetry.core.vcs.git import ParsedUrl from poetry.core.version.requirements import Requirement # Removing comments parts = name.split(" #", 1) name = parts[0].strip() if len(parts) > 1: rest = parts[1] if " ;" in rest: name += " ;" + rest.split(" ;", 1)[1] req = Requirement(name) name = req.name link = None if is_url(name): link = Link(name) elif req.url: link = Link(req.url) else: path_str = os.path.normpath(os.path.abspath(name)) p, extras = strip_extras(path_str) if os.path.isdir(p) and (os.path.sep in name or name.startswith(".")): if not is_installable_dir(p): raise ValueError( f"Directory {name!r} is not installable. File 'setup.py' " "not found.") link = Link(path_to_url(p)) elif is_archive_file(p): link = Link(path_to_url(p)) # it's a local file, dir, or url if link: is_file_uri = link.scheme == "file" is_relative_uri = is_file_uri and re.search(r"\.\./", link.url) # Handle relative file URLs if is_file_uri and is_relative_uri: path = Path(link.path) if relative_to: path = relative_to / path link = Link(path_to_url(path)) # wheel file version = None if link.is_wheel: m = wheel_file_re.match(link.filename) if not m: raise ValueError(f"Invalid wheel name: {link.filename}") name = m.group("name") version = m.group("ver") dep: Dependency | None = None if link.scheme.startswith("git+"): url = ParsedUrl.parse(link.url) dep = VCSDependency( name, "git", url.url, rev=url.rev, directory=url.subdirectory, extras=req.extras, ) elif link.scheme == "git": dep = VCSDependency(name, "git", link.url_without_fragment, extras=req.extras) elif link.scheme in ["http", "https"]: dep = URLDependency(name, link.url, extras=req.extras) elif is_file_uri: # handle RFC 8089 references path = url_to_path(req.url) dep = _make_file_or_dir_dep(name=name, path=path, base=relative_to, extras=req.extras) else: with suppress(ValueError): # this is a local path not using the file URI scheme dep = _make_file_or_dir_dep( name=name, path=Path(req.url), base=relative_to, extras=req.extras, ) if dep is None: dep = Dependency(name, version or "*", extras=req.extras) if version: dep._constraint = parse_constraint(version) else: constraint: VersionConstraint | str if req.pretty_constraint: constraint = req.constraint else: constraint = "*" dep = Dependency(name, constraint, extras=req.extras) if req.marker: dep.marker = req.marker return dep
def create_dependency( cls, name: str, constraint: DependencyConstraint, groups: list[str] | None = None, root_dir: Path | None = None, ) -> Dependency: from poetry.core.packages.constraints import ( parse_constraint as parse_generic_constraint, ) from poetry.core.packages.dependency import Dependency from poetry.core.packages.dependency_group import MAIN_GROUP from poetry.core.packages.directory_dependency import DirectoryDependency from poetry.core.packages.file_dependency import FileDependency from poetry.core.packages.url_dependency import URLDependency from poetry.core.packages.utils.utils import create_nested_marker from poetry.core.packages.vcs_dependency import VCSDependency from poetry.core.semver.helpers import parse_constraint from poetry.core.version.markers import AnyMarker from poetry.core.version.markers import parse_marker if groups is None: groups = [MAIN_GROUP] if constraint is None: constraint = "*" if isinstance(constraint, dict): optional = constraint.get("optional", False) python_versions = constraint.get("python") platform = constraint.get("platform") markers = constraint.get("markers") if "allows-prereleases" in constraint: message = ( f'The "{name}" dependency specifies ' 'the "allows-prereleases" property, which is deprecated. ' 'Use "allow-prereleases" instead.') warn(message, DeprecationWarning) logger.warning(message) allows_prereleases = constraint.get( "allow-prereleases", constraint.get("allows-prereleases", False)) dependency: Dependency if "git" in constraint: # VCS dependency dependency = VCSDependency( name, "git", constraint["git"], branch=constraint.get("branch", None), tag=constraint.get("tag", None), rev=constraint.get("rev", None), directory=constraint.get("subdirectory", None), groups=groups, optional=optional, develop=constraint.get("develop", False), extras=constraint.get("extras", []), ) elif "file" in constraint: file_path = Path(constraint["file"]) dependency = FileDependency( name, file_path, groups=groups, base=root_dir, extras=constraint.get("extras", []), ) elif "path" in constraint: path = Path(constraint["path"]) if root_dir: is_file = root_dir.joinpath(path).is_file() else: is_file = path.is_file() if is_file: dependency = FileDependency( name, path, groups=groups, optional=optional, base=root_dir, extras=constraint.get("extras", []), ) else: dependency = DirectoryDependency( name, path, groups=groups, optional=optional, base=root_dir, develop=constraint.get("develop", False), extras=constraint.get("extras", []), ) elif "url" in constraint: dependency = URLDependency( name, constraint["url"], groups=groups, optional=optional, extras=constraint.get("extras", []), ) else: version = constraint["version"] dependency = Dependency( name, version, optional=optional, groups=groups, allows_prereleases=allows_prereleases, extras=constraint.get("extras", []), ) marker = parse_marker(markers) if markers else AnyMarker() if python_versions: marker = marker.intersect( parse_marker( create_nested_marker( "python_version", parse_constraint(python_versions)))) if platform: marker = marker.intersect( parse_marker( create_nested_marker( "sys_platform", parse_generic_constraint(platform)))) if not marker.is_any(): dependency.marker = marker dependency.source_name = constraint.get("source") else: dependency = Dependency(name, constraint, groups=groups) return dependency