Beispiel #1
0
def test_accepts_fails_with_python_versions_mismatch() -> None:
    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)
Beispiel #2
0
def test_accepts_python_versions() -> None:
    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 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
Beispiel #4
0
def test_to_dependency_with_python_constraint() -> None:
    package = Package("foo", "1.2.3")
    package.python_versions = ">=3.6"
    dep = package.to_dependency()

    assert dep.name == "foo"
    assert dep.constraint == package.version
    assert dep.python_versions == ">=3.6"
Beispiel #5
0
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(
                Factory.create_dependency(dep_name, dep_constraint))

    repository.add_package(package)
Beispiel #6
0
def add_to_repo(
    repository: Repository,
    name: str,
    version: str,
    deps: dict[str, str] | None = None,
    python: str | None = None,
) -> None:
    package = Package(name, version)
    if python:
        package.python_versions = python

    if deps:
        for dep_name, dep_constraint in deps.items():
            package.add_dependency(Factory.create_dependency(dep_name, dep_constraint))

    repository.add_package(package)
Beispiel #7
0
    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
Beispiel #8
0
    def locked_repository(self,
                          with_dev_reqs=False
                          ):  # type: (bool) -> poetry.repositories.Repository
        """
        Searches and returns a repository of locked packages.
        """
        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:
            package = Package(info["name"], info["version"], info["version"])
            package.description = info.get("description", "")
            package.category = info["category"]
            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:
                        m = re.match(r"^(.+?)(?:\s+\((.+)\))?$", dep)
                        dep_name = m.group(1)
                        constraint = m.group(2) or "*"

                        package.extras[name].append(
                            Dependency(dep_name, constraint))

            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():
                if isinstance(constraint, list):
                    for c in constraint:
                        package.add_dependency(dep_name, c)

                    continue

                package.add_dependency(dep_name, constraint)

            if "develop" in info:
                package.develop = info["develop"]

            if "source" in info:
                package.source_type = info["source"].get("type", "")
                package.source_url = info["source"]["url"]
                package.source_reference = info["source"]["reference"]

            packages.add_package(package)

        return packages
Beispiel #9
0
    def to_package(
        self,
        name: Optional[str] = None,
        extras: Optional[List[str]] = None,
        root_dir: Optional[Path] = None,
    ) -> 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,
            source_type=self._source_type,
            source_url=self._source_url,
            source_reference=self._source_reference,
        )
        package.description = self.summary
        package.root_dir = root_dir
        package.python_versions = self.requires_python or "*"
        package.files = self.files

        if root_dir or (self._source_type in {"directory"}
                        and self._source_url):
            # this is a local poetry project, this means we can extract "richer" requirement information
            # eg: development requirements etc.
            poetry_package = self._get_poetry_package(
                path=root_dir or self._source_url)
            if poetry_package:
                package.extras = poetry_package.extras
                package.requires = poetry_package.requires
                return package

        seen_requirements = set()

        for req in self.requires_dist or []:
            try:
                # Attempt to parse the PEP-508 requirement string
                dependency = Dependency.create_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.create_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] = []

                    package.extras[extra].append(dependency)

            req = dependency.to_pep_508(with_extras=True)

            if req not in seen_requirements:
                package.requires.append(dependency)
                seen_requirements.add(req)

        return package
Beispiel #10
0
    def to_package(
        self,
        name: str | None = None,
        extras: list[str] | None = None,
        root_dir: Path | None = None,
    ) -> 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 name:
            raise RuntimeError("Unable to create package with no name")

        if not self.version:
            # The version could not be determined, so we raise an error since it is
            # mandatory.
            raise RuntimeError(
                f"Unable to retrieve the package version for {name}")

        package = Package(
            name=name,
            version=self.version,
            source_type=self._source_type,
            source_url=self._source_url,
            source_reference=self._source_reference,
        )
        if self.summary is not None:
            package.description = self.summary
        package.root_dir = root_dir
        package.python_versions = self.requires_python or "*"
        package.files = self.files

        # If this is a local poetry project, we can extract "richer" requirement
        # information, eg: development requirements etc.
        if root_dir is not None:
            path = root_dir
        elif self._source_type == "directory" and self._source_url is not None:
            path = Path(self._source_url)
        else:
            path = None

        if path is not None:
            poetry_package = self._get_poetry_package(path=path)
            if poetry_package:
                package.extras = poetry_package.extras
                for dependency in poetry_package.requires:
                    package.add_dependency(dependency)

                return package

        seen_requirements = set()

        for req in self.requires_dist or []:
            try:
                # Attempt to parse the PEP-508 requirement string
                dependency = Dependency.create_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.create_from_pep_508(
                    req, relative_to=root_dir)
            except ValueError:
                # Likely unable to parse constraint so we skip it
                logger.debug(
                    f"Invalid constraint ({req}) found in"
                    f" {package.name}-{package.version} dependencies, skipping",
                )
                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] = []

                    package.extras[extra].append(dependency)

            req = dependency.to_pep_508(with_extras=True)

            if req not in seen_requirements:
                package.add_dependency(dependency)
                seen_requirements.add(req)

        return package