def get_requirements(items: dict, inculde_optional) -> Dict[str, Requirement]:
    rv = {}
    for k, v in items.items():
        vc = None

        if isinstance(v, str):
            vc = parse_constraint(v)

        elif isinstance(v, dict):
            if not v.get('optional') or inculde_optional:
                version = v.get('version')
                if isinstance(version, str):
                    vc = parse_constraint(version)

        else:
            raise NotImplementedError(type(v))

        if vc:
            vcs = str(vc)
            if vcs == '*':
                rv[k] = Requirement(k)
            else:
                rv[k] = Requirement(k + vcs)

    return rv
Example #2
0
    def all_classifiers(self):
        classifiers = copy.copy(self.classifiers)

        # Automatically set python classifiers
        if self.python_versions == "*":
            python_constraint = parse_constraint("~2.7 || ^3.4")
        else:
            python_constraint = self.python_constraint

        for version in sorted(self.AVAILABLE_PYTHONS):
            if len(version) == 1:
                constraint = parse_constraint(version + ".*")
            else:
                constraint = Version.parse(version)

            if python_constraint.allows_any(constraint):
                classifiers.append(
                    "Programming Language :: Python :: {}".format(version))

        # Automatically set license classifiers
        if self.license:
            classifiers.append(self.license.classifier)

        classifiers = set(classifiers)

        return sorted(classifiers)
Example #3
0
    def write(self) -> str:
        buffer = []

        required_python_version_notification = False
        for incompatibility in self._root.external_incompatibilities:
            if isinstance(incompatibility.cause, PythonCause):
                if not required_python_version_notification:
                    buffer.append(
                        "The current project's Python requirement ({}) "
                        "is not compatible with some of the required "
                        "packages Python requirement:".format(
                            incompatibility.cause.root_python_version))
                    required_python_version_notification = True

                root_constraint = parse_constraint(
                    incompatibility.cause.root_python_version)
                constraint = parse_constraint(
                    incompatibility.cause.python_version)
                buffer.append(
                    "  - {} requires Python {}, so it will not be satisfied for Python {}"
                    .format(
                        incompatibility.terms[0].dependency.name,
                        incompatibility.cause.python_version,
                        root_constraint.difference(constraint),
                    ))

        if required_python_version_notification:
            buffer.append("")

        if isinstance(self._root.cause, ConflictCause):
            self._visit(self._root, {})
        else:
            self._write(
                self._root,
                "Because {}, version solving failed.".format(self._root))

        padding = (0 if not self._line_numbers else len("({}) ".format(
            list(self._line_numbers.values())[-1])))

        last_was_empty = False
        for line in self._lines:
            message = line[0]
            if not message:
                if not last_was_empty:
                    buffer.append("")

                last_was_empty = True
                continue

            last_was_empty = False

            number = line[-1]
            if number is not None:
                message = "({})".format(number).ljust(padding) + message
            else:
                message = " " * padding + message

            buffer.append(message)

        return "\n".join(buffer)
    def __init__(self, exception):
        from poetry.core.semver import parse_constraint
        from poetry.mixology.incompatibility_cause import PythonCause

        self._title = "Check your dependencies Python requirement."

        failure = exception.error
        version_solutions = []
        for incompatibility in failure._incompatibility.external_incompatibilities:
            if isinstance(incompatibility.cause, PythonCause):
                root_constraint = parse_constraint(
                    incompatibility.cause.root_python_version
                )
                constraint = parse_constraint(incompatibility.cause.python_version)

                version_solutions.append(
                    "For <fg=default;options=bold>{}</>, a possible solution would be "
                    'to set the `<fg=default;options=bold>python</>` property to <fg=yellow>"{}"</>'.format(
                        incompatibility.terms[0].dependency.name,
                        root_constraint.intersect(constraint),
                    )
                )

        description = (
            "The Python requirement can be specified via the `<fg=default;options=bold>python</>` "
            "or `<fg=default;options=bold>markers</>` properties"
        )
        if version_solutions:
            description += "\n\n" + "\n".join(version_solutions)

        description += "\n"

        self._description = description
Example #5
0
 def set_constraint(self, constraint):
     try:
         if not isinstance(constraint, VersionConstraint):
             self._constraint = parse_constraint(constraint)
         else:
             self._constraint = constraint
     except ValueError:
         self._constraint = parse_constraint("*")
Example #6
0
 def set_constraint(self, constraint):  # type: (Union[str, "VersionTypes"]) -> None
     try:
         if not isinstance(constraint, VersionConstraint):
             self._constraint = parse_constraint(constraint)
         else:
             self._constraint = constraint
     except ValueError:
         self._constraint = parse_constraint("*")
Example #7
0
File: new.py Project: yosmoc/poetry
    def handle(self):
        from pathlib import Path

        from poetry.core.semver import parse_constraint
        from poetry.core.vcs.git import GitConfig
        from poetry.layouts import layout
        from poetry.utils.env import SystemEnv

        if self.option("src"):
            layout_ = layout("src")
        else:
            layout_ = layout("standard")

        path = Path.cwd() / Path(self.argument("path"))
        name = self.option("name")
        if not name:
            name = path.name

        if path.exists():
            if list(path.glob("*")):
                # Directory is not empty. Aborting.
                raise RuntimeError("Destination <fg=yellow>{}</> "
                                   "exists and is not empty".format(path))

        readme_format = "rst"

        config = GitConfig()
        author = None
        if config.get("user.name"):
            author = config["user.name"]
            author_email = config.get("user.email")
            if author_email:
                author += " <{}>".format(author_email)

        current_env = SystemEnv(Path(sys.executable))
        default_python = "^{}".format(".".join(
            str(v) for v in current_env.version_info[:2]))

        dev_dependencies = {}
        python_constraint = parse_constraint(default_python)
        if parse_constraint("<3.5").allows_any(python_constraint):
            dev_dependencies["pytest"] = "^4.6"
        if parse_constraint(">=3.5").allows_all(python_constraint):
            dev_dependencies["pytest"] = "^5.2"

        layout_ = layout_(
            name,
            "0.1.0",
            author=author,
            readme_format=readme_format,
            python=default_python,
            dev_dependencies=dev_dependencies,
        )
        layout_.create(path)

        self.line("Created package <info>{}</> in <fg=blue>{}</>".format(
            module_name(name), path.relative_to(Path.cwd())))
Example #8
0
    def __init__(
        self,
        name,  # type: str
        constraint,  # type: Union[str, VersionConstraint]
        optional=False,  # type: bool
        category="main",  # type: str
        allows_prereleases=False,  # type: bool
        extras=None,  # type: Union[List[str], FrozenSet[str]]
        source_type=None,  # type: Optional[str]
        source_url=None,  # type: Optional[str]
        source_reference=None,  # type: Optional[str]
        source_resolved_reference=None,  # type: Optional[str]
    ):
        super(Dependency, self).__init__(
            name,
            source_type=source_type,
            source_url=source_url,
            source_reference=source_reference,
            source_resolved_reference=source_resolved_reference,
            features=extras,
        )

        try:
            if not isinstance(constraint, VersionConstraint):
                self._constraint = parse_constraint(constraint)
            else:
                self._constraint = constraint
        except ValueError:
            self._constraint = parse_constraint("*")

        self._pretty_constraint = str(constraint)
        self._optional = optional
        self._category = category

        if isinstance(self._constraint, VersionRange) and self._constraint.min:
            allows_prereleases = (
                allows_prereleases or self._constraint.min.is_prerelease()
            )

        self._allows_prereleases = allows_prereleases

        self._python_versions = "*"
        self._python_constraint = parse_constraint("*")
        self._transitive_python_versions = None
        self._transitive_python_constraint = None
        self._transitive_marker = None
        self._extras = frozenset(extras or [])

        self._in_extras = []

        self._activated = not self._optional

        self.is_root = False
        self.marker = AnyMarker()
        self.source_name = None
Example #9
0
    def find_packages(self, dependency: "Dependency") -> List["Package"]:
        constraint = dependency.constraint
        packages = []
        ignored_pre_release_packages = []

        if constraint is None:
            constraint = "*"

        if not isinstance(constraint, VersionConstraint):
            constraint = parse_constraint(constraint)

        allow_prereleases = dependency.allows_prereleases()
        if isinstance(constraint, VersionRange):
            if (constraint.max is not None and constraint.max.is_prerelease()
                    or constraint.min is not None
                    and constraint.min.is_prerelease()):
                allow_prereleases = True

        for package in self.packages:
            if dependency.name == package.name:
                if (package.is_prerelease() and not allow_prereleases
                        and not package.source_type):
                    # If prereleases are not allowed and the package is a prerelease
                    # and is a standard package then we skip it
                    if constraint.is_any():
                        # we need this when all versions of the package are pre-releases
                        ignored_pre_release_packages.append(package)
                    continue

                if constraint.allows(package.version) or (
                        package.is_prerelease()
                        and constraint.allows(package.version.next_patch)):
                    packages.append(package)

        return packages or ignored_pre_release_packages
Example #10
0
    def get_release_info(self, name: str, version: str) -> PackageInfo:
        """
        Return the release information given a package name and a version.

        The information is returned from the cache if it exists
        or retrieved from the remote server.
        """
        if self._disable_cache:
            return PackageInfo.load(self._get_release_info(name, version))

        cached = self._cache.remember_forever(
            "{}:{}".format(name, version),
            lambda: self._get_release_info(name, version))

        cache_version = cached.get("_cache_version", "0.0.0")
        if parse_constraint(cache_version) != self.CACHE_VERSION:
            # The cache must be updated
            self._log(
                "The cache for {} {} is outdated. Refreshing.".format(
                    name, version),
                level="debug",
            )
            cached = self._get_release_info(name, version)

            self._cache.forever("{}:{}".format(name, version), cached)

        return PackageInfo.load(cached)
Example #11
0
    def __init__(self, requirement_string):
        try:
            req = REQUIREMENT.parseString(requirement_string)
        except ParseException as e:
            raise InvalidRequirement(
                'Invalid requirement, parse error at "{0!r}"'.format(
                    requirement_string[e.loc:e.loc + 8]))

        self.name = req.name
        if req.url:
            parsed_url = urlparse.urlparse(req.url)
            if parsed_url.scheme == "file":
                if urlparse.urlunparse(parsed_url) != req.url:
                    raise InvalidRequirement("Invalid URL given")
            elif (not (parsed_url.scheme and parsed_url.netloc) or
                  (not parsed_url.scheme
                   and not parsed_url.netloc)) and not parsed_url.path:
                raise InvalidRequirement("Invalid URL: {0}".format(req.url))
            self.url = req.url
        else:
            self.url = None

        self.extras = set(req.extras.asList() if req.extras else [])
        constraint = req.specifier
        if not constraint:
            constraint = "*"

        self.constraint = parse_constraint(constraint)
        self.pretty_constraint = constraint

        self.marker = req.marker if req.marker else None
Example #12
0
def get_python_constraint_from_marker(
    marker, ):  # type: (BaseMarker) -> VersionConstraint
    python_marker = marker.only("python_version")
    if python_marker.is_any():
        return VersionRange()

    if python_marker.is_empty():
        return EmptyConstraint()

    markers = convert_markers(marker)

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

    return parse_constraint(" || ".join(ors))
Example #13
0
    def _get_lock_data(self):  # type: () -> dict
        if not self._lock.exists():
            raise RuntimeError(
                "No lockfile found. Unable to read locked packages")

        try:
            lock_data = self._lock.read()
        except TOMLKitError as e:
            raise RuntimeError("Unable to read the lock file ({}).".format(e))

        lock_version = Version.parse(lock_data["metadata"].get(
            "lock-version", "1.0"))
        current_version = Version.parse(self._VERSION)
        accepted_versions = parse_constraint("^{}".format(
            Version(current_version.major, current_version.minor)))
        lock_version_allowed = accepted_versions.allows(lock_version)
        if lock_version_allowed and current_version < lock_version:
            logger.warning(
                "The lock file might not be compatible with the current version of Poetry.\n"
                "Upgrade Poetry to ensure the lock file is read properly or, alternatively, "
                "regenerate the lock file with the `poetry lock` command.")
        elif not lock_version_allowed:
            raise RuntimeError(
                "The lock file is not compatible with the current version of Poetry.\n"
                "Upgrade Poetry to be able to read the lock file or, alternatively, "
                "regenerate the lock file with the `poetry lock` command.")

        return lock_data
Example #14
0
    def find_packages(self,
                      name,
                      constraint=None,
                      extras=None,
                      allow_prereleases=False):
        packages = []

        if constraint is None:
            constraint = "*"

        if not isinstance(constraint, VersionConstraint):
            constraint = parse_constraint(constraint)

        if isinstance(constraint, VersionRange):
            if (constraint.max is not None and constraint.max.is_prerelease()
                    or constraint.min is not None
                    and constraint.min.is_prerelease()):
                allow_prereleases = True

        key = name
        if not constraint.is_any():
            key = "{}:{}".format(key, str(constraint))

        if self._cache.store("matches").has(key):
            versions = self._cache.store("matches").get(key)
        else:
            page = self._get("/{}/".format(
                canonicalize_name(name).replace(".", "-")))
            if page is None:
                return []

            versions = []
            for version in page.versions:
                if version.is_prerelease() and not allow_prereleases:
                    continue

                if constraint.allows(version):
                    versions.append(version)

            self._cache.store("matches").put(key, versions, 5)

        for version in versions:
            package = Package(name, version)
            package.source_type = "legacy"
            package.source_reference = self.name
            package.source_url = self._url

            if extras is not None:
                package.requires_extras = extras

            packages.append(package)

        self._log(
            "{} packages found for {} {}".format(len(packages), name,
                                                 str(constraint)),
            level="debug",
        )

        return packages
Example #15
0
 def python_versions(self, value):
     self._python_versions = value
     self._python_constraint = parse_constraint(value)
     if not self._python_constraint.is_any():
         self.marker = self.marker.intersect(
             parse_marker(
                 self._create_nested_marker("python_version",
                                            self._python_constraint)))
Example #16
0
    def __init__(
        self,
        name,  # type: str
        constraint,  # type: str
        optional=False,  # type: bool
        category="main",  # type: str
        allows_prereleases=False,  # type: bool
        source_name=None,  # type: Optional[str]
    ):
        self._name = canonicalize_name(name)
        self._pretty_name = name

        try:
            if not isinstance(constraint, VersionConstraint):
                self._constraint = parse_constraint(constraint)
            else:
                self._constraint = constraint
        except ValueError:
            self._constraint = parse_constraint("*")

        self._pretty_constraint = str(constraint)
        self._optional = optional
        self._category = category

        if isinstance(self._constraint, VersionRange) and self._constraint.min:
            allows_prereleases = (
                allows_prereleases or self._constraint.min.is_prerelease()
            )

        self._allows_prereleases = allows_prereleases
        self._source_name = source_name

        self._python_versions = "*"
        self._python_constraint = parse_constraint("*")
        self._transitive_python_versions = None
        self._transitive_python_constraint = None
        self._transitive_marker = None

        self._extras = []
        self._in_extras = []

        self._activated = not self._optional

        self.is_root = False
        self.marker = AnyMarker()
Example #17
0
    def __init__(self, requirement_string):
        try:
            parsed = _parser.parse(requirement_string)
        except (UnexpectedCharacters, UnexpectedToken) as e:
            raise InvalidRequirement(
                "The requirement is invalid: Unexpected character at column {}\n\n{}".format(
                    e.column, e.get_context(requirement_string)
                )
            )

        self.name = next(parsed.scan_values(lambda t: t.type == "NAME")).value
        url = next(parsed.scan_values(lambda t: t.type == "URI"), None)

        if url:
            url = url.value
            parsed_url = urlparse.urlparse(url)
            if parsed_url.scheme == "file":
                if urlparse.urlunparse(parsed_url) != url:
                    raise InvalidRequirement(
                        'The requirement is invalid: invalid URL "{0}"'.format(url)
                    )
            elif (
                not (parsed_url.scheme and parsed_url.netloc)
                or (not parsed_url.scheme and not parsed_url.netloc)
            ) and not parsed_url.path:
                raise InvalidRequirement(
                    'The requirement is invalid: invalid URL "{0}"'.format(url)
                )
            self.url = url
        else:
            self.url = None

        self.extras = [e.value for e in parsed.scan_values(lambda t: t.type == "EXTRA")]
        constraint = next(parsed.find_data("version_specification"), None)
        if not constraint:
            constraint = "*"
        else:
            constraint = ",".join(constraint.children)

        try:
            self.constraint = parse_constraint(constraint)
        except ParseConstraintError:
            raise InvalidRequirement(
                'The requirement is invalid: invalid version constraint "{}"'.format(
                    constraint
                )
            )

        self.pretty_constraint = constraint

        marker = next(parsed.find_data("marker_spec"), None)
        if marker:
            marker = _compact_markers(
                marker.children[0].children, tree_prefix="markers__"
            )

        self.marker = marker
Example #18
0
    def python_versions(self, value):
        self._python_versions = value

        if value == "*" or value == VersionRange():
            value = "~2.7 || >=3.4"

        self._python_constraint = parse_constraint(value)
        self._python_marker = parse_marker(
            create_nested_marker("python_version", self._python_constraint))
Example #19
0
    def find_best_candidate(
        self,
        package_name,  # type: str
        target_package_version=None,  # type:  Union[str, None]
        allow_prereleases=False,  # type: bool
        source=None,  # type: str
    ):  # type: (...) -> Union[Package, bool]
        """
        Given a package name and optional version,
        returns the latest Package that matches
        """
        if target_package_version:
            constraint = parse_constraint(target_package_version)
        else:
            constraint = parse_constraint("*")

        candidates = self._pool.find_packages(
            package_name, constraint, allow_prereleases=True, repository=source
        )
        only_prereleases = all([c.version.is_prerelease() for c in candidates])

        if not candidates:
            return False

        dependency = Dependency(package_name, constraint)

        package = None
        for candidate in candidates:
            if (
                candidate.is_prerelease()
                and not dependency.allows_prereleases()
                and not allow_prereleases
                and not only_prereleases
            ):
                continue

            # Select highest version of the two
            if package is None or package.version < candidate.version:
                package = candidate

        if package is None:
            return False
        return package
Example #20
0
def assert_requirement(req, name, url=None, extras=None, constraint="*", marker=None):
    if extras is None:
        extras = []

    assert name == req.name
    assert url == req.url
    assert sorted(extras) == sorted(req.extras)
    assert parse_constraint(constraint) == req.constraint

    if marker:
        assert marker == str(req.marker)
Example #21
0
    def __init__(self, name, version, pretty_version=None):
        super(ProjectPackage, self).__init__(name, version, pretty_version)

        self.build_config = dict()
        self.packages = []
        self.include = []
        self.exclude = []
        self.custom_urls = {}

        if self._python_versions == "*":
            self._python_constraint = parse_constraint("~2.7 || >=3.4")
Example #22
0
    def find_packages(self,
                      name,
                      constraint=None,
                      extras=None,
                      allow_prereleases=False):
        name = name.lower()
        packages = []
        ignored_pre_release_packages = []

        if extras is None:
            extras = []

        if constraint is None:
            constraint = "*"

        if not isinstance(constraint, VersionConstraint):
            constraint = parse_constraint(constraint)

        if isinstance(constraint, VersionRange):
            if (constraint.max is not None and constraint.max.is_prerelease()
                    or constraint.min is not None
                    and constraint.min.is_prerelease()):
                allow_prereleases = True

        for package in self.packages:
            if name == package.name:
                if (package.is_prerelease() and not allow_prereleases
                        and not package.source_type):
                    # If prereleases are not allowed and the package is a prerelease
                    # and is a standard package then we skip it
                    if constraint.is_any():
                        # we need this when all versions of the package are pre-releases
                        ignored_pre_release_packages.append(package)
                    continue

                if constraint.allows(package.version):
                    for dep in package.requires:
                        for extra in extras:
                            if extra not in package.extras:
                                continue

                            reqs = package.extras[extra]
                            for req in reqs:
                                if req.name == dep.name:
                                    dep.activate()

                    if extras:
                        package.requires_extras = extras

                    packages.append(package)

        return packages or ignored_pre_release_packages
Example #23
0
    def __init__(self, name, version, pretty_version=None):
        """
        Creates a new in memory package.
        """
        self._pretty_name = name
        self._name = canonicalize_name(name)

        if not isinstance(version, Version):
            self._version = Version.parse(version)
            self._pretty_version = pretty_version or version
        else:
            self._version = version
            self._pretty_version = pretty_version or self._version.text

        self.description = ""

        self._authors = []
        self._maintainers = []

        self.homepage = None
        self.repository_url = None
        self.documentation_url = None
        self.keywords = []
        self._license = None
        self.readme = None

        self.source_name = ""
        self.source_type = ""
        self.source_reference = ""
        self.source_url = ""

        self.requires = []
        self.dev_requires = []
        self.extras = {}
        self.requires_extras = []

        self.category = "main"
        self.files = []
        self.optional = False

        self.classifiers = []

        self._python_versions = "*"
        self._python_constraint = parse_constraint("*")
        self._python_marker = AnyMarker()

        self.platform = None
        self.marker = AnyMarker()

        self.root_dir = None

        self.develop = True
Example #24
0
def format_python_constraint(
    constraint,
):  # type: (Union[Version, VersionUnion, "VersionConstraint"]) -> str
    """
    This helper will help in transforming
    disjunctive constraint into proper constraint.
    """
    if isinstance(constraint, Version):
        if constraint.precision >= 3:
            return "=={}".format(str(constraint))

        # Transform 3.6 or 3
        if constraint.precision == 2:
            # 3.6
            constraint = parse_constraint("~{}.{}".format(
                constraint.major, constraint.minor))
        else:
            constraint = parse_constraint("^{}.0".format(constraint.major))

    if not isinstance(constraint, VersionUnion):
        return str(constraint)

    formatted = []
    accepted = []

    for version in PYTHON_VERSION:
        version_constraint = parse_constraint(version)
        matches = constraint.allows_any(version_constraint)
        if not matches:
            formatted.append("!=" + version)
        else:
            accepted.append(version)

    # Checking lower bound
    low = accepted[0]

    formatted.insert(0, ">=" + ".".join(low.split(".")[:2]))

    return ", ".join(formatted)
Example #25
0
    def get_update_status(self, latest, package):
        from poetry.core.semver import parse_constraint

        if latest.full_pretty_version == package.full_pretty_version:
            return "up-to-date"

        constraint = parse_constraint("^" + package.pretty_version)

        if latest.version and constraint.allows(latest.version):
            # It needs an immediate semver-compliant upgrade
            return "semver-safe-update"

        # it needs an upgrade but has potential BC breaks so is not urgent
        return "update-possible"
Example #26
0
    def __init__(
        self,
        name,
        version,
        pretty_version=None
    ):  # type: (str, Union[str, VersionRange], Optional[str]) -> None
        super(ProjectPackage, self).__init__(name, version, pretty_version)

        self.build_config = dict()
        self.packages = []
        self.include = []
        self.exclude = []
        self.custom_urls = {}

        if self._python_versions == "*":
            self._python_constraint = parse_constraint("~2.7 || >=3.4")
Example #27
0
    def base_pep_508_name(self):  # type: () -> str
        requirement = self.pretty_name

        if self.extras:
            requirement += "[{}]".format(",".join(self.extras))

        if isinstance(self.constraint, VersionUnion):
            if self.constraint.excludes_single_version():
                requirement += " ({})".format(str(self.constraint))
            else:
                constraints = self.pretty_constraint.split(",")
                constraints = [parse_constraint(c) for c in constraints]
                constraints = [str(c) for c in constraints]
                requirement += " ({})".format(",".join(constraints))
        elif isinstance(self.constraint, Version):
            requirement += " (=={})".format(self.constraint.text)
        elif not self.constraint.is_any():
            requirement += " ({})".format(str(self.constraint).replace(" ", ""))

        return requirement
Example #28
0
 def supports_python2(self):
     return self._package.python_constraint.allows_any(
         parse_constraint(">=2.0.0 <3.0.0"))
Example #29
0
    def handle(self) -> int:
        from tomlkit import inline_table

        from poetry.core.semver import parse_constraint

        packages = self.argument("name")
        is_dev = self.option("dev")

        if self.option("extras") and len(packages) > 1:
            raise ValueError("You can only specify one package "
                             "when using the --extras option")

        section = "dependencies"
        if is_dev:
            section = "dev-dependencies"

        original_content = self.poetry.file.read()
        content = self.poetry.file.read()
        poetry_content = content["tool"]["poetry"]

        if section not in poetry_content:
            poetry_content[section] = {}

        existing_packages = self.get_existing_packages_from_input(
            packages, poetry_content, section)

        if existing_packages:
            self.notify_about_existing_packages(existing_packages)

        packages = [name for name in packages if name not in existing_packages]

        if not packages:
            self.line("Nothing to add.")
            return 0

        requirements = self._determine_requirements(
            packages,
            allow_prereleases=self.option("allow-prereleases"),
            source=self.option("source"),
        )

        for _constraint in requirements:
            if "version" in _constraint:
                # Validate version constraint
                parse_constraint(_constraint["version"])

            constraint = inline_table()
            for name, value in _constraint.items():
                if name == "name":
                    continue

                constraint[name] = value

            if self.option("optional"):
                constraint["optional"] = True

            if self.option("allow-prereleases"):
                constraint["allow-prereleases"] = True

            if self.option("extras"):
                extras = []
                for extra in self.option("extras"):
                    if " " in extra:
                        extras += [e.strip() for e in extra.split(" ")]
                    else:
                        extras.append(extra)

                constraint["extras"] = self.option("extras")

            if self.option("python"):
                constraint["python"] = self.option("python")

            if self.option("platform"):
                constraint["platform"] = self.option("platform")

            if self.option("source"):
                constraint["source"] = self.option("source")

            if len(constraint) == 1 and "version" in constraint:
                constraint = constraint["version"]

            poetry_content[section][_constraint["name"]] = constraint

        try:
            # Write new content
            self.poetry.file.write(content)

            # Cosmetic new line
            self.line("")

            # Update packages
            self.reset_poetry()

            self._installer.set_package(self.poetry.package)
            self._installer.dry_run(self.option("dry-run"))
            self._installer.verbose(self._io.is_verbose())
            self._installer.update(True)
            if self.option("lock"):
                self._installer.lock()

            self._installer.whitelist([r["name"] for r in requirements])

            status = self._installer.run()
        except BaseException:
            # Using BaseException here as some exceptions, eg: KeyboardInterrupt, do not inherit from Exception
            self.poetry.file.write(original_content)
            raise

        if status != 0 or self.option("dry-run"):
            # Revert changes
            if not self.option("dry-run"):
                self.line_error(
                    "\n"
                    "<error>Failed to add packages, reverting the pyproject.toml file "
                    "to its original content.</error>")

            self.poetry.file.write(original_content)

        return status
Example #30
0
    def find_packages(self, dependency: Dependency) -> List[Package]:
        """
        Find packages on the remote server.
        """
        constraint = dependency.constraint
        if constraint is None:
            constraint = "*"

        if not isinstance(constraint, VersionConstraint):
            constraint = parse_constraint(constraint)

        allow_prereleases = dependency.allows_prereleases()
        if isinstance(constraint, VersionRange):
            if (constraint.max is not None and constraint.max.is_prerelease()
                    or constraint.min is not None
                    and constraint.min.is_prerelease()):
                allow_prereleases = True

        try:
            info = self.get_package_info(dependency.name)
        except PackageNotFound:
            self._log(
                "No packages found for {} {}".format(dependency.name,
                                                     str(constraint)),
                level="debug",
            )
            return []

        packages = []
        ignored_pre_release_packages = []

        for version, release in info["releases"].items():
            if not release:
                # Bad release
                self._log(
                    "No release information found for {}-{}, skipping".format(
                        dependency.name, version),
                    level="debug",
                )
                continue

            try:
                package = Package(info["info"]["name"], version)
            except ParseVersionError:
                self._log(
                    'Unable to parse version "{}" for the {} package, skipping'
                    .format(version, dependency.name),
                    level="debug",
                )
                continue

            if package.is_prerelease() and not allow_prereleases:
                if constraint.is_any():
                    # we need this when all versions of the package are pre-releases
                    ignored_pre_release_packages.append(package)
                continue

            if not constraint or (constraint
                                  and constraint.allows(package.version)):
                packages.append(package)

        self._log(
            "{} packages found for {} {}".format(len(packages),
                                                 dependency.name,
                                                 str(constraint)),
            level="debug",
        )

        return packages or ignored_pre_release_packages