def test_to_pep_508():
    dependency = VCSDependency("poetry", "git",
                               "https://github.com/python-poetry/poetry.git")

    expected = "poetry @ git+https://github.com/python-poetry/poetry.git@master"

    assert expected == dependency.to_pep_508()
def test_to_pep_508_ssh() -> None:
    dependency = VCSDependency("poetry", "git",
                               "[email protected]:sdispater/poetry.git")

    expected = "poetry @ git+ssh://[email protected]/sdispater/poetry.git"

    assert dependency.to_pep_508() == expected
Exemple #3
0
    def search_for_vcs(self, dependency: VCSDependency) -> list[Package]:
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency in self._deferred_cache:
            return [self._deferred_cache[dependency]]

        package = self.get_package_from_vcs(
            dependency.vcs,
            dependency.source,
            branch=dependency.branch,
            tag=dependency.tag,
            rev=dependency.rev,
            name=dependency.name,
        )
        package.develop = dependency.develop

        dependency._constraint = package.version
        dependency._pretty_constraint = package.version.text

        dependency._source_reference = package.source_reference
        dependency._source_resolved_reference = package.source_resolved_reference

        if hasattr(package, "source_subdirectory") and hasattr(
                dependency, "_source_subdirectory"):
            # this is supported only for poetry-core >= 1.1.0a7
            dependency._source_subdirectory = package.source_subdirectory

        self._deferred_cache[dependency] = package

        return [package]
def test_to_pep_508_ssh():
    dependency = VCSDependency("poetry", "git",
                               "[email protected]:sdispater/poetry.git")

    expected = "poetry @ git+ssh://[email protected]/sdispater/poetry.git@master"

    assert expected == dependency.to_pep_508()
Exemple #5
0
    def search_for_vcs(self, dependency: VCSDependency) -> list[Package]:
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency in self._deferred_cache:
            return [self._deferred_cache[dependency]]

        package = self.get_package_from_vcs(
            dependency.vcs,
            dependency.source,
            branch=dependency.branch,
            tag=dependency.tag,
            rev=dependency.rev,
            source_root=self._source_root
            or (self._env.path.joinpath("src") if self._env else None),
        )

        self.validate_package_for_dependency(dependency=dependency,
                                             package=package)

        package.develop = dependency.develop

        dependency._constraint = package.version
        dependency._pretty_constraint = package.version.text

        dependency._source_reference = package.source_reference
        dependency._source_resolved_reference = package.source_resolved_reference
        dependency._source_subdirectory = package.source_subdirectory

        self._deferred_cache[dependency] = package

        return [package]
def test_to_pep_508() -> None:
    dependency = VCSDependency("poetry", "git",
                               "https://github.com/python-poetry/poetry.git")

    expected = "poetry @ git+https://github.com/python-poetry/poetry.git"

    assert dependency.to_pep_508() == expected
Exemple #7
0
    def search_for_vcs(self, dependency: VCSDependency) -> List[Package]:
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency in self._deferred_cache:
            return [self._deferred_cache[dependency]]

        package = self.get_package_from_vcs(
            dependency.vcs,
            dependency.source,
            branch=dependency.branch,
            tag=dependency.tag,
            rev=dependency.rev,
            name=dependency.name,
        )
        package.develop = dependency.develop

        dependency._constraint = package.version
        dependency._pretty_constraint = package.version.text

        self._deferred_cache[dependency] = package

        return [package]
def test_to_pep_508_with_extras():
    dependency = VCSDependency("poetry", "git",
                               "https://github.com/python-poetry/poetry.git")
    dependency.extras.append("foo")

    expected = "poetry[foo] @ git+https://github.com/python-poetry/poetry.git@master"

    assert expected == dependency.to_pep_508()
def test_to_pep_508_in_extras():
    dependency = VCSDependency("poetry", "git",
                               "https://github.com/python-poetry/poetry.git")
    dependency.in_extras.append("foo")

    expected = 'poetry @ git+https://github.com/python-poetry/poetry.git@master ; extra == "foo"'
    assert expected == dependency.to_pep_508()

    dependency = VCSDependency("poetry", "git",
                               "https://github.com/python-poetry/poetry.git")
    dependency.in_extras.append("foo")
    dependency.extras.append("bar")

    expected = 'poetry[bar] @ git+https://github.com/python-poetry/poetry.git@master ; extra == "foo"'

    assert expected == dependency.to_pep_508()

    dependency = VCSDependency("poetry", "git",
                               "https://github.com/python-poetry/poetry.git",
                               "b;ar;")
    dependency.in_extras.append("foo;")

    expected = 'poetry @ git+https://github.com/python-poetry/poetry.git@b;ar; ; extra == "foo;"'

    assert expected == dependency.to_pep_508()
def test_to_pep_508_in_extras() -> None:
    dependency = VCSDependency("poetry", "git",
                               "https://github.com/python-poetry/poetry.git")
    dependency.in_extras.append("foo")

    expected = (
        'poetry @ git+https://github.com/python-poetry/poetry.git ; extra == "foo"'
    )
    assert dependency.to_pep_508() == expected

    dependency = VCSDependency("poetry",
                               "git",
                               "https://github.com/python-poetry/poetry.git",
                               extras=["bar"])
    dependency.in_extras.append("foo")

    expected = (
        'poetry[bar] @ git+https://github.com/python-poetry/poetry.git ; extra == "foo"'
    )

    assert dependency.to_pep_508() == expected

    dependency = VCSDependency("poetry", "git",
                               "https://github.com/python-poetry/poetry.git",
                               "b;ar;")
    dependency.in_extras.append("foo;")

    expected = (
        "poetry @ git+https://github.com/python-poetry/poetry.git@b;ar; ; extra =="
        ' "foo;"')

    assert dependency.to_pep_508() == expected
def test_to_pep_508_with_extras() -> None:
    dependency = VCSDependency(
        "poetry",
        "git",
        "https://github.com/python-poetry/poetry.git",
        extras=["foo", "bar"],
    )

    expected = "poetry[bar,foo] @ git+https://github.com/python-poetry/poetry.git"

    assert dependency.to_pep_508() == expected
Exemple #12
0
def test_search_for_vcs_retains_develop_flag(provider: Provider, value: bool):
    dependency = VCSDependency("demo",
                               "git",
                               "https://github.com/demo/demo.git",
                               develop=value)
    package = provider.search_for_vcs(dependency)[0]
    assert package.develop == value
Exemple #13
0
def test_category(category):
    dependency = VCSDependency(
        "poetry",
        "git",
        "https://github.com/python-poetry/poetry.git",
        category=category,
    )
    assert category == dependency.category
def test_category(groups: list[str]) -> None:
    dependency = VCSDependency(
        "poetry",
        "git",
        "https://github.com/python-poetry/poetry.git",
        groups=groups,
    )
    assert dependency.groups == frozenset(groups)
def test_vcs_dependencies_are_equal_if_resolved_references_match() -> None:
    dependency1 = VCSDependency(
        "poetry",
        "git",
        "https://github.com/python-poetry/poetry.git",
        branch="develop",
        resolved_rev="123456",
    )
    dependency2 = VCSDependency(
        "poetry",
        "git",
        "https://github.com/python-poetry/poetry.git",
        rev="123",
        resolved_rev="123456",
    )

    assert dependency1 == dependency2
Exemple #16
0
def test_search_for_vcs_read_setup_raises_error_if_no_version(provider, mocker):
    mocker.patch(
        "poetry.inspection.info.PackageInfo._pep517_metadata",
        return_value=PackageInfo(name="demo", version=None),
    )

    dependency = VCSDependency("demo", "git", "https://github.com/demo/no-version.git")

    with pytest.raises(RuntimeError):
        provider.search_for_vcs(dependency)
def test_vcs_dependency_can_have_resolved_reference_specified() -> None:
    dependency = VCSDependency(
        "poetry",
        "git",
        "https://github.com/python-poetry/poetry.git",
        branch="develop",
        resolved_rev="123456",
    )

    assert dependency.branch == "develop"
    assert dependency.source_reference == "develop"
    assert dependency.source_resolved_reference == "123456"
Exemple #18
0
def test_search_for_vcs_setup_egg_info(provider):
    dependency = VCSDependency("demo", "git",
                               "https://github.com/demo/demo.git")

    package = provider.search_for_vcs(dependency)[0]

    assert package.name == "demo"
    assert package.version.text == "0.1.2"
    assert package.requires == [get_dependency("pendulum", ">=1.4.4")]
    assert package.extras == {
        "foo": [get_dependency("cleo")],
        "bar": [get_dependency("tomlkit")],
    }
Exemple #19
0
def test_search_for_vcs_read_setup(provider, mocker):
    mocker.patch("poetry.utils.env.EnvManager.get", return_value=MockEnv())

    dependency = VCSDependency("demo", "git",
                               "https://github.com/demo/demo.git")

    package = provider.search_for_vcs(dependency)[0]

    assert package.name == "demo"
    assert package.version.text == "0.1.2"
    assert package.requires == [get_dependency("pendulum", ">=1.4.4")]
    assert package.extras == {
        "foo": [get_dependency("cleo")],
        "bar": [get_dependency("tomlkit")],
    }
Exemple #20
0
def test_search_for_vcs_read_setup_with_extras(provider, mocker):
    mocker.patch("poetry.utils.env.EnvManager.get", return_value=MockEnv())

    dependency = VCSDependency(
        "demo", "git", "https://github.com/demo/demo.git", extras=["foo"]
    )

    package = provider.search_for_vcs(dependency)[0]

    assert package.name == "demo"
    assert package.version.text == "0.1.2"

    required = [r for r in package.requires if not r.is_optional()]
    optional = [r for r in package.requires if r.is_optional()]
    assert required == [get_dependency("pendulum", ">=1.4.4")]
    assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
Exemple #21
0
def test_search_for_vcs_setup_egg_info(provider: Provider):
    dependency = VCSDependency("demo", "git",
                               "https://github.com/demo/demo.git")

    package = provider.search_for_direct_origin_dependency(dependency)

    assert package.name == "demo"
    assert package.version.text == "0.1.2"

    required = [r for r in package.requires if not r.is_optional()]
    optional = [r for r in package.requires if r.is_optional()]
    assert required == [get_dependency("pendulum", ">=1.4.4")]
    assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
    assert package.extras == {
        "foo": [get_dependency("cleo")],
        "bar": [get_dependency("tomlkit")],
    }
Exemple #22
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)
Exemple #23
0
    def to_dependency(self) -> Dependency:
        from pathlib import Path

        from poetry.core.packages.dependency import Dependency
        from poetry.core.packages.directory_dependency import DirectoryDependency
        from poetry.core.packages.file_dependency import FileDependency
        from poetry.core.packages.url_dependency import URLDependency
        from poetry.core.packages.vcs_dependency import VCSDependency

        dep: Dependency
        if self.source_type == "directory":
            dep = DirectoryDependency(
                self._name,
                Path(cast(str, self._source_url)),
                groups=list(self._dependency_groups.keys()),
                optional=self.optional,
                base=self.root_dir,
                develop=self.develop,
                extras=self.features,
            )
        elif self.source_type == "file":
            dep = FileDependency(
                self._name,
                Path(cast(str, self._source_url)),
                groups=list(self._dependency_groups.keys()),
                optional=self.optional,
                base=self.root_dir,
                extras=self.features,
            )
        elif self.source_type == "url":
            dep = URLDependency(
                self._name,
                cast(str, self._source_url),
                groups=list(self._dependency_groups.keys()),
                optional=self.optional,
                extras=self.features,
            )
        elif self.source_type == "git":
            dep = VCSDependency(
                self._name,
                self.source_type,
                cast(str, self.source_url),
                rev=self.source_reference,
                resolved_rev=self.source_resolved_reference,
                directory=self.source_subdirectory,
                groups=list(self._dependency_groups.keys()),
                optional=self.optional,
                develop=self.develop,
                extras=self.features,
            )
        else:
            dep = Dependency(self._name, self._version, extras=self.features)

        if not self.marker.is_any():
            dep.marker = self.marker

        if not self.python_constraint.is_any():
            dep.python_versions = self.python_versions

        if not self.is_direct_origin():
            return dep

        return dep.with_constraint(self._version)
Exemple #24
0
def test_convert_dependencies():
    package = Package("foo", "1.2.3")
    result = SdistBuilder.convert_dependencies(
        package,
        [
            Dependency("A", "^1.0"),
            Dependency("B", "~1.0"),
            Dependency("C", "1.2.3"),
            VCSDependency("D", "git", "https://github.com/sdispater/d.git"),
            Dependency("E", "^1.0"),
            Dependency("F", "^1.0,!=1.3"),
        ],
    )
    main = [
        "A>=1.0,<2.0",
        "B>=1.0,<1.1",
        "C==1.2.3",
        "D @ git+https://github.com/sdispater/d.git@master",
        "E>=1.0,<2.0",
        "F>=1.0,<2.0,!=1.3",
    ]
    extras = {}

    assert result == (main, extras)

    package = Package("foo", "1.2.3")
    package.extras = {"bar": [Dependency("A", "*")]}

    result = SdistBuilder.convert_dependencies(
        package,
        [
            Dependency("A", ">=1.2", optional=True),
            Dependency("B", "~1.0"),
            Dependency("C", "1.2.3"),
        ],
    )
    main = ["B>=1.0,<1.1", "C==1.2.3"]
    extras = {"bar": ["A>=1.2"]}

    assert result == (main, extras)

    c = Dependency("C", "1.2.3")
    c.python_versions = "~2.7 || ^3.6"
    d = Dependency("D", "3.4.5", optional=True)
    d.python_versions = "~2.7 || ^3.4"

    package.extras = {"baz": [Dependency("D", "*")]}

    result = SdistBuilder.convert_dependencies(
        package,
        [
            Dependency("A", ">=1.2", optional=True),
            Dependency("B", "~1.0"), c, d
        ],
    )
    main = ["B>=1.0,<1.1"]

    extra_python = (':python_version >= "2.7" and python_version < "2.8" '
                    'or python_version >= "3.6" and python_version < "4.0"')
    extra_d_dependency = (
        'baz:python_version >= "2.7" and python_version < "2.8" '
        'or python_version >= "3.4" and python_version < "4.0"')
    extras = {extra_python: ["C==1.2.3"], extra_d_dependency: ["D==3.4.5"]}

    assert result == (main, extras)
    def create_from_pep_508(cls,
                            name: str,
                            relative_to: Path | None = None) -> Dependency:
        """
        Resolve a PEP-508 requirement string to a `Dependency` instance. If a `relative_to`
        path is specified, this is used as the base directory if the identified dependency is
        of file or directory type.
        """
        from poetry.core.packages.url_dependency import URLDependency
        from poetry.core.packages.utils.link import Link
        from poetry.core.packages.utils.utils import is_archive_file
        from poetry.core.packages.utils.utils import is_installable_dir
        from poetry.core.packages.utils.utils import is_url
        from poetry.core.packages.utils.utils import path_to_url
        from poetry.core.packages.utils.utils import strip_extras
        from poetry.core.packages.utils.utils import url_to_path
        from poetry.core.packages.vcs_dependency import VCSDependency
        from poetry.core.utils.patterns import wheel_file_re
        from poetry.core.vcs.git import ParsedUrl
        from poetry.core.version.requirements import Requirement

        # Removing comments
        parts = name.split(" #", 1)
        name = parts[0].strip()
        if len(parts) > 1:
            rest = parts[1]
            if " ;" in rest:
                name += " ;" + rest.split(" ;", 1)[1]

        req = Requirement(name)

        name = req.name
        link = None

        if is_url(name):
            link = Link(name)
        elif req.url:
            link = Link(req.url)
        else:
            path_str = os.path.normpath(os.path.abspath(name))
            p, extras = strip_extras(path_str)
            if os.path.isdir(p) and (os.path.sep in name
                                     or name.startswith(".")):

                if not is_installable_dir(p):
                    raise ValueError(
                        f"Directory {name!r} is not installable. File 'setup.py' "
                        "not found.")
                link = Link(path_to_url(p))
            elif is_archive_file(p):
                link = Link(path_to_url(p))

        # it's a local file, dir, or url
        if link:
            is_file_uri = link.scheme == "file"
            is_relative_uri = is_file_uri and re.search(r"\.\./", link.url)

            # Handle relative file URLs
            if is_file_uri and is_relative_uri:
                path = Path(link.path)
                if relative_to:
                    path = relative_to / path
                link = Link(path_to_url(path))

            # wheel file
            version = None
            if link.is_wheel:
                m = wheel_file_re.match(link.filename)
                if not m:
                    raise ValueError(f"Invalid wheel name: {link.filename}")
                name = m.group("name")
                version = m.group("ver")

            dep: Dependency | None = None

            if link.scheme.startswith("git+"):
                url = ParsedUrl.parse(link.url)
                dep = VCSDependency(
                    name,
                    "git",
                    url.url,
                    rev=url.rev,
                    directory=url.subdirectory,
                    extras=req.extras,
                )
            elif link.scheme == "git":
                dep = VCSDependency(name,
                                    "git",
                                    link.url_without_fragment,
                                    extras=req.extras)
            elif link.scheme in ["http", "https"]:
                dep = URLDependency(name, link.url, extras=req.extras)
            elif is_file_uri:
                # handle RFC 8089 references
                path = url_to_path(req.url)
                dep = _make_file_or_dir_dep(name=name,
                                            path=path,
                                            base=relative_to,
                                            extras=req.extras)
            else:
                with suppress(ValueError):
                    # this is a local path not using the file URI scheme
                    dep = _make_file_or_dir_dep(
                        name=name,
                        path=Path(req.url),
                        base=relative_to,
                        extras=req.extras,
                    )

            if dep is None:
                dep = Dependency(name, version or "*", extras=req.extras)

            if version:
                dep._constraint = parse_constraint(version)
        else:
            constraint: VersionConstraint | str
            if req.pretty_constraint:
                constraint = req.constraint
            else:
                constraint = "*"
            dep = Dependency(name, constraint, extras=req.extras)

        if req.marker:
            dep.marker = req.marker

        return dep
Exemple #26
0
    def create_dependency(
        cls,
        name: str,
        constraint: DependencyConstraint,
        groups: list[str] | None = None,
        root_dir: Path | None = None,
    ) -> Dependency:
        from poetry.core.packages.constraints import (
            parse_constraint as parse_generic_constraint, )
        from poetry.core.packages.dependency import Dependency
        from poetry.core.packages.dependency_group import MAIN_GROUP
        from poetry.core.packages.directory_dependency import DirectoryDependency
        from poetry.core.packages.file_dependency import FileDependency
        from poetry.core.packages.url_dependency import URLDependency
        from poetry.core.packages.utils.utils import create_nested_marker
        from poetry.core.packages.vcs_dependency import VCSDependency
        from poetry.core.semver.helpers import parse_constraint
        from poetry.core.version.markers import AnyMarker
        from poetry.core.version.markers import parse_marker

        if groups is None:
            groups = [MAIN_GROUP]

        if constraint is None:
            constraint = "*"

        if isinstance(constraint, dict):
            optional = constraint.get("optional", False)
            python_versions = constraint.get("python")
            platform = constraint.get("platform")
            markers = constraint.get("markers")
            if "allows-prereleases" in constraint:
                message = (
                    f'The "{name}" dependency specifies '
                    'the "allows-prereleases" property, which is deprecated. '
                    'Use "allow-prereleases" instead.')
                warn(message, DeprecationWarning)
                logger.warning(message)

            allows_prereleases = constraint.get(
                "allow-prereleases", constraint.get("allows-prereleases",
                                                    False))

            dependency: Dependency
            if "git" in constraint:
                # VCS dependency
                dependency = VCSDependency(
                    name,
                    "git",
                    constraint["git"],
                    branch=constraint.get("branch", None),
                    tag=constraint.get("tag", None),
                    rev=constraint.get("rev", None),
                    directory=constraint.get("subdirectory", None),
                    groups=groups,
                    optional=optional,
                    develop=constraint.get("develop", False),
                    extras=constraint.get("extras", []),
                )
            elif "file" in constraint:
                file_path = Path(constraint["file"])

                dependency = FileDependency(
                    name,
                    file_path,
                    groups=groups,
                    base=root_dir,
                    extras=constraint.get("extras", []),
                )
            elif "path" in constraint:
                path = Path(constraint["path"])

                if root_dir:
                    is_file = root_dir.joinpath(path).is_file()
                else:
                    is_file = path.is_file()

                if is_file:
                    dependency = FileDependency(
                        name,
                        path,
                        groups=groups,
                        optional=optional,
                        base=root_dir,
                        extras=constraint.get("extras", []),
                    )
                else:
                    dependency = DirectoryDependency(
                        name,
                        path,
                        groups=groups,
                        optional=optional,
                        base=root_dir,
                        develop=constraint.get("develop", False),
                        extras=constraint.get("extras", []),
                    )
            elif "url" in constraint:
                dependency = URLDependency(
                    name,
                    constraint["url"],
                    groups=groups,
                    optional=optional,
                    extras=constraint.get("extras", []),
                )
            else:
                version = constraint["version"]

                dependency = Dependency(
                    name,
                    version,
                    optional=optional,
                    groups=groups,
                    allows_prereleases=allows_prereleases,
                    extras=constraint.get("extras", []),
                )

            marker = parse_marker(markers) if markers else AnyMarker()

            if python_versions:
                marker = marker.intersect(
                    parse_marker(
                        create_nested_marker(
                            "python_version",
                            parse_constraint(python_versions))))

            if platform:
                marker = marker.intersect(
                    parse_marker(
                        create_nested_marker(
                            "sys_platform",
                            parse_generic_constraint(platform))))

            if not marker.is_any():
                dependency.marker = marker

            dependency.source_name = constraint.get("source")
        else:
            dependency = Dependency(name, constraint, groups=groups)

        return dependency