コード例 #1
0
ファイル: test_packages.py プロジェクト: shen390s/pkgcore
 def test_eq(self):
     p = (packages.PackageRestriction('one', values.AlwaysTrue), )
     p2 = (packages.PackageRestriction('one', values.AlwaysFalse), )
     v = values.AlwaysTrue
     v2 = values.AlwaysFalse
     self.assertEqual(packages.Conditional('use', v, p),
                      packages.Conditional('use', v, p))
     self.assertNotEqual(packages.Conditional('use', v2, p),
                         packages.Conditional('use', v, p))
     self.assertNotEqual(packages.Conditional('use', v, p),
                         packages.Conditional('use', v, p2))
     self.assertNotEqual(packages.Conditional('use1', v, p),
                         packages.Conditional('use', v, p))
コード例 #2
0
    def __init__(self, *args, stable_arches_addon=None):
        super().__init__(*args)
        arches = {x.strip().lstrip("~") for x in self.options.stable_arches}

        # stable, then unstable, then file
        self.arch_restricts = {}
        for arch in arches:
            self.arch_restricts[arch] = [
                packages.PackageRestriction(
                    "keywords", values.ContainmentMatch2((arch,))),
                packages.PackageRestriction(
                    "keywords", values.ContainmentMatch2((f"~{arch}",)))
            ]
コード例 #3
0
    def __init__(self, options, arches, *args):
        super(UnstableOnlyReport, self).__init__(options)
        arches = set(x.strip().lstrip("~") for x in options.arches)

        # stable, then unstable, then file
        self.arch_restricts = {}
        for arch in arches:
            self.arch_restricts[arch] = [
                packages.PackageRestriction("keywords",
                                            values.ContainmentMatch(arch)),
                packages.PackageRestriction(
                    "keywords", values.ContainmentMatch("~%s" % arch))
            ]
コード例 #4
0
def parse_maintainer(value):
    """
    Case insensitive Regex match on the combined 'name <email>' bit of
    metadata.xml's maintainer data.
    """
    if value:
        return packages.PackageRestriction(
            'maintainers',
            values.AnyMatch(
                values.UnicodeConversion(
                    values.StrRegex(value.lower(), case_sensitive=False))))
    else:
        # empty string matches packages without a maintainer
        return packages.PackageRestriction('maintainers',
                                           values.EqualityMatch(()))
コード例 #5
0
 def test_collect_all(self):
     prs = [packages.PackageRestriction("category", values.AlwaysTrue)] * 10
     self.assertEqual(
         list(util.collect_package_restrictions(packages.AndRestriction(
                     packages.OrRestriction(), packages.AndRestriction(),
                     *prs))),
         prs)
コード例 #6
0
ファイル: domain.py プロジェクト: ulm/pkgcore
    def _make_keywords_filter(self, default_keys, accept_keywords, incremental=False):
        """Generates a restrict that matches iff the keywords are allowed."""
        if not accept_keywords and not self.profile.keywords:
            return packages.PackageRestriction(
                "keywords", values.ContainmentMatch2(frozenset(default_keys)))

        if self.unstable_arch not in default_keys:
            # stable; thus empty entries == ~arch
            def f(r, v):
                if not v:
                    return r, self.unstable_arch
                return r, v
            data = collapsed_restrict_to_data(
                ((packages.AlwaysTrue, default_keys),),
                (f(*i) for i in accept_keywords))
        else:
            if incremental:
                f = collapsed_restrict_to_data
            else:
                f = non_incremental_collapsed_restrict_to_data
            data = f(((packages.AlwaysTrue, default_keys),), accept_keywords)

        if incremental:
            raise NotImplementedError(self._incremental_apply_keywords_filter)
            #f = self._incremental_apply_keywords_filter
        else:
            f = self._apply_keywords_filter
        return delegate(partial(f, data))
コード例 #7
0
    def generate_intersects_from_pkg_node(self, pkg_node, tag=None):
        arch = pkg_node.get("arch")
        if arch is not None:
            arch = str(arch.strip()).split()
            if not arch or "*" in arch:
                arch = None

        vuln = list(pkg_node.findall("vulnerable"))
        if not vuln:
            return None
        elif len(vuln) > 1:
            vuln_list = [self.generate_restrict_from_range(x) for x in vuln]
            vuln = packages.OrRestriction(*vuln_list)
        else:
            vuln_list = [self.generate_restrict_from_range(vuln[0])]
            vuln = vuln_list[0]
        if arch is not None:
            vuln = packages.AndRestriction(
                vuln,
                packages.PackageRestriction(
                    "keywords", values.ContainmentMatch(all=False, *arch)))
        invuln = (pkg_node.findall("unaffected"))
        if not invuln:
            # wrap it.
            return packages.KeyedAndRestriction(vuln, tag=tag)
        invuln_list = [
            self.generate_restrict_from_range(x, negate=True) for x in invuln
        ]
        invuln = [x for x in invuln_list if x not in vuln_list]
        if not invuln:
            if tag is None:
                return packages.KeyedAndRestriction(vuln, tag=tag)
            return packages.KeyedAndRestriction(vuln, tag=tag)
        return packages.KeyedAndRestriction(vuln, tag=tag, *invuln)
コード例 #8
0
ファイル: glsa.py プロジェクト: chutz/pkgcore
 def generate_restrict_from_range(self, node, negate=False):
     op = str(node.get("range").strip())
     base = str(node.text.strip())
     glob = base.endswith("*")
     if glob:
         base = base[:-1]
     base = cpv.versioned_CPV("cat/pkg-%s" % base)
     restrict = self.op_translate[op.lstrip("r")]
     if op.startswith("r"):
         if glob:
             raise ValueError("glob cannot be used with %s ops" % op)
         elif not base.revision:
             if '=' not in restrict:
                 # this is a non-range.
                 raise ValueError(
                     "range %s version %s is a guaranteed empty set" %
                     (op, str(node.text.strip())))
             return atom_restricts.VersionMatch("~",
                                                base.version,
                                                negate=negate)
         return packages.AndRestriction(
             atom_restricts.VersionMatch("~", base.version),
             atom_restricts.VersionMatch(restrict,
                                         base.version,
                                         rev=base.revision),
             negate=negate)
     if glob:
         return packages.PackageRestriction(
             "fullver", values.StrGlobMatch(base.fullver))
     return atom_restricts.VersionMatch(restrict,
                                        base.version,
                                        rev=base.revision,
                                        negate=negate)
コード例 #9
0
ファイル: test_filtered.py プロジェクト: ulm/pkgcore
    def test_filtering(self):
        repo, vrepo = self.setup_repos()
        a = atom("dev-lib/fake")
        a2 = atom("dev-util/diffball")
        self.assertEqual(
            sorted(vrepo.itermatch(a)), sorted(repo.itermatch(a)))
        self.assertEqual(sorted(vrepo.itermatch(a2)), sorted([]))
        repo, vrepo = self.setup_repos(atom("=dev-util/diffball-1.0"))
        self.assertEqual(
            sorted(vrepo.itermatch(a)), sorted(repo.itermatch(a)))
        self.assertEqual(
            sorted(vrepo.itermatch(a2)),
            sorted([versioned_CPV("dev-util/diffball-0.7")]))
        repo, vrepo = self.setup_repos(packages.PackageRestriction(
            "package", values.OrRestriction(
                *[values.StrExactMatch(x) for x in ("diffball", "fake")])))
        self.assertEqual(
            sorted(vrepo.itermatch(packages.AlwaysTrue)),
            sorted(repo.itermatch(atom("dev-util/bsdiff"))))

        # check sentinel value handling.
        vrepo = filtered.tree(repo, a2, sentinel_val=True)
        self.assertEqual(
            sorted(x.cpvstr for x in vrepo),
            sorted(['dev-util/diffball-0.7', 'dev-util/diffball-1.0']))
コード例 #10
0
ファイル: perl.py プロジェクト: lucianposton/pkgcheck
class PerlCheck(Check):
    """Perl ebuild related checks."""

    _restricted_source = (sources.RestrictionRepoSource,
                          (packages.PackageRestriction(
                              'inherited',
                              values.ContainmentMatch2('perl-module')), ))
    _source = (sources.EbuildFileRepoSource, (), (('source',
                                                   _restricted_source), ))
    known_results = frozenset([MismatchedPerlVersion])

    def __init__(self, *args):
        super().__init__(*args)
        self.dist_version_re = re.compile(
            'DIST_VERSION=(?P<dist_version>\d+(\.\d+)*)\s*\n')
        # Initialize connection with perl script. This is done during
        # __init__() since only one running version of the script is shared
        # between however many scanning processes will be run. Also, it makes
        # it easier to disable this check if required perl deps are missing.
        self.perl = _PerlConnection(self.options)

    def feed(self, pkg):
        match = self.dist_version_re.search(''.join(pkg.lines))
        if match is not None:
            dist_version = match.group('dist_version')
            normalized = self.perl.normalize(dist_version)
            if normalized != pkg.version:
                yield MismatchedPerlVersion(dist_version, normalized, pkg=pkg)
コード例 #11
0
def _caching_grab_virtuals(repo, cache_basedir):
    virtuals = {}
    update = False
    cache = _read_mtime_cache(pjoin(cache_basedir, 'virtuals.cache'))

    existing = _get_mtimes(repo.location)
    for cat, mtime in existing.iteritems():
        d = cache.pop(cat, None)
        if d is not None and long(d[0]) == long(mtime):
            d = _convert_cached_virtuals(d)
            if d is not None:
                _merge_virtuals(virtuals, d)
                continue

        update = True
        _collect_virtuals(virtuals, repo.itermatch(
            packages.PackageRestriction("category",
                values.StrExactMatch(cat))))

    if update or cache:
        _write_mtime_cache(existing, virtuals,
            pjoin(cache_basedir, 'virtuals.cache'))

    defaults = _collect_default_providers(virtuals)
#    _finalize_virtuals(virtuals)
    return defaults, virtuals
コード例 #12
0
ファイル: test_filtered.py プロジェクト: ferringb/pkgcore
 def test_iter(self):
     repo, vrepo = self.setup_repos(
         packages.PackageRestriction(
             "package",
             values.OrRestriction(
                 *[values.StrExactMatch(x) for x in ("diffball", "fake")])))
     assert sorted(vrepo) == sorted(repo.itermatch(atom("dev-util/bsdiff")))
コード例 #13
0
    def restrictions(self):
        # ordering here matters; against 24702 ebuilds for
        # a non matchable atom with package as the first restriction
        # 10 loops, best of 3: 206 msec per loop
        # with category as the first(the obvious ordering)
        # 10 loops, best of 3: 209 msec per loop
        # why?  because category is more likely to collide;
        # at the time of this profiling, there were 151 categories.
        # over 11k packages however.
        r = [restricts.PackageDep(self.package), restricts.CategoryDep(self.category)]

        if self.repo_id is not None:
            r.insert(0, restricts.RepositoryDep(self.repo_id))

        if self.fullver is not None:
            if self.op == '=*':
                r.append(packages.PackageRestriction(
                    "fullver", values.StrGlobMatch(self.fullver)))
            else:
                r.append(restricts.VersionMatch(
                    self.op, self.version, self.revision, negate=self.negate_vers))

        if self.slot is not None:
            r.append(restricts.SlotDep(self.slot))
            if self.subslot is not None:
                r.append(restricts.SubSlotDep(self.subslot))

        if self.use is not None:
            r.extend(restricts._parse_nontransitive_use(self.use))

        return tuple(r)
コード例 #14
0
 def test_itermatch(self):
     imatch = self.ctree.itermatch
     assert sorted(x.cpvstr for x in imatch(packages.AlwaysTrue)) == \
         sorted(self.tree1_list + self.tree2_list)
     p = packages.PackageRestriction("package", values.StrExactMatch("diffball"))
     assert sorted(x.cpvstr for x in imatch(p)) == \
         [y for y in sorted(self.tree1_list + self.tree2_list) if "/diffball" in y]
コード例 #15
0
ファイル: glsa.py プロジェクト: houseofsuns/pkgcore
 def generate_restrict_from_range(self, node, negate=False):
     op = str(node.get("range").strip())
     base = str(node.text.strip())
     glob = base.endswith("*")
     if glob:
         base = base[:-1]
     base = cpv.versioned_CPV("cat/pkg-%s" % base)
     restrict = self.op_translate[op.lstrip("r")]
     if glob:
         if op != "eq":
             raise ValueError("glob cannot be used with %s ops" % op)
         return packages.PackageRestriction(
             "fullver", values.StrGlobMatch(base.fullver))
     if op.startswith("r"):
         if not base.revision:
             if op == "rlt": # rlt -r0 can never match
                 # this is a non-range.
                 raise ValueError(
                     "range %s version %s is a guaranteed empty set" %
                     (op, str(node.text.strip())))
             elif op == "rle": # rle -r0 -> = -r0
                 return atom_restricts.VersionMatch("=", base.version, negate=negate)
             elif op == "rge": # rge -r0 -> ~
                 return atom_restricts.VersionMatch("~", base.version, negate=negate)
             # rgt -r0 passes through to regular ~ + >
         return packages.AndRestriction(
             atom_restricts.VersionMatch("~", base.version),
             atom_restricts.VersionMatch(restrict, base.version, rev=base.revision),
             negate=negate)
     return atom_restricts.VersionMatch(
         restrict, base.version, rev=base.revision, negate=negate)
コード例 #16
0
def parse_maintainer(value):
    """
    Case insensitive Regex match on the combined 'name <email>' bit of
    metadata.xml's maintainer data.
    """
    return packages.PackageRestriction(
        'maintainers',
        values.AnyMatch(
            values.UnicodeConversion(
                values.StrRegex(value.lower(), case_sensitive=False))))
コード例 #17
0
def parse_ownsre(value):
    """Value is a regexp matched against the string form of an fs object.

    This means the object kind is prepended to the path the regexp has
    to match.
    """
    return packages.PackageRestriction(
        'contents',
        values.AnyMatch(
            values.GetAttrRestriction('location', values.StrRegex(value))))
コード例 #18
0
def parse_maintainer_name(value):
    """
    Case insensitive Regex match on the name bit of metadata.xml's
    maintainer data.
    """
    return packages.PackageRestriction(
        'maintainers',
        values.AnyMatch(
            values.GetAttrRestriction(
                'name', values.StrRegex(value.lower(), case_sensitive=False))))
コード例 #19
0
class RequiredUseCheck(Check):
    """REQUIRED_USE validity checks."""

    # only run the check for EAPI 4 and above
    _source = (sources.RestrictionRepoSource, (
        packages.PackageRestriction('eapi', values.GetAttrRestriction(
            'options.has_required_use', values.FunctionRestriction(bool))),))
    required_addons = (addons.UseAddon, addons.ProfileAddon)
    known_results = frozenset([InvalidRequiredUse, RequiredUseDefaults, UnstatedIuse])

    def __init__(self, *args, use_addon, profile_addon):
        super().__init__(*args)
        self.iuse_filter = use_addon.get_filter('required_use')
        self.profiles = profile_addon

    def feed(self, pkg):
        # check REQUIRED_USE for invalid nodes
        _nodes, unstated = self.iuse_filter((str,), pkg, pkg.required_use)
        yield from unstated

        # check both stable/unstable profiles for stable KEYWORDS and only
        # unstable profiles for unstable KEYWORDS
        keywords = []
        for keyword in pkg.sorted_keywords:
            if keyword[0] != '~':
                keywords.append(keyword)
            keywords.append('~' + keyword.lstrip('~'))

        # check USE defaults (pkg IUSE defaults + profile USE) against
        # REQUIRED_USE for all profiles matching a pkg's KEYWORDS
        failures = defaultdict(list)
        for keyword in keywords:
            for profile in sorted(self.profiles.get(keyword, ()), key=attrgetter('name')):
                # skip packages masked by the profile
                if profile.visible(pkg):
                    src = FakeConfigurable(pkg, profile)
                    for node in pkg.required_use.evaluate_depset(src.use):
                        if not node.match(src.use):
                            failures[node].append((src.use, profile.key, profile.name))

        if self.options.verbosity > 0:
            # report all failures with profile info in verbose mode
            for node, profile_info in failures.items():
                for use, keyword, profile in profile_info:
                    yield RequiredUseDefaults(
                        str(node), sorted(use), keyword, profile, pkg=pkg)
        else:
            # only report one failure per REQUIRED_USE node in regular mode
            for node, profile_info in failures.items():
                num_profiles = len(profile_info)
                _use, _keyword, profile = profile_info[0]
                yield RequiredUseDefaults(
                    str(node), profile=profile, num_profiles=num_profiles, pkg=pkg)
コード例 #20
0
def parse_revdep(value):
    """Value should be an atom, packages with deps intersecting that match."""
    try:
        targetatom = atom.atom(value)
    except atom.MalformedAtom as e:
        raise argparser.error(e)
    val_restrict = values.FlatteningRestriction(
        atom.atom,
        values.AnyMatch(values.FunctionRestriction(targetatom.intersects)))
    return packages.OrRestriction(*list(
        packages.PackageRestriction(dep, val_restrict)
        for dep in ('bdepend', 'depend', 'rdepend', 'pdepend')))
コード例 #21
0
    def __init__(self, options, stable_arches=None):
        super().__init__(options)
        arches = frozenset(arch.strip().lstrip("~") for arch in options.stable_arches)
        self.target_arches = frozenset(
            "~%s" % arch.strip().lstrip("~") for arch in arches)

        source_arches = options.source_arches
        if source_arches is None:
            source_arches = options.stable_arches
        self.source_arches = frozenset(
            arch.lstrip("~") for arch in source_arches)
        self.source_filter = packages.PackageRestriction(
            "keywords", values.ContainmentMatch2(self.source_arches))
コード例 #22
0
def revdep_pkgs_finalize(sequence, namespace):
    if not sequence:
        return []
    l = []
    for atom_inst in sequence:
        for repo in namespace.repos:
            l.extend(repo.itermatch(atom_inst))
    # have our pkgs; now build the restrict.
    any_restrict = values.AnyMatch(
        values.FunctionRestriction(partial(_revdep_pkgs_match, tuple(l))))
    r = values.FlatteningRestriction(atom.atom, any_restrict)
    return list(
        packages.PackageRestriction(dep, r)
        for dep in ('bdepend', 'depend', 'rdepend', 'pdepend'))
コード例 #23
0
ファイル: plan.py プロジェクト: austin987/pkgcore
 def generate_mangled_blocker(self, choices, blocker):
     """converts a blocker into a "cannot block ourself" block"""
     # note the second Or clause is a bit loose; allows any version to
     # slip through instead of blocking everything that isn't the
     # parent pkg
     if blocker.category != 'virtual':
         return blocker
     return packages.AndRestriction(
         blocker,
         packages.PackageRestriction("provider.key",
                                     values.StrExactMatch(
                                         choices.current_pkg.key),
                                     negate=True,
                                     ignore_missing=True))
コード例 #24
0
ファイル: test_util.py プロジェクト: pombreda/pkgcore
    def test_collect_specific(self):
        prs = {}
        for x in ("category", "package", "version", "iuse"):
            prs[x] = packages.PackageRestriction(x, values.AlwaysTrue)

        r = packages.AndRestriction(packages.OrRestriction(*prs.values()),
                                    packages.AlwaysTrue)
        for k, v in prs.iteritems():
            self.assertEqual(
                list(util.collect_package_restrictions(r, attrs=[k])), [v])
        r = packages.AndRestriction(packages.OrRestriction(*prs.values()),
                                    *prs.values())
        for k, v in prs.iteritems():
            self.assertEqual(
                list(util.collect_package_restrictions(r, attrs=[k])), [v] * 2)
コード例 #25
0
    def __init__(self, *args, stable_arches_addon=None):
        super().__init__(*args)
        self.all_arches = frozenset(self.options.arches)
        self.stable_arches = frozenset(arch.strip().lstrip("~")
                                       for arch in self.options.stable_arches)
        self.target_arches = frozenset(f'~{arch}'
                                       for arch in self.stable_arches)

        source_arches = self.options.source_arches
        if source_arches is None:
            source_arches = self.options.stable_arches
        self.source_arches = frozenset(
            arch.lstrip("~") for arch in source_arches)
        self.source_filter = packages.PackageRestriction(
            "keywords", values.ContainmentMatch2(self.source_arches))
コード例 #26
0
    def generate_restrict_from_range(self, node, negate=False):
        op = str(node.get("range").strip())
        slot = str(node.get("slot", "").strip())

        try:
            restrict = self.op_translate[op.lstrip("r")]
        except KeyError:
            raise ValueError(f'unknown operator: {op!r}')
        if node.text is None:
            raise ValueError(f"{op!r} node missing version")

        base = str(node.text.strip())
        glob = base.endswith("*")
        if glob:
            base = base[:-1]
        base = cpv.VersionedCPV(f"cat/pkg-{base}")

        if glob:
            if op != "eq":
                raise ValueError(f"glob cannot be used with {op} ops")
            return packages.PackageRestriction(
                "fullver", values.StrGlobMatch(base.fullver))
        restrictions = []
        if op.startswith("r"):
            if not base.revision:
                if op == "rlt":  # rlt -r0 can never match
                    # this is a non-range.
                    raise ValueError(
                        "range %s version %s is a guaranteed empty set" %
                        (op, str(node.text.strip())))
                elif op == "rle":  # rle -r0 -> = -r0
                    return atom_restricts.VersionMatch("=",
                                                       base.version,
                                                       negate=negate)
                elif op == "rge":  # rge -r0 -> ~
                    return atom_restricts.VersionMatch("~",
                                                       base.version,
                                                       negate=negate)
            # rgt -r0 passes through to regular ~ + >
            restrictions.append(atom_restricts.VersionMatch("~", base.version))
        restrictions.append(
            atom_restricts.VersionMatch(restrict,
                                        base.version,
                                        rev=base.revision), )
        if slot:
            restrictions.append(atom_restricts.SlotDep(slot))
        return packages.AndRestriction(*restrictions, negate=negate)
コード例 #27
0
class MissingSlotDepCheck(Check):
    """Check for missing slot dependencies."""

    # only run the check for EAPI 5 and above
    _source = (sources.RestrictionRepoSource, (
        packages.PackageRestriction('eapi', values.GetAttrRestriction(
            'options.sub_slotting', values.FunctionRestriction(bool))),))
    required_addons = (addons.UseAddon,)
    known_results = frozenset([MissingSlotDep])

    def __init__(self, *args, use_addon):
        super().__init__(*args)
        self.iuse_filter = use_addon.get_filter()

    def feed(self, pkg):
        rdepend, _ = self.iuse_filter((atom_cls,), pkg, pkg.rdepend)
        depend, _ = self.iuse_filter((atom_cls,), pkg, pkg.depend)

        # skip deps that are blockers or have explicit slots/slot operators
        for dep in (x for x in set(rdepend).intersection(depend) if not
                    (x.blocks or x.slot is not None or x.slot_operator is not None)):
            dep_slots = {x.slot for x in pkg.repo.itermatch(dep.no_usedeps)}
            if len(dep_slots) > 1:
                yield MissingSlotDep(str(dep), sorted(dep_slots), pkg=pkg)
コード例 #28
0
ファイル: parserestrict.py プロジェクト: houseofsuns/pkgcore
def parse_match(text):
    """generate appropriate restriction for text

    Parsing basically breaks it down into chunks split by /, with each
    chunk allowing for prefix/postfix globbing- note that a postfixed
    glob on package token is treated as package attribute matching,
    not as necessarily a version match.

    If only one chunk is found, it's treated as a package chunk.
    Finally, it supports a nonstandard variation of atom syntax where
    the category can be dropped.

    Examples:

    - `*`: match all
    - `dev-*/*`: category must start with 'dev-'
    - `dev-*`: package must start with 'dev-'
    - `*-apps/portage*`: category must end in '-apps', package must start with
      'portage'
    - `>=portage-2.1`: atom syntax, package 'portage', version greater then or
      equal to '2.1'
    - dev-qt/*:5: all Qt 5 libs
    - boost:0/1.60: all packages named boost with a slot/subslot of 0/1.60.0

    :param text: string to attempt to parse
    :type text: string
    :return: :obj:`pkgcore.restrictions.packages` derivative
    """

    # Ensure the text var is a string if we're under py3k.
    if not is_py3k:
        text = text.encode('ascii')
    orig_text = text = text.strip()
    if "!" in text:
        raise ParseError(
            "'!' or any form of blockers make no sense in this usage: '%s'" %
            (text, ))

    restrictions = []
    if '::' in text:
        text, repo_id = text.rsplit('::', 1)
        restrictions.append(restricts.RepositoryDep(repo_id))
    if ':' in text:
        text, slot = text.rsplit(':', 1)
        slot, _sep, subslot = slot.partition('/')
        if slot:
            restrictions.append(restricts.SlotDep(slot))
        if subslot:
            restrictions.append(restricts.SubSlotDep(subslot))

    tsplit = text.rsplit("/", 1)
    if len(tsplit) == 1:
        ops, text = collect_ops(text)
        if not ops:
            if "*" in text:
                r = convert_glob(text)
                if r is None:
                    restrictions.append(packages.AlwaysTrue)
                else:
                    restrictions.append(
                        packages.PackageRestriction("package", r))
                if len(restrictions) == 1:
                    return restrictions[0]
                return packages.AndRestriction(*restrictions)
        elif text.startswith("*"):
            raise ParseError(
                "cannot do prefix glob matches with version ops: %s" %
                (orig_text, ))
        # ok... fake category.  whee.
        try:
            r = list(
                collect_package_restrictions(atom.atom(
                    "%scategory/%s" % (ops, text)).restrictions,
                                             attrs=("category", ),
                                             invert=True))
        except errors.MalformedAtom as e:
            e.atom = orig_text
            raise_from(ParseError(str(e)))
        if not restrictions and len(r) == 1:
            return r[0]
        restrictions.extend(r)
        return packages.AndRestriction(*restrictions)
    elif text[0] in "=<>~" or "*" not in text:
        try:
            return atom.atom(orig_text)
        except errors.MalformedAtom as e:
            raise_from(ParseError(str(e)))

    r = map(convert_glob, tsplit)
    if not r[0] and not r[1]:
        restrictions.append(packages.AlwaysTrue)
    elif not r[0]:
        restrictions.append(packages.PackageRestriction("package", r[1]))
    elif not r[1]:
        restrictions.append(packages.PackageRestriction("category", r[0]))
    else:
        restrictions.extend((
            packages.PackageRestriction("category", r[0]),
            packages.PackageRestriction("package", r[1]),
        ))
    if len(restrictions) == 1:
        return restrictions[0]
    return packages.AndRestriction(*restrictions)
コード例 #29
0
ファイル: parserestrict.py プロジェクト: houseofsuns/pkgcore
 def _parse(value):
     return packages.PackageRestriction(
         attr,
         values.ContainmentMatch2(
             values_kls(
                 token_kls(piece.strip()) for piece in value.split(','))))
コード例 #30
0
    def test_identify_candidates(self):
        with pytest.raises(TypeError):
            self.repo.match("asdf")
        rc = packages.PackageRestriction("category",
                                         values.StrExactMatch("dev-util"))
        assert \
            sorted(set(x.package for x in self.repo.itermatch(rc))) == \
            sorted(["diffball", "bsdiff"])
        rp = packages.PackageRestriction("package",
                                         values.StrExactMatch("diffball"))
        assert list(
            x.version
            for x in self.repo.itermatch(rp, sorter=sorted)) == ["0.7", "1.0"]
        assert \
            self.repo.match(packages.OrRestriction(rc, rp), sorter=sorted) == \
            sorted(VersionedCPV(x) for x in (
                "dev-util/diffball-0.7", "dev-util/diffball-1.0",
                "dev-util/bsdiff-0.4.1", "dev-util/bsdiff-0.4.2"))
        assert \
            sorted(self.repo.itermatch(packages.AndRestriction(rc, rp))) == \
            sorted(VersionedCPV(x) for x in (
                "dev-util/diffball-0.7", "dev-util/diffball-1.0"))
        assert sorted(self.repo) == self.repo.match(packages.AlwaysTrue,
                                                    sorter=sorted)
        # mix/match cat/pkg to check that it handles that corner case
        # properly for sorting.
        assert \
            sorted(self.repo, reverse=True) == \
            self.repo.match(packages.OrRestriction(
                rc, rp, packages.AlwaysTrue),
                sorter=partial(sorted, reverse=True))
        rc2 = packages.PackageRestriction("category",
                                          values.StrExactMatch("dev-lib"))
        assert sorted(self.repo.itermatch(packages.AndRestriction(rp,
                                                                  rc2))) == []

        # note this mixes a category level match, and a pkg level
        # match. they *must* be treated as an or.
        assert \
            sorted(self.repo.itermatch(packages.OrRestriction(rp, rc2))) == \
            sorted(VersionedCPV(x) for x in (
                "dev-util/diffball-0.7", "dev-util/diffball-1.0",
                "dev-lib/fake-1.0", "dev-lib/fake-1.0-r1"))

        # this is similar to the test above, but mixes a cat/pkg
        # candidate with a pkg candidate
        rp2 = packages.PackageRestriction("package",
                                          values.StrExactMatch("fake"))
        r = packages.OrRestriction(atom("dev-util/diffball"), rp2)
        assert \
            sorted(self.repo.itermatch(r)) == \
            sorted(VersionedCPV(x) for x in (
                "dev-util/diffball-0.7", "dev-util/diffball-1.0",
                "dev-lib/fake-1.0", "dev-lib/fake-1.0-r1"))

        assert \
            sorted(self.repo.itermatch(
                packages.OrRestriction(packages.AlwaysTrue, rp2))) == \
            sorted(VersionedCPV(x) for x in (
                "dev-util/diffball-0.7", "dev-util/diffball-1.0",
                "dev-util/bsdiff-0.4.1", "dev-util/bsdiff-0.4.2",
                "dev-lib/fake-1.0", "dev-lib/fake-1.0-r1"))

        assert \
            sorted(self.repo.itermatch(packages.PackageRestriction(
                'category', values.StrExactMatch('dev-util', negate=True)))) == \
            sorted(VersionedCPV(x) for x in ("dev-lib/fake-1.0", "dev-lib/fake-1.0-r1"))

        obj = malleable_obj(livefs=False)
        pkg_cls = post_curry(MutatedPkg, {'repo': obj})
        assert \
            sorted(self.repo.itermatch(boolean.AndRestriction(boolean.OrRestriction(
                packages.PackageRestriction(
                    "repo.livefs", values.EqualityMatch(False)),
                packages.PackageRestriction(
                    "category", values.StrExactMatch("virtual"))),
                atom("dev-lib/fake")),
                pkg_cls=pkg_cls)) == \
            sorted(VersionedCPV(x) for x in (
                "dev-lib/fake-1.0", "dev-lib/fake-1.0-r1"))

        assert \
            sorted(self.repo.itermatch(packages.PackageRestriction(
                'category', values.StrExactMatch('dev-lib', negate=True),
                negate=True))) == \
            sorted(VersionedCPV(x) for x in (
                "dev-lib/fake-1.0", "dev-lib/fake-1.0-r1"))

        assert \
            sorted(self.repo.itermatch(packages.PackageRestriction(
                'category', values.StrExactMatch('dev-lib', negate=True), negate=True))) == \
            sorted(VersionedCPV(x) for x in (
                "dev-lib/fake-1.0", "dev-lib/fake-1.0-r1"))