def plugin_package(plugin_package_requires_dist: list[str]) -> Package: package = Package("poetry-plugin", "1.2.3") for requirement in plugin_package_requires_dist: package.add_dependency(Dependency.create_from_pep_508(requirement)) return package
def test_dependency_from_pep_508_with_python_full_version_pep440_compatible_release_tilde(): name = 'pathlib2 ; python_version ~= "3.4" or python_version < "3"' dep = Dependency.create_from_pep_508(name) assert dep.name == "pathlib2" assert str(dep.constraint) == "*" assert dep.python_versions == "~=3.4 || <3"
def test_dependency_platform_in(): name = "requests (==2.18.0); sys_platform in 'win32 darwin'" dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" assert str(dep.marker) == 'sys_platform in "win32 darwin"'
def dependencies(self) -> list[Dependency]: if self._dependencies is None: # avoid circular dependency when loading DirectoryDependency from poetry.core.packages.dependency import Dependency from poetry.core.packages.directory_dependency import DirectoryDependency from poetry.core.packages.file_dependency import FileDependency self._dependencies = [] for requirement in self.requires: dependency = None try: dependency = Dependency.create_from_pep_508(requirement) except ValueError: # PEP 517 requires can be path if not PEP 508 path = Path(requirement) # compatibility Python < 3.8 # https://docs.python.org/3/library/pathlib.html#methods with suppress(OSError): if path.is_file(): dependency = FileDependency(name=canonicalize_name( path.name), path=path) elif path.is_dir(): dependency = DirectoryDependency( name=canonicalize_name(path.name), path=path) if dependency is None: # skip since we could not determine requirement continue self._dependencies.append(dependency) return self._dependencies
def test_dependency_from_pep_508_with_url(): name = "django-utils @ https://example.com/django-utils-1.0.0.tar.gz" dep = Dependency.create_from_pep_508(name) assert "django-utils" == dep.name assert dep.is_url() assert "https://example.com/django-utils-1.0.0.tar.gz" == dep.url
def test_dependency_from_pep_508_with_extras(): name = 'requests==2.18.0; extra == "foo" or extra == "bar"' dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" assert dep.in_extras == ["foo", "bar"] assert str(dep.marker) == 'extra == "foo" or extra == "bar"'
def test_dependency_from_pep_508_with_python_full_version_pep440_compatible_release_astrix( ) -> None: name = 'pathlib2 ; python_version == "3.4.*" or python_version < "3"' dep = Dependency.create_from_pep_508(name) assert dep.name == "pathlib2" assert str(dep.constraint) == "*" assert dep.python_versions == "==3.4.* || <3"
def test_dependency_python_version_in(): name = "requests (==2.18.0); python_version in '3.3 3.4 3.5'" dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" assert dep.python_versions == "3.3.* || 3.4.* || 3.5.*" assert str(dep.marker) == 'python_version in "3.3 3.4 3.5"'
def test_dependency_with_extra(): name = "requests[security] (==2.18.0)" dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" assert len(dep.extras) == 1 assert "security" in dep.extras
def test_dependency_from_pep_508_with_platform(): name = 'requests (==2.18.0); sys_platform == "win32" or sys_platform == "darwin"' dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" assert dep.extras == frozenset() assert dep.python_versions == "*" assert str(dep.marker) == 'sys_platform == "win32" or sys_platform == "darwin"'
def test_dependency_from_pep_508_with_wheel_url(): name = ( "example_wheel @ https://example.com/example_wheel-14.0.2-py2.py3-none-any.whl" ) dep = Dependency.create_from_pep_508(name) assert "example-wheel" == dep.name assert str(dep.constraint) == "14.0.2"
def test_to_pep_508_in_extras_parsed() -> None: dependency = Dependency.create_from_pep_508( 'foo[baz,bar] (>=1.23,<2.0) ; extra == "baz"') result = dependency.to_pep_508() assert result == 'foo[bar,baz] (>=1.23,<2.0); extra == "baz"' result = dependency.to_pep_508(with_extras=False) assert result == "foo[bar,baz] (>=1.23,<2.0)"
def test_dependency_from_pep_508_with_single_python_version(): name = 'requests (==2.18.0); python_version == "2.7"' dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" assert dep.extras == frozenset() assert dep.python_versions == "~2.7" assert str(dep.marker) == 'python_version == "2.7"'
def test_dependency_from_pep_508_with_url() -> None: name = "django-utils @ https://example.com/django-utils-1.0.0.tar.gz" dep = Dependency.create_from_pep_508(name) assert dep.name == "django-utils" assert dep.is_url() dep = cast(URLDependency, dep) assert dep.url == "https://example.com/django-utils-1.0.0.tar.gz"
def test_dependency_from_pep_508_with_git_url(): name = "django-utils @ git+ssh://[email protected]/[email protected]" dep = Dependency.create_from_pep_508(name) assert "django-utils" == dep.name assert dep.is_vcs() assert "git" == dep.vcs assert "ssh://[email protected]/corp-utils.git" == dep.source assert "1.2" == dep.reference
def _test_directory_dependency_pep_508(name, path, pep_508_input, pep_508_output=None): dep = Dependency.create_from_pep_508(pep_508_input, relative_to=Path(__file__).parent) assert dep.is_directory() assert dep.name == name assert dep.path == path assert dep.to_pep_508() == pep_508_output or pep_508_input
def test_dependency_from_pep_508_with_git_url() -> None: name = "django-utils @ git+ssh://[email protected]/[email protected]" dep = Dependency.create_from_pep_508(name) assert dep.name == "django-utils" assert dep.is_vcs() dep = cast(VCSDependency, dep) assert dep.vcs == "git" assert dep.source == "ssh://[email protected]/corp-utils.git" assert dep.reference == "1.2"
def test_dependency_from_pep_508_with_not_in_op_marker(): name = ("jinja2 (>=2.7,<2.8)" '; python_version not in "3.0,3.1,3.2" and extra == "export"') dep = Dependency.create_from_pep_508(name) assert dep.name == "jinja2" assert str(dep.constraint) == ">=2.7,<2.8" assert dep.in_extras == ["export"] assert dep.python_versions == "!=3.0.*, !=3.1.*, !=3.2.*" assert (str(dep.marker) == 'python_version not in "3.0,3.1,3.2" and extra == "export"')
def _test_directory_dependency_pep_508( name: str, path: Path, pep_508_input: str, pep_508_output: str | None = None) -> None: dep = Dependency.create_from_pep_508(pep_508_input, relative_to=Path(__file__).parent) assert dep.is_directory() dep = cast(DirectoryDependency, dep) assert dep.name == name assert dep.path == path assert dep.to_pep_508() == pep_508_output or pep_508_input
def test_dependency_from_pep_508_with_git_url_and_comment_and_extra(): name = ( "poetry @ git+https://github.com/python-poetry/poetry.git@b;ar;#egg=poetry" ' ; extra == "foo;"') dep = Dependency.create_from_pep_508(name) assert "poetry" == dep.name assert dep.is_vcs() assert "git" == dep.vcs assert "https://github.com/python-poetry/poetry.git" == dep.source assert "b;ar;" == dep.reference assert dep.in_extras == ["foo;"]
def test_dependency_from_pep_508_with_python_version_union_of_multi(): name = ("requests (==2.18.0); " '(python_version >= "2.7" and python_version < "2.8") ' 'or (python_version >= "3.4" and python_version < "3.5")') dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" assert dep.extras == frozenset() assert dep.python_versions == ">=2.7 <2.8 || >=3.4 <3.5" assert str(dep.marker) == ( 'python_version >= "2.7" and python_version < "2.8" ' 'or python_version >= "3.4" and python_version < "3.5"')
def test_dependency_from_pep_508_with_git_url_and_comment_and_extra() -> None: name = ( "poetry @ git+https://github.com/python-poetry/poetry.git@b;ar;#egg=poetry" ' ; extra == "foo;"') dep = Dependency.create_from_pep_508(name) assert dep.name == "poetry" assert dep.is_vcs() dep = cast(VCSDependency, dep) assert dep.vcs == "git" assert dep.source == "https://github.com/python-poetry/poetry.git" assert dep.reference == "b;ar;" assert dep.in_extras == ["foo;"]
def test_dependency_from_pep_508_complex(): name = ("requests (==2.18.0); " 'python_version >= "2.7" and python_version != "3.2" ' 'and (sys_platform == "win32" or sys_platform == "darwin") ' 'and extra == "foo"') dep = Dependency.create_from_pep_508(name) assert dep.name == "requests" assert str(dep.constraint) == "2.18.0" assert dep.in_extras == ["foo"] assert dep.python_versions == ">=2.7 !=3.2.*" assert str(dep.marker) == ( 'python_version >= "2.7" and python_version != "3.2" ' 'and (sys_platform == "win32" or sys_platform == "darwin") ' 'and extra == "foo"')
def test_dependency_from_pep_508_should_not_produce_empty_constraints_for_correct_markers(): name = 'pytest-mypy; python_implementation != "PyPy" and python_version <= "3.10" and python_version > "3"' dep = Dependency.create_from_pep_508(name) assert dep.name == "pytest-mypy" assert str(dep.constraint) == "*" assert dep.python_versions == "<=3.10 >3" assert dep.python_constraint.allows(Version.parse("3.6")) assert dep.python_constraint.allows(Version.parse("3.10")) assert not dep.python_constraint.allows(Version.parse("3")) assert dep.python_constraint.allows(Version.parse("3.0.1")) assert ( str(dep.marker) == 'platform_python_implementation != "PyPy" and python_version <= "3.10" and python_version > "3"' )
def _test_file_dependency_pep_508(mocker, name, path, pep_508_input, pep_508_output=None): mocker.patch.object(Path, "exists").return_value = True mocker.patch.object(Path, "is_file").return_value = True dep = Dependency.create_from_pep_508(pep_508_input, relative_to=Path(__file__).parent) assert dep.is_file() assert dep.name == name assert dep.path == path assert dep.to_pep_508() == pep_508_output or pep_508_input
def test_dependency_from_pep_508_with_git_url_and_subdirectory() -> None: name = ( "django-utils @" " git+ssh://[email protected]/[email protected]#subdirectory=package-dir" ) dep = Dependency.create_from_pep_508(name) assert dep.name == "django-utils" assert dep.is_vcs() dep = cast(VCSDependency, dep) assert dep.vcs == "git" assert dep.source == "ssh://[email protected]/corp-utils.git" assert dep.reference == "1.2" assert dep.directory == "package-dir"
def pep508_to_dependency_specification( requirement: str) -> DependencySpec | None: if " ; " not in requirement and re.search(r"@[\^~!=<>\d]", requirement): # this is of the form package@<semver>, do not attempt to parse it return None with contextlib.suppress(ValueError): dependency = Dependency.create_from_pep_508(requirement) specification: DependencySpec = {} specification = dependency_to_specification(dependency, specification) if specification: specification["name"] = dependency.name return specification return None
def load(cls, env: Env, with_dependencies: bool = False) -> "InstalledRepository": """ Load installed packages. """ from poetry.core.packages.dependency import Dependency repo = cls() seen = set() for entry in reversed(env.sys_path): for distribution in sorted( metadata.distributions(path=[entry]), key=lambda d: str(d._path), ): name = canonicalize_name(distribution.metadata["name"]) if name in seen: continue path = Path(str(distribution._path)) try: path.relative_to(_VENDORS) except ValueError: pass else: continue package = cls.create_package_from_distribution( distribution, env) if with_dependencies: for require in distribution.metadata.get_all( "requires-dist", []): dep = Dependency.create_from_pep_508(require) package.add_dependency(dep) seen.add(package.name) repo.add_package(package) return repo
def _test_file_dependency_pep_508( mocker: MockerFixture, name: str, path: Path, pep_508_input: str, pep_508_output: str | None = None, marker: BaseMarker | None = None, ) -> None: mocker.patch.object(Path, "exists").return_value = True mocker.patch.object(Path, "is_file").return_value = True dep = Dependency.create_from_pep_508(pep_508_input, relative_to=Path(__file__).parent) if marker: dep.marker = marker assert dep.is_file() dep = cast(FileDependency, dep) assert dep.name == name assert dep.path == path assert dep.to_pep_508() == pep_508_output or pep_508_input
def locked_repository( self, with_dev_reqs: bool = False) -> poetry.repositories.Repository: """ Searches and returns a repository of locked packages. """ from poetry.factory import Factory if not self.is_locked(): return poetry.repositories.Repository() lock_data = self.lock_data packages = poetry.repositories.Repository() if with_dev_reqs: locked_packages = lock_data["package"] else: locked_packages = [ p for p in lock_data["package"] if p["category"] == "main" ] if not locked_packages: return packages for info in locked_packages: source = info.get("source", {}) source_type = source.get("type") url = source.get("url") if source_type in ["directory", "file"]: url = self._lock.path.parent.joinpath(url).resolve().as_posix() package = Package( info["name"], info["version"], info["version"], source_type=source_type, source_url=url, source_reference=source.get("reference"), source_resolved_reference=source.get("resolved_reference"), ) package.description = info.get("description", "") package.category = info.get("category", "main") package.groups = info.get("groups", ["default"]) package.optional = info["optional"] if "hashes" in lock_data["metadata"]: # Old lock so we create dummy files from the hashes package.files = [{ "name": h, "hash": h } for h in lock_data["metadata"]["hashes"][info["name"]]] else: package.files = lock_data["metadata"]["files"][info["name"]] package.python_versions = info["python-versions"] extras = info.get("extras", {}) if extras: for name, deps in extras.items(): package.extras[name] = [] for dep in deps: try: dependency = Dependency.create_from_pep_508(dep) except InvalidRequirement: # handle lock files with invalid PEP 508 m = re.match( r"^(.+?)(?:\[(.+?)])?(?:\s+\((.+)\))?$", dep) dep_name = m.group(1) extras = m.group(2) or "" constraint = m.group(3) or "*" dependency = Dependency(dep_name, constraint, extras=extras.split(",")) package.extras[name].append(dependency) if "marker" in info: package.marker = parse_marker(info["marker"]) else: # Compatibility for old locks if "requirements" in info: dep = Dependency("foo", "0.0.0") for name, value in info["requirements"].items(): if name == "python": dep.python_versions = value elif name == "platform": dep.platform = value split_dep = dep.to_pep_508(False).split(";") if len(split_dep) > 1: package.marker = parse_marker(split_dep[1].strip()) for dep_name, constraint in info.get("dependencies", {}).items(): root_dir = self._lock.path.parent if package.source_type == "directory": # root dir should be the source of the package relative to the lock path root_dir = Path(package.source_url) if isinstance(constraint, list): for c in constraint: package.add_dependency( Factory.create_dependency(dep_name, c, root_dir=root_dir)) continue package.add_dependency( Factory.create_dependency(dep_name, constraint, root_dir=root_dir)) if "develop" in info: package.develop = info["develop"] packages.add_package(package) return packages