def find_latest_package( self, package: Package, root: ProjectPackage ) -> Package | None: from cleo.io.null_io import NullIO from poetry.puzzle.provider import Provider from poetry.version.version_selector import VersionSelector # find the latest version allowed in this pool if package.source_type in ("git", "file", "directory"): requires = root.all_requires for dep in requires: if dep.name == package.name: provider = Provider(root, self.poetry.pool, NullIO()) if dep.is_vcs(): dep = cast(VCSDependency, dep) return provider.search_for_vcs(dep)[0] if dep.is_file(): dep = cast(FileDependency, dep) return provider.search_for_file(dep)[0] if dep.is_directory(): dep = cast(DirectoryDependency, dep) return provider.search_for_directory(dep)[0] name = package.name selector = VersionSelector(self.poetry.pool) return selector.find_best_candidate(name, f">={package.pretty_version}")
def _parse_dependency_specification_path(requirement: str, cwd: Path) -> DependencySpec | None: if (os.path.sep in requirement or "/" in requirement) and ( cwd.joinpath(requirement).exists() or Path(requirement).expanduser().exists() and Path(requirement).expanduser().is_absolute()): path = Path(requirement).expanduser() is_absolute = path.is_absolute() if not path.is_absolute(): path = cwd.joinpath(requirement) if path.is_file(): package = Provider.get_package_from_file(path.resolve()) else: package = Provider.get_package_from_directory(path.resolve()) return { "name": package.name, "path": path.relative_to(cwd).as_posix() if not is_absolute else path.as_posix(), } return None
def find_latest_package(self, package, include_dev): from clikit.io import NullIO from poetry.puzzle.provider import Provider from poetry.version.version_selector import VersionSelector # find the latest version allowed in this pool if package.source_type in ("git", "file", "directory"): requires = self.poetry.package.requires if include_dev: requires = requires + self.poetry.package.dev_requires for dep in requires: if dep.name == package.name: provider = Provider(self.poetry.package, self.poetry.pool, NullIO()) if dep.is_vcs(): return provider.search_for_vcs(dep)[0] if dep.is_file(): return provider.search_for_file(dep)[0] if dep.is_directory(): return provider.search_for_directory(dep)[0] name = package.name selector = VersionSelector(self.poetry.pool) return selector.find_best_candidate( name, ">={}".format(package.pretty_version))
def find_latest_package(self, package: "Package", root: "ProjectPackage") -> Union["Package", bool]: from cleo.io.null_io import NullIO from poetry.puzzle.provider import Provider from poetry.version.version_selector import VersionSelector # find the latest version allowed in this pool if package.source_type in ("git", "file", "directory"): requires = root.all_requires for dep in requires: if dep.name == package.name: provider = Provider(root, self.poetry.pool, NullIO()) if dep.is_vcs(): return provider.search_for_vcs(dep)[0] if dep.is_file(): return provider.search_for_file(dep)[0] if dep.is_directory(): return provider.search_for_directory(dep)[0] name = package.name selector = VersionSelector(self.poetry.pool) return selector.find_best_candidate( name, ">={}".format(package.pretty_version))
def test_search_for_vcs_read_setup_raises_error_if_no_version( provider: Provider, mocker: MockerFixture): mocker.patch( "poetry.inspection.info.PackageInfo._pep517_metadata", return_value=PackageInfo(name="demo", version=None), ) dependency = VCSDependency("demo", "git", "https://github.com/demo/no-version.git") with pytest.raises(RuntimeError): provider.search_for_vcs(dependency)
def test_search_for_directory_setup_with_base(provider: Provider, directory: str): dependency = DirectoryDependency( "demo", Path(__file__).parent.parent / "fixtures" / "git" / "github.com" / "demo" / directory, base=Path(__file__).parent.parent / "fixtures" / "git" / "github.com" / "demo" / directory, ) package = provider.search_for_directory(dependency)[0] assert package.name == "demo" assert package.version.text == "0.1.2" required = [r for r in package.requires if not r.is_optional()] optional = [r for r in package.requires if r.is_optional()] assert required == [get_dependency("pendulum", ">=1.4.4")] assert optional == [get_dependency("tomlkit"), get_dependency("cleo")] assert package.extras == { "foo": [get_dependency("cleo")], "bar": [get_dependency("tomlkit")], } assert package.root_dir == (Path(__file__).parent.parent / "fixtures" / "git" / "github.com" / "demo" / directory)
def test_search_for_file_sdist(provider: Provider): dependency = FileDependency( "demo", Path(__file__).parent.parent / "fixtures" / "distributions" / "demo-0.1.0.tar.gz", ) package = provider.search_for_direct_origin_dependency(dependency) assert package.name == "demo" assert package.version.text == "0.1.0" required = [ r for r in sorted(package.requires, key=lambda r: r.name) if not r.is_optional() ] optional = [ r for r in sorted(package.requires, key=lambda r: r.name) if r.is_optional() ] assert required == [get_dependency("pendulum", ">=1.4.4")] assert optional == [ get_dependency("cleo"), get_dependency("tomlkit"), ] assert package.extras == { "foo": [get_dependency("cleo")], "bar": [get_dependency("tomlkit")], }
def test_search_for_directory_poetry_with_extras(provider: Provider): dependency = DirectoryDependency( "project-with-extras", Path(__file__).parent.parent / "fixtures" / "project_with_extras", extras=["extras_a"], ) package = provider.search_for_directory(dependency)[0] assert package.name == "project-with-extras" assert package.version.text == "1.2.3" required = [ r for r in sorted(package.requires, key=lambda r: r.name) if not r.is_optional() ] optional = [ r for r in sorted(package.requires, key=lambda r: r.name) if r.is_optional() ] assert required == [] assert optional == [ get_dependency("cachy", ">=0.2.0"), get_dependency("pendulum", ">=1.4.4"), ] assert package.extras == { "extras_a": [get_dependency("pendulum", ">=1.4.4")], "extras_b": [get_dependency("cachy", ">=0.2.0")], }
def _parse_dependency_specification_git_url(requirement: str, env: Env | None = None ) -> DependencySpec | None: from poetry.core.vcs.git import Git from poetry.core.vcs.git import ParsedUrl parsed = ParsedUrl.parse(requirement) url = Git.normalize_url(requirement) pair = {"name": parsed.name, "git": url.url} if parsed.rev: pair["rev"] = url.revision if parsed.subdirectory: pair["subdirectory"] = parsed.subdirectory source_root = env.path.joinpath("src") if env else None package = Provider.get_package_from_vcs( "git", url=url.url, rev=pair.get("rev"), subdirectory=parsed.subdirectory, source_root=source_root, ) pair["name"] = package.name return pair
def test_search_for_file_wheel_with_extras(provider: Provider): dependency = FileDependency( "demo", Path(__file__).parent.parent / "fixtures" / "distributions" / "demo-0.1.0-py2.py3-none-any.whl", extras=["foo"], ) package = provider.search_for_file(dependency)[0] assert package.name == "demo" assert package.version.text == "0.1.0" required = [ r for r in sorted(package.requires, key=lambda r: r.name) if not r.is_optional() ] optional = [ r for r in sorted(package.requires, key=lambda r: r.name) if r.is_optional() ] assert required == [get_dependency("pendulum", ">=1.4.4")] assert optional == [ get_dependency("cleo"), get_dependency("tomlkit"), ] assert package.extras == { "foo": [get_dependency("cleo")], "bar": [get_dependency("tomlkit")], }
def test_search_for_directory_setup_read_setup_with_extras( provider: Provider, mocker: MockerFixture ): mocker.patch("poetry.utils.env.EnvManager.get", return_value=MockEnv()) dependency = DirectoryDependency( "demo", Path(__file__).parent.parent / "fixtures" / "git" / "github.com" / "demo" / "demo", extras=["foo"], ) package = provider.search_for_directory(dependency)[0] assert package.name == "demo" assert package.version.text == "0.1.2" required = [r for r in package.requires if not r.is_optional()] optional = [r for r in package.requires if r.is_optional()] assert required == [get_dependency("pendulum", ">=1.4.4")] assert optional == [get_dependency("tomlkit"), get_dependency("cleo")] assert package.extras == { "foo": [get_dependency("cleo")], "bar": [get_dependency("tomlkit")], }
def test_search_for_vcs_retains_develop_flag(provider: Provider, value: bool): dependency = VCSDependency("demo", "git", "https://github.com/demo/demo.git", develop=value) package = provider.search_for_vcs(dependency)[0] assert package.develop == value
def test_search_for_directory_setup_read_setup_with_no_dependencies( provider: Provider): dependency = DirectoryDependency( "demo", Path(__file__).parent.parent / "fixtures" / "git" / "github.com" / "demo" / "no-dependencies", ) package = provider.search_for_directory(dependency)[0] assert package.name == "demo" assert package.version.text == "0.1.2" assert package.requires == [] assert package.extras == {}
def _parse_dependency_specification_url(requirement: str, env: Env | None = None ) -> DependencySpec | None: url_parsed = urllib.parse.urlparse(requirement) if not (url_parsed.scheme and url_parsed.netloc): return None if url_parsed.scheme in ["git+https", "git+ssh"]: return _parse_dependency_specification_git_url(requirement, env) if url_parsed.scheme in ["http", "https"]: package = Provider.get_package_from_url(requirement) return {"name": package.name, "url": cast(str, package.source_url)} return None
def test_search_for_vcs_setup_egg_info(provider: Provider): dependency = VCSDependency("demo", "git", "https://github.com/demo/demo.git") package = provider.search_for_vcs(dependency)[0] assert package.name == "demo" assert package.version.text == "0.1.2" required = [r for r in package.requires if not r.is_optional()] optional = [r for r in package.requires if r.is_optional()] assert required == [get_dependency("pendulum", ">=1.4.4")] assert optional == [get_dependency("tomlkit"), get_dependency("cleo")] assert package.extras == { "foo": [get_dependency("cleo")], "bar": [get_dependency("tomlkit")], }
def test_complete_package_preserves_source_type_with_subdirectories( provider: Provider, root: ProjectPackage) -> None: dependency_one = Factory.create_dependency( "one", { "git": "https://github.com/demo/subdirectories.git", "subdirectory": "one", }, ) dependency_one_copy = Factory.create_dependency( "one", { "git": "https://github.com/demo/subdirectories.git", "subdirectory": "one-copy", }, ) dependency_two = Factory.create_dependency( "two", { "git": "https://github.com/demo/subdirectories.git", "subdirectory": "two" }, ) root.add_dependency( Factory.create_dependency( "one", { "git": "https://github.com/demo/subdirectories.git", "subdirectory": "one", }, )) root.add_dependency(dependency_one_copy) root.add_dependency(dependency_two) complete_package = provider.complete_package( DependencyPackage(root.to_dependency(), root)) requires = complete_package.package.all_requires assert len(requires) == 3 assert {r.to_pep_508() for r in requires} == { dependency_one.to_pep_508(), dependency_one_copy.to_pep_508(), dependency_two.to_pep_508(), }
def test_complete_package_preserves_source_type(provider: Provider, root: ProjectPackage) -> None: fixtures = Path(__file__).parent.parent / "fixtures" project_dir = fixtures.joinpath("with_conditional_path_deps") for folder in ["demo_one", "demo_two"]: path = (project_dir / folder).as_posix() root.add_dependency(Factory.create_dependency("demo", {"path": path})) complete_package = provider.complete_package( DependencyPackage(root.to_dependency(), root)) requires = complete_package.package.all_requires assert len(requires) == 2 assert {requires[0].source_url, requires[1].source_url} == { project_dir.joinpath("demo_one").as_posix(), project_dir.joinpath("demo_two").as_posix(), }
def find_latest_package(self, package): from poetry.io import NullIO from poetry.puzzle.provider import Provider from poetry.version.version_selector import VersionSelector # find the latest version allowed in this pool if package.source_type == "git": for dep in self.poetry.package.requires: if dep.name == package.name and dep.is_vcs(): return Provider( self.poetry.package, self.poetry.pool, NullIO() ).search_for_vcs(dep)[0] name = package.name selector = VersionSelector(self.poetry.pool) return selector.find_best_candidate(name, ">={}".format(package.pretty_version))
def test_search_for_vcs_read_setup_with_extras(provider: Provider, mocker: MockerFixture): mocker.patch("poetry.utils.env.EnvManager.get", return_value=MockEnv()) dependency = VCSDependency("demo", "git", "https://github.com/demo/demo.git", extras=["foo"]) package = provider.search_for_vcs(dependency)[0] assert package.name == "demo" assert package.version.text == "0.1.2" required = [r for r in package.requires if not r.is_optional()] optional = [r for r in package.requires if r.is_optional()] assert required == [get_dependency("pendulum", ">=1.4.4")] assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
def __init__( self, package: ProjectPackage, pool: Pool, installed: Repository, locked: Repository, io: IO, provider: Provider | None = None, ) -> None: self._package = package self._pool = pool self._installed = installed self._locked = locked self._io = io if provider is None: provider = Provider(self._package, self._pool, self._io) self._provider = provider self._overrides: list[dict[DependencyPackage, dict[str, Dependency]]] = []
def __init__( self, package: "ProjectPackage", pool: "Pool", installed: "Repository", locked: "Repository", io: "IO", provider: Optional[Provider] = None, ): self._package = package self._pool = pool self._installed = installed self._locked = locked self._io = io if provider is None: provider = Provider(self._package, self._pool, self._io) self._provider = provider self._overrides: List[Dict] = []
def test_search_for_directory_setup_egg_info_with_extras(provider: Provider): dependency = DirectoryDependency( "demo", Path(__file__).parent.parent / "fixtures" / "git" / "github.com" / "demo" / "demo", extras=["foo"], ) package = provider.search_for_direct_origin_dependency(dependency) assert package.name == "demo" assert package.version.text == "0.1.2" required = [r for r in package.requires if not r.is_optional()] optional = [r for r in package.requires if r.is_optional()] assert required == [get_dependency("pendulum", ">=1.4.4")] assert optional == [get_dependency("tomlkit"), get_dependency("cleo")] assert package.extras == { "foo": [get_dependency("cleo")], "bar": [get_dependency("tomlkit")], }
def _parse_requirements(self, requirements: List[str]) -> List[Dict[str, str]]: from poetry.puzzle.provider import Provider result = [] try: cwd = self.poetry.file.parent except (PyProjectException, RuntimeError): cwd = Path.cwd() for requirement in requirements: requirement = requirement.strip() extras = [] extras_m = re.search(r"\[([\w\d,-_ ]+)\]$", requirement) if extras_m: extras = [e.strip() for e in extras_m.group(1).split(",")] requirement, _ = requirement.split("[") url_parsed = urllib.parse.urlparse(requirement) if url_parsed.scheme and url_parsed.netloc: # Url if url_parsed.scheme in ["git+https", "git+ssh"]: from poetry.core.vcs.git import Git from poetry.core.vcs.git import ParsedUrl parsed = ParsedUrl.parse(requirement) url = Git.normalize_url(requirement) pair = dict([("name", parsed.name), ("git", url.url)]) if parsed.rev: pair["rev"] = url.revision if extras: pair["extras"] = extras package = Provider.get_package_from_vcs( "git", url.url, rev=pair.get("rev") ) pair["name"] = package.name result.append(pair) continue elif url_parsed.scheme in ["http", "https"]: package = Provider.get_package_from_url(requirement) pair = dict([("name", package.name), ("url", package.source_url)]) if extras: pair["extras"] = extras result.append(pair) continue elif (os.path.sep in requirement or "/" in requirement) and cwd.joinpath( requirement ).exists(): path = cwd.joinpath(requirement) if path.is_file(): package = Provider.get_package_from_file(path.resolve()) else: package = Provider.get_package_from_directory(path) result.append( dict( [ ("name", package.name), ("path", path.relative_to(cwd).as_posix()), ] + ([("extras", extras)] if extras else []) ) ) continue pair = re.sub( "^([^@=: ]+)(?:@|==|(?<![<>~!])=|:| )(.*)$", "\\1 \\2", requirement ) pair = pair.strip() require = dict() if " " in pair: name, version = pair.split(" ", 2) extras_m = re.search(r"\[([\w\d,-_]+)\]$", name) if extras_m: extras = [e.strip() for e in extras_m.group(1).split(",")] name, _ = name.split("[") require["name"] = name if version != "latest": require["version"] = version else: m = re.match( r"^([^><=!: ]+)((?:>=|<=|>|<|!=|~=|~|\^).*)$", requirement.strip() ) if m: name, constraint = m.group(1), m.group(2) extras_m = re.search(r"\[([\w\d,-_]+)\]$", name) if extras_m: extras = [e.strip() for e in extras_m.group(1).split(",")] name, _ = name.split("[") require["name"] = name require["version"] = constraint else: extras_m = re.search(r"\[([\w\d,-_]+)\]$", pair) if extras_m: extras = [e.strip() for e in extras_m.group(1).split(",")] pair, _ = pair.split("[") require["name"] = pair if extras: require["extras"] = extras result.append(require) return result
def provider(root: ProjectPackage, pool: Pool) -> Provider: return Provider(root, pool, NullIO())
def _parse_requirements( self, requirements): # type: (List[str]) -> List[Dict[str, str]] from poetry.puzzle.provider import Provider result = [] try: cwd = self.poetry.file.parent except RuntimeError: cwd = Path.cwd() for requirement in requirements: requirement = requirement.strip() extras = [] extras_m = re.search(r"\[([\w\d,-_]+)\]$", requirement) if extras_m: extras = [e.strip() for e in extras_m.group(1).split(",")] requirement, _ = requirement.split("[") if requirement.startswith(("git+https://", "git+ssh://")): url = requirement.lstrip("git+") rev = None if "@" in url: url, rev = url.split("@") pair = OrderedDict([("name", url.split("/")[-1].rstrip(".git")), ("git", url)]) if rev: pair["rev"] = rev if extras: pair["extras"] = extras package = Provider.get_package_from_vcs( "git", url, reference=pair.get("rev")) pair["name"] = package.name result.append(pair) continue elif (os.path.sep in requirement or "/" in requirement) and cwd.joinpath(requirement).exists(): path = cwd.joinpath(requirement) if path.is_file(): package = Provider.get_package_from_file(path.resolve()) else: package = Provider.get_package_from_directory(path) result.append( OrderedDict([ ("name", package.name), ("path", path.relative_to(cwd).as_posix()), ] + ([("extras", extras)] if extras else []))) continue pair = re.sub("^([^@=: ]+)(?:@|==|(?<![<>~!])=|:| )(.*)$", "\\1 \\2", requirement) pair = pair.strip() require = OrderedDict() if " " in pair: name, version = pair.split(" ", 2) require["name"] = name if version != "latest": require["version"] = version else: m = re.match("^([^><=!: ]+)((?:>=|<=|>|<|!=|~=|~|\^).*)$", requirement.strip()) if m: name, constraint = m.group(1), m.group(2) extras_m = re.search(r"\[([\w\d,-_]+)\]$", name) if extras_m: extras = [ e.strip() for e in extras_m.group(1).split(",") ] name, _ = name.split("[") require["name"] = name require["version"] = constraint else: extras_m = re.search(r"\[([\w\d,-_]+)\]$", pair) if extras_m: extras = [ e.strip() for e in extras_m.group(1).split(",") ] pair, _ = pair.split("[") require["name"] = pair if extras: require["extras"] = extras result.append(require) return result
def provider(root, pool): return Provider(root, pool, NullIO())