Пример #1
0
    def test_parsing(self):
        # check for gentoo bug 263787
        self.process_pkg(False, 'app-text', 'foo-123-bar')
        self.process_ver(False, 'app-text', 'foo-123-bar', '2.0017a_p', '-r5')
        with pytest.raises(cpv.InvalidCPV):
            cpv.UnversionedCPV('app-text/foo-123')
        for cat_ret, cats in [[False, self.good_cats], [True, self.bad_cats]]:
            for cat in cats:
                for pkg_ret, pkgs in [[False, self.good_pkgs],
                                      [True, self.bad_pkgs]]:
                    for pkg in pkgs:
                        self.process_pkg(cat_ret or pkg_ret, cat, pkg)

        for cp in self.good_cp:
            cat, pkg = cp.rsplit("/", 1)
            for rev_ret, revs in [[False, self.good_revs],
                                  [True, self.bad_revs]]:
                for rev in revs:
                    for ver_ret, vers in [[False, self.good_vers],
                                          [True, self.bad_vers]]:
                        for ver in vers:
                            self.process_ver(ver_ret or rev_ret, cat, pkg, ver,
                                             rev)

        for x in (10, 18, 19, 36, 100):
            assert cpv.CPV("da", "ba", f"1-r0{'0' * x}").revision == 0
            assert \
                int(cpv.CPV("da", "ba", f"1-r1{'0' * x}1").revision) == int(f"1{'0' * x}1")
Пример #2
0
    def test_r0_revisions(self):
        # single '0'
        obj = cpv.CPV("dev-util/diffball-1.0-r0", versioned=True)
        assert obj.cpvstr == "dev-util/diffball-1.0"
        assert str(obj) == "dev-util/diffball-1.0"
        assert obj.fullver == "1.0-r0"
        assert obj.revision == 0

        # multiple '0'
        obj = cpv.CPV("dev-util/diffball-1.0-r000", versioned=True)
        assert obj.cpvstr == "dev-util/diffball-1.0"
        assert str(obj) == "dev-util/diffball-1.0"
        assert obj.fullver == "1.0-r000"
        assert obj.revision == 0

        # single '0' prefix
        obj = cpv.CPV("dev-util/diffball-1.0-r01", versioned=True)
        assert obj.cpvstr == "dev-util/diffball-1.0-r1"
        assert str(obj) == "dev-util/diffball-1.0-r1"
        assert obj.fullver == "1.0-r01"
        assert obj.revision == 1

        # multiple '0' prefixes
        obj = cpv.CPV("dev-util/diffball-1.0-r0001", versioned=True)
        assert obj.cpvstr == "dev-util/diffball-1.0-r1"
        assert str(obj) == "dev-util/diffball-1.0-r1"
        assert obj.fullver == "1.0-r0001"
        assert obj.revision == 1
Пример #3
0
def parse_pv(repo, text):
    """Return a CPV instance from either a cpv or a pv string.

    If a pv is passed it needs to match a single cpv in repo.
    """
    try:
        return cpv.CPV.versioned(text)
    except errors.InvalidCPV:
        restrict = parse_match('=%s' % (text, ))
        result = None
        for match in repo.itermatch(restrict):
            if result is not None:
                raise ParseError('multiple matches for %s (%s, %s)' %
                                 (text, result.cpvstr, match.cpvstr))
            result = match
        if result is None:
            raise ParseError('no matches for %s' % (text, ))
        return cpv.CPV(result.category, result.package, result.version)
Пример #4
0
def native_init(self, atom, negate_vers=False, eapi=-1):
    """
    :param atom: string, see gentoo ebuild atom syntax
    :keyword negate_vers: boolean controlling whether the version should be
        inverted for restriction matching
    :keyword eapi: string/int controlling what eapi to enforce for this atom
    """
    sf = object.__setattr__

    orig_atom = atom

    override_kls = False
    use_start = atom.find("[")
    slot_start = atom.find(":")
    if use_start != -1:
        # use dep
        use_end = atom.find("]", use_start)
        if use_end == -1:
            raise errors.MalformedAtom(orig_atom,
                                       "use restriction isn't completed")
        elif use_end != len(atom) - 1:
            raise errors.MalformedAtom(orig_atom,
                                       "trailing garbage after use dep")
        sf(self, "use", tuple(sorted(atom[use_start + 1:use_end].split(','))))
        for x in self.use:
            # stripped purely for validation reasons
            try:
                if x[-1] in "=?":
                    override_kls = True
                    x = x[:-1]
                    if x[0] == '!':
                        x = x[1:]
                    if x[0] == '-':
                        raise errors.MalformedAtom(
                            orig_atom, "malformed use flag: %s" % x)
                elif x[0] == '-':
                    x = x[1:]

                if x[-1] == ')' and eapi not in (0, 1, 2, 3):
                    # use defaults.
                    if x[-3:] in ("(+)", "(-)"):
                        x = x[:-3]

                if not x:
                    raise errors.MalformedAtom(orig_atom,
                                               'empty use dep detected')
                elif x[0] not in alphanum:
                    raise errors.MalformedAtom(
                        orig_atom,
                        "invalid first char spotted in use dep '%s' (must be alphanumeric)"
                        % x)
                if not valid_use_chars.issuperset(x):
                    raise errors.MalformedAtom(
                        orig_atom, "invalid char spotted in use dep '%s'" % x)
            except IndexError:
                raise errors.MalformedAtom(orig_atom, 'empty use dep detected')
        if override_kls:
            sf(self, '__class__', self._transitive_use_atom)
        atom = atom[0:use_start] + atom[use_end + 1:]
    else:
        sf(self, "use", None)
    if slot_start != -1:
        i2 = atom.find("::", slot_start)
        if i2 != -1:
            repo_id = atom[i2 + 2:]
            if not repo_id:
                raise errors.MalformedAtom(orig_atom,
                                           "repo_id must not be empty")
            elif repo_id[0] in '-':
                raise errors.MalformedAtom(
                    orig_atom,
                    "invalid first char of repo_id '%s' (must not begin with a hyphen)"
                    % repo_id)
            elif not valid_repo_chars.issuperset(repo_id):
                raise errors.MalformedAtom(
                    orig_atom,
                    "repo_id may contain only [a-Z0-9_-/], found %r" %
                    (repo_id, ))
            atom = atom[:i2]
            sf(self, "repo_id", repo_id)
        else:
            sf(self, "repo_id", None)
        # slot dep.
        slot = atom[slot_start + 1:]
        slot_operator = subslot = None
        if not slot:
            # if the slot char came in only due to repo_id, force slots to None
            if i2 == -1:
                raise errors.MalformedAtom(
                    orig_atom, "Empty slot targets aren't allowed")
            slot = None
        else:
            slots = (slot, )
            if eapi not in (0, 1, 2, 3, 4):
                if slot[0:1] in ("*", "="):
                    if len(slot) > 1:
                        raise errors.MalformedAtom(
                            orig_atom,
                            "Slot operators '*' and '=' do not take slot targets"
                        )
                    slot_operator = slot
                    slot, slots = None, ()
                else:
                    if slot.endswith('='):
                        slot_operator = '='
                        slot = slot[:-1]
                    slots = slot.split('/', 1)
            elif eapi == 0:
                raise errors.MalformedAtom(
                    orig_atom, "slot dependencies aren't allowed in EAPI 0")

            for chunk in slots:
                if not chunk:
                    raise errors.MalformedAtom(
                        orig_atom, "Empty slot targets aren't allowed")

                if chunk[0] in '-.':
                    raise errors.MalformedAtom(
                        orig_atom,
                        "Slot targets must not start with a hypen or dot: %r" %
                        chunk)
                elif not valid_slot_chars.issuperset(chunk):
                    raise errors.MalformedAtom(
                        orig_atom,
                        "Invalid character(s) in slot target: %s" % ', '.join(
                            map(
                                repr,
                                sorted(
                                    set(chunk).difference(valid_slot_chars)))))

            if len(slots) == 2:
                slot, subslot = slots

        sf(self, "slot_operator", slot_operator)
        sf(self, "slot", slot)
        sf(self, "subslot", subslot)
        atom = atom[:slot_start]
    else:
        sf(self, "slot_operator", None)
        sf(self, "slot", None)
        sf(self, "subslot", None)
        sf(self, "repo_id", None)

    sf(self, "blocks", atom[0] == "!")
    if self.blocks:
        atom = atom[1:]
        # hackish/slow, but lstrip doesn't take a 'prune this many' arg
        # open to alternatives
        if eapi not in (0, 1) and atom.startswith("!"):
            atom = atom[1:]
            sf(self, "blocks_strongly", True)
        else:
            sf(self, "blocks_strongly", False)
    else:
        sf(self, "blocks_strongly", False)

    if atom[0] in ('<', '>'):
        if atom[1] == '=':
            sf(self, 'op', atom[:2])
            atom = atom[2:]
        else:
            sf(self, 'op', atom[0])
            atom = atom[1:]
    elif atom[0] == '=':
        if atom[-1] == '*':
            sf(self, 'op', '=*')
            atom = atom[1:-1]
        else:
            atom = atom[1:]
            sf(self, 'op', '=')
    elif atom[0] == '~':
        sf(self, 'op', '~')
        atom = atom[1:]
    else:
        sf(self, 'op', '')
    sf(self, 'cpvstr', atom)

    if eapi == 0:
        for x in ('use', 'slot'):
            if getattr(self, x) is not None:
                raise errors.MalformedAtom(
                    orig_atom, "%s atoms aren't supported for EAPI 0" % x)
    elif eapi == 1:
        if self.use is not None:
            raise errors.MalformedAtom(
                orig_atom, "use atoms aren't supported for EAPI < 2")
    if eapi != -1:
        if self.repo_id is not None:
            raise errors.MalformedAtom(
                orig_atom, "repo_id atoms aren't supported for EAPI %i" % eapi)
    if use_start != -1 and slot_start != -1 and use_start < slot_start:
        raise errors.MalformedAtom(orig_atom,
                                   "slot restriction must proceed use")
    try:
        c = cpv.CPV(self.cpvstr, versioned=bool(self.op))
    except errors.InvalidCPV as e:
        raise_from(errors.MalformedAtom(orig_atom))
    sf(self, "key", c.key)
    sf(self, "package", c.package)
    sf(self, "category", c.category)
    sf(self, "version", c.version)
    sf(self, "fullver", c.fullver)
    sf(self, "revision", c.revision)

    if self.op:
        if self.version is None:
            raise errors.MalformedAtom(orig_atom,
                                       "operator requires a version")
        elif self.op == '~' and self.revision:
            raise errors.MalformedAtom(
                orig_atom,
                "~ revision operater cannot be combined with a revision")
    elif self.version is not None:
        raise errors.MalformedAtom(orig_atom,
                                   'versioned atom requires an operator')
    sf(self, "_hash", hash(orig_atom))
    sf(self, "negate_vers", negate_vers)
Пример #5
0
 def test_init(self):
     cpv.CPV("dev-util", "diffball", "0.7.1")
     cpv.CPV("dev-util", "diffball")
     cpv.CPV("dev-util/diffball-0.7.1", versioned=True)
     with pytest.raises(TypeError):
         cpv.VersionedCPV("dev-util", "diffball", None)
Пример #6
0
 def make_inst(self, cat, pkg, fullver=""):
     if self.testing_secondary_args:
         return cpv.CPV(cat, pkg, fullver, versioned=bool(fullver))
     if fullver:
         return cpv.VersionedCPV(f"{cat}/{pkg}-{fullver}")
     return cpv.UnversionedCPV(f"{cat}/{pkg}")