Source code for pkgcore.repository.filtered

"""
filtering repository
"""

__all__ = ("tree",)

from itertools import filterfalse
import typing

from snakeoil.klass import DirProxy, GetAttrProxy, alias_method

from ..operations.repo import operations_proxy
from ..restrictions import restriction
from . import errors, prototype
from pkgcore.ebuild.restricts import CategoryDep
from pkgcore.ebuild.atom import atom


[docs] class tree(prototype.tree): """Filter existing repository based upon passed in restrictions.""" operations_kls = operations_proxy def __init__(self, repo, restrict, sentinel_val=False): self.raw_repo = repo self.sentinel_val = sentinel_val if not hasattr(self.raw_repo, "itermatch"): raise errors.InitializationError( f"{self.raw_repo} is not a repository tree derivative" ) if not isinstance(restrict, restriction.base): raise errors.InitializationError(f"{restrict} is not a restriction") self.restrict = restrict self.raw_repo = repo if sentinel_val: self._filterfunc = filter else: self._filterfunc = filterfalse super().__init__()
[docs] def itermatch(self, restrict, **kwds): # note that this lets the repo do the initial filtering. # better design would to analyze the restrictions, and inspect # the repo, determine what can be done without cost # (determined by repo's attributes) versus what does cost # (metadata pull for example). return self._filterfunc( self.restrict.match, self.raw_repo.itermatch(restrict, **kwds) )
itermatch.__doc__ = prototype.tree.itermatch.__doc__.replace( "@param", "@keyword" ).replace(":keyword restrict:", ":param restrict:") def __len__(self): count = 0 for i in self: count += 1 return count # note: for the _get_* methods they use itermatch which would typically # be a cycle; this class's itermatch is fully reliant on the raw repo # thus no cycle. # TODO: add support for .{category,package,version}.force_regen via custom class. No code relies upon this, # but that functionality missing means the implementation has a known potential for developing a stale cache. _get_categories = alias_method("raw_repo.categories.__iter__") def _get_packages(self, category: str) -> typing.Iterable[str]: for package in self.raw_repo.packages[category]: if any(self.itermatch(atom(f"{category}/{package}"))): yield package def _get_versions(self, catpkg: tuple[str, str]) -> typing.Iterable[str]: return (pkg.fullver for pkg in self.itermatch(atom(f"{catpkg[0]}/{catpkg[1]}"))) __getattr__ = GetAttrProxy("raw_repo") __dir__ = DirProxy("raw_repo") def __getitem__(self, key): v = self.raw_repo[key] if self.restrict.match(v) != self.sentinel_val: raise KeyError(key) return v def __repr__(self): return "<%s raw_repo=%r restrict=%r sentinel=%r @%#8x>" % ( self.__class__.__name__, getattr(self, "raw_repo", "unset"), getattr(self, "restrict", "unset"), getattr(self, "sentinel_val", "unset"), id(self), )