예제 #1
0
def test_invalid_requirement(string, exception):
    with pytest.raises(
            InvalidRequirement,
            match=re.escape(
                "The requirement is invalid: {}".format(exception)),
    ):
        Requirement(string)
예제 #2
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
def test_invalid_requirement(string: str, exception: str) -> None:
    with pytest.raises(
            InvalidRequirement,
            match=re.escape(f"The requirement is invalid: {exception}"),
    ):
        Requirement(string)
def test_requirement(string: str, expected: dict[str, Any]) -> None:
    req = Requirement(string)

    assert_requirement(req, **expected)
예제 #5
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
예제 #6
0
def test_requirement(string, expected):
    req = Requirement(string)

    assert_requirement(req, **expected)
예제 #7
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