Пример #1
0
    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
Пример #2
0
    def dependencies(self):
        if self._dependencies is None:
            # avoid circular dependency when loading DirectoryDependency
            from poetry.core.packages import DirectoryDependency
            from poetry.core.packages import FileDependency
            from poetry.core.packages import dependency_from_pep_508

            self._dependencies = []
            for requirement in self.requires:
                dependency = None
                try:
                    dependency = dependency_from_pep_508(requirement)
                except ValueError:
                    # PEP 517 requires can be path if not PEP 508
                    path = Path(requirement)
                    try:
                        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)
                    except OSError:
                        # compatibility Python < 3.8
                        # https://docs.python.org/3/library/pathlib.html#methods
                        pass

                if dependency is None:
                    # skip since we could not determine requirement
                    continue

                self._dependencies.append(dependency)

        return self._dependencies
Пример #3
0
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_from_pep_508(name)

    assert dep.name == "pathlib2"
    assert str(dep.constraint) == "*"
    assert dep.python_versions == "~=3.4 || <3"
Пример #4
0
def test_to_pep_508_in_extras_parsed():
    dependency = dependency_from_pep_508('foo[bar] (>=1.23,<2.0) ; extra == "baz"')

    result = dependency.to_pep_508()
    assert result == 'foo[bar] (>=1.23,<2.0); extra == "baz"'

    result = dependency.to_pep_508(with_extras=False)
    assert result == "foo[bar] (>=1.23,<2.0)"
Пример #5
0
def test_dependency_from_pep_508_with_platform():
    name = 'requests (==2.18.0); sys_platform == "win32" or sys_platform == "darwin"'
    dep = dependency_from_pep_508(name)

    assert dep.name == "requests"
    assert str(dep.constraint) == "2.18.0"
    assert dep.extras == []
    assert dep.python_versions == "*"
    assert str(dep.marker) == 'sys_platform == "win32" or sys_platform == "darwin"'
def _test_directory_dependency_pep_508(name,
                                       path,
                                       pep_508_input,
                                       pep_508_output=None):
    dep = dependency_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
Пример #7
0
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_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
Пример #8
0
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_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;"]
Пример #9
0
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_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"'
    )
Пример #10
0
    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,
            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_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] = []

                    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