Esempio n. 1
0
def test_get_extra_package_names(
    packages: List[Package],
    extras: Dict[str, List[str]],
    extra_names: List[str],
    expected_extra_package_names: List[str],
):
    assert expected_extra_package_names == list(
        get_extra_package_names(packages, extras, extra_names))
Esempio n. 2
0
def test_get_extra_package_names(
    packages: list[Package],
    extras: dict[str, list[str]],
    extra_names: list[str],
    expected_extra_package_names: list[str],
):
    assert (
        list(get_extra_package_names(packages, extras, extra_names))
        == expected_extra_package_names
    )
Esempio n. 3
0
    def _get_extra_packages(self, repo: Repository) -> list[str]:
        """
        Returns all package names required by extras.

        Maybe we just let the solver handle it?
        """
        if self._update:
            extras = {k: [d.name for d in v] for k, v in self._package.extras.items()}
        else:
            extras = self._locker.lock_data.get("extras", {})

        return list(get_extra_package_names(repo.packages, extras, self._extras))
Esempio n. 4
0
    def get_project_dependency_packages(
        self,
        project_requires: list[Dependency],
        project_python_marker: BaseMarker | None = None,
        extras: bool | Sequence[str] | None = None,
    ) -> Iterator[DependencyPackage]:
        # Apply the project python marker to all requirements.
        if project_python_marker is not None:
            marked_requires: list[Dependency] = []
            for require in project_requires:
                require = deepcopy(require)
                require.marker = require.marker.intersect(
                    project_python_marker)
                marked_requires.append(require)
            project_requires = marked_requires

        repository = self.locked_repository()

        # Build a set of all packages required by our selected extras
        extra_package_names: set[str] | None = None

        if extras is not True:
            extra_package_names = set(
                get_extra_package_names(
                    repository.packages,
                    self.lock_data.get("extras", {}),
                    extras or (),
                ))

        # If a package is optional and we haven't opted in to it, do not select
        selected = []
        for dependency in project_requires:
            try:
                package = repository.find_packages(dependency=dependency)[0]
            except IndexError:
                continue

            if extra_package_names is not None and (
                    package.optional
                    and package.name not in extra_package_names):
                # a package is locked as optional, but is not activated via extras
                continue

            selected.append(dependency)

        for package, dependency in self.get_project_dependencies(
                project_requires=selected,
                locked_packages=repository.packages,
        ):
            for extra in dependency.extras:
                package.requires_extras.append(extra)

            yield DependencyPackage(dependency=dependency, package=package)
Esempio n. 5
0
    def get_project_dependency_packages(
        self,
        project_requires: List[Dependency],
        dev: bool = False,
        extras: Optional[Union[bool, Sequence[str]]] = None,
    ) -> Iterator[DependencyPackage]:
        repository = self.locked_repository(with_dev_reqs=dev)

        # Build a set of all packages required by our selected extras
        extra_package_names = (
            None if (isinstance(extras, bool) and extras is True) else ()
        )

        if extra_package_names is not None:
            extra_package_names = set(
                get_extra_package_names(
                    repository.packages,
                    self.lock_data.get("extras", {}),
                    extras or (),
                )
            )

        # If a package is optional and we haven't opted in to it, do not select
        selected = []
        for dependency in project_requires:
            try:
                package = repository.find_packages(dependency=dependency)[0]
            except IndexError:
                continue

            if extra_package_names is not None and (
                package.optional and package.name not in extra_package_names
            ):
                # a package is locked as optional, but is not activated via extras
                continue

            selected.append(dependency)

        for dependency in self.get_project_dependencies(
            project_requires=selected,
            locked_packages=repository.packages,
            with_nested=True,
        ):
            try:
                package = repository.find_packages(dependency=dependency)[0]
            except IndexError:
                continue

            for extra in dependency.extras:
                package.requires_extras.append(extra)

            yield DependencyPackage(dependency=dependency, package=package)
Esempio n. 6
0
def test_get_extra_package_names(packages, extras, extra_names,
                                 expected_extra_package_names):
    assert expected_extra_package_names == list(
        get_extra_package_names(packages, extras, extra_names))
Esempio n. 7
0
    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)
Esempio n. 8
0
    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 = ""
        repository = self._poetry.locker.locked_repository(dev)

        # Build a set of all packages required by our selected extras
        extra_package_names = set(
            get_extra_package_names(
                repository.packages,
                self._poetry.locker.lock_data.get("extras", {}),
                extras or (),
            )
        )

        dependency_lines = set()

        for dependency in self._poetry.locker.get_project_dependencies(
            project_requires=self._poetry.package.all_requires,
            with_nested=True,
            with_dev=dev,
        ):
            try:
                package = repository.find_packages(dependency=dependency)[0]
            except IndexError:
                continue

            # 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

            line = ""

            if package.develop:
                line += "-e "

            requirement = dependency.to_pep_508(with_extras=False)
            is_direct_reference = (
                dependency.is_vcs()
                or dependency.is_url()
                or dependency.is_file()
                or dependency.is_directory()
            )

            if is_direct_reference:
                line = requirement
            else:
                line = "{}=={}".format(package.name, package.version)
                if ";" in requirement:
                    markers = requirement.split(";", 1)[1].strip()
                    if markers:
                        line += "; {}".format(markers)

            if not is_direct_reference 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 ""
                        )
            dependency_lines.add(line)

        content += "\n".join(sorted(dependency_lines))
        content += "\n"

        if indexes:
            # If we have extra indexes, we add them to the beginning of the output
            indexes_header = ""
            for index in sorted(indexes):
                repositories = [
                    r
                    for r in self._poetry.pool.repositories
                    if r.url == index.rstrip("/")
                ]
                if not repositories:
                    continue
                repository = repositories[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)