def _parse_dependency_specification_git_url(requirement: str,
                                            env: Env | None = None
                                            ) -> DependencySpec | None:
    from poetry.core.vcs.git import Git
    from poetry.core.vcs.git import ParsedUrl

    parsed = ParsedUrl.parse(requirement)
    url = Git.normalize_url(requirement)

    pair = {"name": parsed.name, "git": url.url}

    if parsed.rev:
        pair["rev"] = url.revision

    if parsed.subdirectory:
        pair["subdirectory"] = parsed.subdirectory

    source_root = env.path.joinpath("src") if env else None
    package = Provider.get_package_from_vcs(
        "git",
        url=url.url,
        rev=pair.get("rev"),
        subdirectory=parsed.subdirectory,
        source_root=source_root,
    )
    pair["name"] = package.name
    return pair
示例#2
0
文件: helpers.py 项目: yosmoc/poetry
def mock_clone(_, source, dest):
    # Checking source to determine which folder we need to copy
    parsed = ParsedUrl.parse(source)

    folder = (Path(__file__).parent / "fixtures" / "git" / parsed.resource /
              parsed.pathname.lstrip("/").rstrip(".git"))

    copy_or_symlink(folder, dest)
示例#3
0
def test_parse_url(url: str, parsed: ParsedUrl) -> None:
    result = ParsedUrl.parse(url)
    assert parsed.name == result.name
    assert parsed.pathname == result.pathname
    assert parsed.port == result.port
    assert parsed.protocol == result.protocol
    assert parsed.resource == result.resource
    assert parsed.rev == result.rev
    assert parsed.url == result.url
    assert parsed.user == result.user
示例#4
0
def test_parse_url(url, parsed):
    result = ParsedUrl.parse(url)
    assert parsed.name == result.name
    assert parsed.pathname == result.pathname
    assert parsed.port == result.port
    assert parsed.protocol == result.protocol
    assert parsed.resource == result.resource
    assert parsed.rev == result.rev
    assert parsed.url == result.url
    assert parsed.user == result.user
    assert parsed.password == result.password
示例#5
0
def mock_clone(
    url: str,
    *_: Any,
    source_root: Path | None = None,
    **__: Any,
) -> MockDulwichRepo:
    # Checking source to determine which folder we need to copy
    parsed = ParsedUrl.parse(url)
    path = re.sub(r"(.git)?$", "", parsed.pathname.lstrip("/"))

    folder = Path(__file__).parent / "fixtures" / "git" / parsed.resource / path

    if not source_root:
        source_root = Path(Config.create().get("cache-dir")) / "src"

    dest = source_root / path
    dest.parent.mkdir(parents=True, exist_ok=True)

    copy_or_symlink(folder, dest)
    return MockDulwichRepo(dest)
示例#6
0
文件: init.py 项目: zipdrug/poetry
    def _parse_requirements(self, requirements: List[str]) -> List[Dict[str, str]]:
        from poetry.puzzle.provider import Provider

        result = []

        try:
            cwd = self.poetry.file.parent
        except (PyProjectException, RuntimeError):
            cwd = Path.cwd()

        for requirement in requirements:
            requirement = requirement.strip()
            extras = []
            extras_m = re.search(r"\[([\w\d,-_ ]+)\]$", requirement)
            if extras_m:
                extras = [e.strip() for e in extras_m.group(1).split(",")]
                requirement, _ = requirement.split("[")

            url_parsed = urllib.parse.urlparse(requirement)
            if url_parsed.scheme and url_parsed.netloc:
                # Url
                if url_parsed.scheme in ["git+https", "git+ssh"]:
                    from poetry.core.vcs.git import Git
                    from poetry.core.vcs.git import ParsedUrl

                    parsed = ParsedUrl.parse(requirement)
                    url = Git.normalize_url(requirement)

                    pair = dict([("name", parsed.name), ("git", url.url)])
                    if parsed.rev:
                        pair["rev"] = url.revision

                    if extras:
                        pair["extras"] = extras

                    package = Provider.get_package_from_vcs(
                        "git", url.url, rev=pair.get("rev")
                    )
                    pair["name"] = package.name
                    result.append(pair)

                    continue
                elif url_parsed.scheme in ["http", "https"]:
                    package = Provider.get_package_from_url(requirement)

                    pair = dict([("name", package.name), ("url", package.source_url)])
                    if extras:
                        pair["extras"] = extras

                    result.append(pair)
                    continue
            elif (os.path.sep in requirement or "/" in requirement) and cwd.joinpath(
                requirement
            ).exists():
                path = cwd.joinpath(requirement)
                if path.is_file():
                    package = Provider.get_package_from_file(path.resolve())
                else:
                    package = Provider.get_package_from_directory(path)

                result.append(
                    dict(
                        [
                            ("name", package.name),
                            ("path", path.relative_to(cwd).as_posix()),
                        ]
                        + ([("extras", extras)] if extras else [])
                    )
                )

                continue

            pair = re.sub(
                "^([^@=: ]+)(?:@|==|(?<![<>~!])=|:| )(.*)$", "\\1 \\2", requirement
            )
            pair = pair.strip()

            require = dict()
            if " " in pair:
                name, version = pair.split(" ", 2)
                extras_m = re.search(r"\[([\w\d,-_]+)\]$", name)
                if extras_m:
                    extras = [e.strip() for e in extras_m.group(1).split(",")]
                    name, _ = name.split("[")

                require["name"] = name
                if version != "latest":
                    require["version"] = version
            else:
                m = re.match(
                    r"^([^><=!: ]+)((?:>=|<=|>|<|!=|~=|~|\^).*)$", requirement.strip()
                )
                if m:
                    name, constraint = m.group(1), m.group(2)
                    extras_m = re.search(r"\[([\w\d,-_]+)\]$", name)
                    if extras_m:
                        extras = [e.strip() for e in extras_m.group(1).split(",")]
                        name, _ = name.split("[")

                    require["name"] = name
                    require["version"] = constraint
                else:
                    extras_m = re.search(r"\[([\w\d,-_]+)\]$", pair)
                    if extras_m:
                        extras = [e.strip() for e in extras_m.group(1).split(",")]
                        pair, _ = pair.split("[")

                    require["name"] = pair

            if extras:
                require["extras"] = extras

            result.append(require)

        return result
示例#7
0
def dependency_from_pep_508(name):
    from poetry.core.vcs.git import ParsedUrl

    # 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)

    if req.marker:
        markers = convert_markers(req.marker)
    else:
        markers = {}

    name = req.name
    path = os.path.normpath(os.path.abspath(name))
    link = None

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

            if not is_installable_dir(p):
                raise ValueError(
                    "Directory {!r} is not installable. File 'setup.py' "
                    "not found.".format(name))
            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:
        # Handle relative file URLs
        if link.scheme == "file" and re.search(r"\.\./", link.url):
            link = Link(
                path_to_url(os.path.normpath(os.path.abspath(link.path))))
        # wheel file
        if link.is_wheel:
            m = wheel_file_re.match(link.filename)
            if not m:
                raise ValueError("Invalid wheel name: {}".format(
                    link.filename))

            name = m.group("name")
            version = m.group("ver")
            dep = Dependency(name, version)
        else:
            name = req.name or link.egg_fragment

            if link.scheme.startswith("git+"):
                url = ParsedUrl.parse(link.url)
                dep = VCSDependency(name, "git", url.url, rev=url.rev)
            elif link.scheme == "git":
                dep = VCSDependency(name, "git", link.url_without_fragment)
            elif link.scheme in ["http", "https"]:
                dep = URLDependency(name, link.url_without_fragment)
            else:
                dep = Dependency(name, "*")
    else:
        if req.pretty_constraint:
            constraint = req.constraint
        else:
            constraint = "*"

        dep = Dependency(name, constraint)

    if "extra" in markers:
        # If we have extras, the dependency is optional
        dep.deactivate()

        for or_ in markers["extra"]:
            for _, extra in or_:
                dep.in_extras.append(extra)

    if "python_version" in markers:
        ors = []
        for or_ in markers["python_version"]:
            ands = []
            for op, version in or_:
                # Expand python version
                if op == "==":
                    version = "~" + version
                    op = ""
                elif op == "!=":
                    version += ".*"
                elif op in ("<=", ">"):
                    parsed_version = Version.parse(version)
                    if parsed_version.precision == 1:
                        if op == "<=":
                            op = "<"
                            version = parsed_version.next_major.text
                        elif op == ">":
                            op = ">="
                            version = parsed_version.next_major.text
                    elif parsed_version.precision == 2:
                        if op == "<=":
                            op = "<"
                            version = parsed_version.next_minor.text
                        elif op == ">":
                            op = ">="
                            version = parsed_version.next_minor.text
                elif op in ("in", "not in"):
                    versions = []
                    for v in re.split("[ ,]+", version):
                        split = v.split(".")
                        if len(split) in [1, 2]:
                            split.append("*")
                            op_ = "" if op == "in" else "!="
                        else:
                            op_ = "==" if op == "in" else "!="

                        versions.append(op_ + ".".join(split))

                    glue = " || " if op == "in" else ", "
                    if versions:
                        ands.append(glue.join(versions))

                    continue

                ands.append("{}{}".format(op, version))

            ors.append(" ".join(ands))

        dep.python_versions = " || ".join(ors)

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

    # Extras
    for extra in req.extras:
        dep.extras.append(extra)

    return dep
示例#8
0
def test_parse_url_should_fail() -> None:
    url = "https://" + "@" * 64 + "!"

    with pytest.raises(ValueError):
        ParsedUrl.parse(url)
示例#9
0
                "subdirectory",
                "subdirectory",
            ),
        ),
    ],
)
def test_normalize_url(url: str, normalized: GitUrl) -> None:
    assert normalized == Git.normalize_url(url)


@pytest.mark.parametrize(
    "url, parsed",
    [
        (
            "git+ssh://user@hostname:project.git#commit",
            ParsedUrl("ssh", "hostname", ":project.git", "user", None,
                      "project", "commit"),
        ),
        (
            "git+http://user@hostname/project/blah.git@commit",
            ParsedUrl("http", "hostname", "/project/blah.git", "user", None,
                      "blah", "commit"),
        ),
        (
            "git+https://user@hostname/project/blah.git",
            ParsedUrl("https", "hostname", "/project/blah.git", "user", None,
                      "blah", None),
        ),
        (
            "git+https://user@hostname/project~_-.foo/blah~_-.bar.git",
            ParsedUrl(
                "https",
示例#10
0
def dependency_from_pep_508(name,
                            relative_to=None
                            ):  # type: (str, Optional[Path]) -> 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.vcs.git import ParsedUrl

    # 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)

    if req.marker:
        markers = convert_markers(req.marker)
    else:
        markers = {}

    name = req.name
    path = os.path.normpath(os.path.abspath(name))
    link = None

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

            if not is_installable_dir(p):
                raise ValueError(
                    "Directory {!r} is not installable. File 'setup.py' "
                    "not found.".format(name))
            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("Invalid wheel name: {}".format(
                    link.filename))
            name = m.group("name")
            version = m.group("ver")

        name = req.name or link.egg_fragment
        dep = None

        if link.scheme.startswith("git+"):
            url = ParsedUrl.parse(link.url)
            dep = VCSDependency(name,
                                "git",
                                url.url,
                                rev=url.rev,
                                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)
        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:
            try:
                # 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,
                )
            except ValueError:
                pass

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

        if version:
            dep._constraint = parse_constraint(version)
    else:
        if req.pretty_constraint:
            constraint = req.constraint
        else:
            constraint = "*"

        dep = Dependency(name, constraint, extras=req.extras)

    if "extra" in markers:
        # If we have extras, the dependency is optional
        dep.deactivate()

        for or_ in markers["extra"]:
            for _, extra in or_:
                dep.in_extras.append(extra)

    if "python_version" in markers:
        ors = []
        for or_ in markers["python_version"]:
            ands = []
            for op, version in or_:
                # Expand python version
                if op == "==" and "*" not in version:
                    version = "~" + version
                    op = ""
                elif op == "!=":
                    version += ".*"
                elif op in ("<=", ">"):
                    parsed_version = Version.parse(version)
                    if parsed_version.precision == 1:
                        if op == "<=":
                            op = "<"
                            version = parsed_version.next_major.text
                        elif op == ">":
                            op = ">="
                            version = parsed_version.next_major.text
                    elif parsed_version.precision == 2:
                        if op == "<=":
                            op = "<"
                            version = parsed_version.next_minor.text
                        elif op == ">":
                            op = ">="
                            version = parsed_version.next_minor.text
                elif op in ("in", "not in"):
                    versions = []
                    for v in re.split("[ ,]+", version):
                        split = v.split(".")
                        if len(split) in [1, 2]:
                            split.append("*")
                            op_ = "" if op == "in" else "!="
                        else:
                            op_ = "==" if op == "in" else "!="

                        versions.append(op_ + ".".join(split))

                    glue = " || " if op == "in" else ", "
                    if versions:
                        ands.append(glue.join(versions))

                    continue

                ands.append("{}{}".format(op, version))

            ors.append(" ".join(ands))

        dep.python_versions = " || ".join(ors)

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

    return dep
示例#11
0
    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
示例#12
0
        ),
    ],
)
def test_normalize_url(url, normalized):
    assert normalized == Git.normalize_url(url)


@pytest.mark.parametrize(
    "url, parsed",
    [
        (
            "git+ssh://user@hostname:project.git#commit",
            ParsedUrl(
                protocol="ssh",
                resource="hostname",
                pathname=":project.git",
                user="******",
                name="project",
                rev="commit",
            ),
        ),
        (
            "git+http://user@hostname/project/blah.git@commit",
            ParsedUrl(
                protocol="http",
                resource="hostname",
                pathname="/project/blah.git",
                user="******",
                name="blah",
                rev="commit",
            ),
        ),