def test_package_add_dependency_vcs_category_default_main(f): package = Package("foo", "0.1.0") dependency = package.add_dependency( f.create_dependency( "poetry", {"git": "https://github.com/python-poetry/poetry.git"})) assert dependency.category == "main"
def test_accepts_fails_with_python_versions_mismatch(): dependency = Dependency("A", "^1.0") dependency.python_versions = "^3.6" package = Package("B", "1.4") package.python_versions = "~3.5" assert not dependency.accepts(package)
def test_accepts_python_versions(): dependency = Dependency("A", "^1.0") dependency.python_versions = "^3.6" package = Package("A", "1.4") package.python_versions = "~3.6" assert dependency.accepts(package)
def search(self, query: str) -> List[Package]: results = [] search = {"q": query} response = requests.session().get(self._base_url + "search", params=search) content = parse(response.content, namespaceHTMLElements=False) for result in content.findall(".//*[@class='package-snippet']"): name = result.find("h3/*[@class='package-snippet__name']").text version = result.find( "h3/*[@class='package-snippet__version']").text if not name or not version: continue description = result.find( "p[@class='package-snippet__description']").text if not description: description = "" try: result = Package(name, version, description) result.description = to_str(description.strip()) results.append(result) except ParseVersionError: self._log( 'Unable to parse version "{}" for the {} package, skipping' .format(version, name), level="debug", ) return results
def install_git(self, package): from poetry.core.packages import Package from poetry.core.vcs import Git src_dir = self._env.path / "src" / package.name if src_dir.exists(): safe_rmtree(str(src_dir)) src_dir.parent.mkdir(exist_ok=True) git = Git() git.clone(package.source_url, src_dir) reference = package.source_resolved_reference if not reference: reference = package.source_reference git.checkout(reference, src_dir) # Now we just need to install from the source directory pkg = Package(package.name, package.version) pkg._source_type = "directory" pkg._source_url = str(src_dir) pkg.develop = package.develop self.install_directory(pkg)
def test_package_equality_source_reference(): a1 = Package( "a", "0.1.0", source_type="git", source_url="https://foo.bar", source_reference="c01b317af582501c5ba07b23d5bef3fbada2d4ef", ) a2 = Package( a1.name, a1.version, source_type="git", source_url="https://foo.bar", source_reference="a444731cd243cb5cd04e4d5fb81f86e1fecf8a00", ) a3 = Package( a1.name, a1.version, source_type="git", source_url="https://foo.bar", source_reference="c01b317af582501c5ba07b23d5bef3fbada2d4ef", ) a4 = Package(a1.name, a1.version, source_type="git") assert a1 == a1 assert a1 == a3 assert a1 != a2 assert a2 != a3 assert a1 != a4 assert a2 != a4
def test_to_dependency_with_features(): package = Package("foo", "1.2.3", features=["baz", "bar"]) dep = package.to_dependency() assert "foo" == dep.name assert package.version == dep.constraint assert frozenset({"bar", "baz"}) == dep.features
def test_to_dependency_with_python_constraint(): package = Package("foo", "1.2.3") package.python_versions = ">=3.6" dep = package.to_dependency() assert "foo" == dep.name assert package.version == dep.constraint assert ">=3.6" == dep.python_versions
def test_package_add_dependency_vcs_category(category): package = Package("foo", "0.1.0") dependency = package.add_dependency( "poetry", constraint={"git": "https://github.com/python-poetry/poetry.git"}, category=category, ) assert dependency.category == category
def add_to_repo(repository, name, version, deps=None, python=None): package = Package(name, version) if python: package.python_versions = python if deps: for dep_name, dep_constraint in deps.items(): package.add_dependency(dep_name, dep_constraint) repository.add_package(package)
def get_package(locked: src_parser.LockedDependency) -> Package: if locked.source is not None: return Package( locked.name, source_type="url", source_url=locked.source.url, version="0.0.0", ) else: return Package(locked.name, version=locked.version)
def set_package_vcs_properties_from_path(cls, src: Path, package: Package) -> None: from poetry.core.vcs.git import Git git = Git() revision = git.rev_parse("HEAD", src).strip() url = git.remote_url(src) package._source_type = "git" package._source_url = url package._source_reference = revision
def test_package_equality_source_type(): a1 = Package("a", "0.1.0", source_type="file") a2 = Package(a1.name, a1.version, source_type="directory") a3 = Package(a1.name, a1.version, source_type=a1.source_type) a4 = Package(a1.name, a1.version) assert a1 == a1 assert a1 == a3 assert a1 != a2 assert a2 != a3 assert a1 != a4 assert a2 != a4
def test_package_url_category_optional(category, optional): package = Package("foo", "0.1.0") dependency = package.add_dependency( "poetry", constraint={ "url": "https://github.com/python-poetry/poetry/releases/download/1.0.5/poetry-1.0.5-linux.tar.gz", "optional": optional, }, category=category, ) assert dependency.category == category assert dependency.is_optional() == optional
def test_package_equality_source_url(): a1 = Package("a", "0.1.0", source_type="file", source_url="/some/path") a2 = Package( a1.name, a1.version, source_type=a1.source_type, source_url="/some/other/path" ) a3 = Package( a1.name, a1.version, source_type=a1.source_type, source_url=a1.source_url ) a4 = Package(a1.name, a1.version, source_type=a1.source_type) assert a1 == a1 assert a1 == a3 assert a1 != a2 assert a2 != a3 assert a1 != a4 assert a2 != a4
def package( self, name, version, extras=None): # type: (str, str, Optional[List[str]]) -> Package """ Retrieve the release information. This is a heavy task which takes time. We have to download a package to get the dependencies. We also need to download every file matching this release to get the various hashes. Note that this will be cached so the subsequent operations should be much faster. """ try: index = self._packages.index(Package(name, version, version)) return self._packages[index] except ValueError: package = super(LegacyRepository, self).package(name, version, extras) package._source_type = "legacy" package._source_url = self._url package._source_reference = self.name return package
def test_to_dependency_for_url(): package = Package( "foo", "1.2.3", source_type="url", source_url="https://example.com/path.tar.gz", features=["baz", "bar"], ) dep = package.to_dependency() assert "foo" == dep.name assert package.version == dep.constraint assert frozenset({"bar", "baz"}) == dep.features assert dep.is_url() assert "https://example.com/path.tar.gz" == dep.url assert "url" == dep.source_type assert "https://example.com/path.tar.gz" == dep.source_url
def to_package( self, name=None, extras=None, root_dir=None ): # type: (Optional[str], Optional[List[str]], Optional[Path]) -> Package """ Create a new `poetry.core.packages.package.Package` instance using metadata from this instance. :param name: Name to use for the package, if not specified name from this instance is used. :param extras: Extras to activate for this package. :param root_dir: Optional root directory to use for the package. If set, dependency strings will be parsed relative to this directory. """ name = name or self.name if not self.version: # The version could not be determined, so we raise an error since it is mandatory. raise RuntimeError( "Unable to retrieve the package version for {}".format(name) ) package = Package(name=name, version=self.version) package.description = self.summary package.root_dir = root_dir package.python_versions = self.requires_python or "*" package.files = self.files for req in self.requires_dist or []: try: # Attempt to parse the PEP-508 requirement string dependency = dependency_from_pep_508(req, relative_to=root_dir) except InvalidMarker: # Invalid marker, We strip the markers hoping for the best req = req.split(";")[0] dependency = dependency_from_pep_508(req, relative_to=root_dir) except ValueError: # Likely unable to parse constraint so we skip it self._log( "Invalid constraint ({}) found in {}-{} dependencies, " "skipping".format(req, package.name, package.version), level="warning", ) continue if dependency.in_extras: # this dependency is required by an extra package for extra in dependency.in_extras: if extra not in package.extras: # this is the first time we encounter this extra for this package package.extras[extra] = [] # Activate extra dependencies if specified if extras and extra in extras: dependency.activate() package.extras[extra].append(dependency) if not dependency.is_optional() or dependency.is_activated(): # we skip add only if the dependency is option and was not activated as part of an extra package.requires.append(dependency) return package
def test_to_dependency_for_directory(): path = Path(__file__).parent.parent.joinpath("fixtures/simple_project") package = Package( "foo", "1.2.3", source_type="directory", source_url=path.as_posix(), features=["baz", "bar"], ) dep = package.to_dependency() assert "foo" == dep.name assert package.version == dep.constraint assert frozenset({"bar", "baz"}) == dep.features assert dep.is_directory() assert path == dep.path assert "directory" == dep.source_type assert path.as_posix() == dep.source_url
def test_package_authors(): package = Package("foo", "0.1.0") package.authors.append("Sébastien Eustace <*****@*****.**>") assert package.author_name == "Sébastien Eustace" assert package.author_email == "*****@*****.**" package.authors.insert(0, "John Doe") assert package.author_name == "John Doe" assert package.author_email is None
def test_to_dependency_for_file(): path = Path(__file__).parent.parent.joinpath( "fixtures/distributions/demo-0.1.0.tar.gz") package = Package( "foo", "1.2.3", source_type="file", source_url=path.as_posix(), features=["baz", "bar"], ) dep = package.to_dependency() assert "foo" == dep.name assert package.version == dep.constraint assert frozenset({"bar", "baz"}) == dep.features assert dep.is_file() assert path == dep.path assert "file" == dep.source_type assert path.as_posix() == dep.source_url
def test_package_authors_invalid(): package = Package("foo", "0.1.0") package.authors.insert(0, "<John Doe") with pytest.raises(ValueError) as e: package.author_name assert ( str(e.value) == "Invalid author string. Must be in the format: John Smith <*****@*****.**>" )
def _install_package(poetry, env, io): "Install package." with temporary_directory() as directory: wheel_name = WheelBuilder.make_in(poetry, directory=Path(directory)) wheel = Path(directory).joinpath(wheel_name) package = Package( poetry.package.name, poetry.package.version, source_type="file", source_url=wheel, ) _make_installer(poetry, env, io).executor.execute([Install(package)])
def load(cls, env): # type: (Env) -> InstalledRepository """ Load installed packages. """ 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 = distribution.metadata["name"] path = Path(str(distribution._path)) version = distribution.metadata["version"] package = Package(name, version, version) package.description = distribution.metadata.get("summary", "") if package.name in seen: continue try: path.relative_to(_VENDORS) except ValueError: pass else: continue seen.add(package.name) repo.add_package(package) is_standard_package = env.is_path_relative_to_lib(path) if is_standard_package: if path.name.endswith(".dist-info"): paths = cls.get_package_paths(env=env, name=package.pretty_name) if paths: for src in paths: if cls.is_vcs_package(src, env): cls.set_package_vcs_properties(package, env) break else: # TODO: handle multiple source directories? package._source_type = "directory" package._source_url = paths.pop().as_posix() continue if cls.is_vcs_package(path, env): cls.set_package_vcs_properties(package, env) else: # If not, it's a path dependency package._source_type = "directory" package._source_url = str(path.parent) return repo
def test_package_resolved_reference_is_relevant_for_equality_only_if_present_for_both_packages( ): a1 = Package( "a", "0.1.0", source_type="git", source_url="https://foo.bar", source_reference="master", source_resolved_reference="c01b317af582501c5ba07b23d5bef3fbada2d4ef", ) a2 = Package( a1.name, a1.version, source_type="git", source_url="https://foo.bar", source_reference="master", source_resolved_reference="a444731cd243cb5cd04e4d5fb81f86e1fecf8a00", ) a3 = Package( a1.name, a1.version, source_type="git", source_url="https://foo.bar", source_reference="master", source_resolved_reference="c01b317af582501c5ba07b23d5bef3fbada2d4ef", ) a4 = Package( a1.name, a1.version, source_type="git", source_url="https://foo.bar", source_reference="master", ) assert a1 == a1 assert a1 == a3 assert a1 != a2 assert a2 != a3 assert a1 == a4 assert a2 == a4
def find_packages(self, name, constraint=None, extras=None, allow_prereleases=False): packages = [] if constraint is None: constraint = "*" if not isinstance(constraint, VersionConstraint): constraint = parse_constraint(constraint) if isinstance(constraint, VersionRange): if (constraint.max is not None and constraint.max.is_prerelease() or constraint.min is not None and constraint.min.is_prerelease()): allow_prereleases = True key = name if not constraint.is_any(): key = "{}:{}".format(key, str(constraint)) if self._cache.store("matches").has(key): versions = self._cache.store("matches").get(key) else: page = self._get("/{}/".format( canonicalize_name(name).replace(".", "-"))) if page is None: return [] versions = [] for version in page.versions: if version.is_prerelease() and not allow_prereleases: continue if constraint.allows(version): versions.append(version) self._cache.store("matches").put(key, versions, 5) for version in versions: package = Package(name, version) package.source_type = "legacy" package.source_reference = self.name package.source_url = self._url if extras is not None: package.requires_extras = extras packages.append(package) self._log( "{} packages found for {} {}".format(len(packages), name, str(constraint)), level="debug", ) return packages
def test_package_clone(f): # TODO(nic): this test is not future-proof, in that any attributes added # to the Package object and not filled out in this test setup might # cause comparisons to match that otherwise should not. A factory method # to create a Package object with all fields fully randomized would be the # most rigorous test for this, but that's likely overkill. p = Package( "lol_wut", "3.141.5926535", pretty_version="③.⑭.⑮", source_type="git", source_url="http://some.url", source_reference="fe4d2adabf3feb5d32b70ab5c105285fa713b10c", source_resolved_reference="fe4d2adabf3feb5d32b70ab5c105285fa713b10c", features=["abc", "def"], ) p.files = (["file1", "file2", "file3"],) p.homepage = "https://some.other.url" p.repository_url = "http://bug.farm" p.documentation_url = "http://lorem.ipsum/dolor/sit.amet" p2 = p.clone() assert p == p2 assert p.__dict__ == p2.__dict__
def find_packages(self, dependency: Dependency) -> List[Package]: """ Find packages on the remote server. """ constraint = dependency.constraint if constraint is None: constraint = "*" if not isinstance(constraint, VersionConstraint): constraint = parse_constraint(constraint) allow_prereleases = dependency.allows_prereleases() if isinstance(constraint, VersionRange): if (constraint.max is not None and constraint.max.is_prerelease() or constraint.min is not None and constraint.min.is_prerelease()): allow_prereleases = True try: info = self.get_package_info(dependency.name) except PackageNotFound: self._log( "No packages found for {} {}".format(dependency.name, str(constraint)), level="debug", ) return [] packages = [] ignored_pre_release_packages = [] for version, release in info["releases"].items(): if not release: # Bad release self._log( "No release information found for {}-{}, skipping".format( dependency.name, version), level="debug", ) continue try: package = Package(info["info"]["name"], version) except ParseVersionError: self._log( 'Unable to parse version "{}" for the {} package, skipping' .format(version, dependency.name), level="debug", ) continue if package.is_prerelease() and not allow_prereleases: if constraint.is_any(): # we need this when all versions of the package are pre-releases ignored_pre_release_packages.append(package) continue if not constraint or (constraint and constraint.allows(package.version)): packages.append(package) self._log( "{} packages found for {} {}".format(len(packages), dependency.name, str(constraint)), level="debug", ) return packages or ignored_pre_release_packages
def find_packages( self, name, # type: str constraint=None, # type: Union[VersionConstraint, str, None] extras=None, # type: Union[list, None] allow_prereleases=False, # type: bool ): # type: (...) -> List[Package] """ Find packages on the remote server. """ if constraint is None: constraint = "*" if not isinstance(constraint, VersionConstraint): constraint = parse_constraint(constraint) if isinstance(constraint, VersionRange): if (constraint.max is not None and constraint.max.is_prerelease() or constraint.min is not None and constraint.min.is_prerelease()): allow_prereleases = True try: info = self.get_package_info(name) except PackageNotFound: self._log( "No packages found for {} {}".format(name, str(constraint)), level="debug", ) return [] packages = [] for version, release in info["releases"].items(): if not release: # Bad release self._log( "No release information found for {}-{}, skipping".format( name, version), level="debug", ) continue try: package = Package(info["info"]["name"], version) except ParseVersionError: self._log( 'Unable to parse version "{}" for the {} package, skipping' .format(version, name), level="debug", ) continue if package.is_prerelease() and not allow_prereleases: continue if not constraint or (constraint and constraint.allows(package.version)): if extras is not None: package.requires_extras = extras packages.append(package) self._log( "{} packages found for {} {}".format(len(packages), name, str(constraint)), level="debug", ) return packages
def get_package(name, version): return Package(name, version)