diff options
author | 2024-01-15 20:50:04 -0800 | |
---|---|---|
committer | 2024-01-23 00:52:08 -0800 | |
commit | 6c1e1f997b0a99954f0eadd7898a368076fb0ea5 (patch) | |
tree | f26581b0365c62ee96d5c4ab76ccba0c1b99f49a | |
parent | refactor: Add missing abstractmethods for ConfiguredTree. (diff) | |
download | pkgcore-6c1e1f997b0a99954f0eadd7898a368076fb0ea5.tar.gz pkgcore-6c1e1f997b0a99954f0eadd7898a368076fb0ea5.tar.bz2 pkgcore-6c1e1f997b0a99954f0eadd7898a368076fb0ea5.zip |
fix filtered.tree.{categories,packages,versions} .
The implementation wasn't properly aliasing _get_* to
the underlying raw_repo, and it should've been filtering
packages and versions according to the filter. This adds that.
This isn't a huge issue, but it breaks API guarantees
for code tring to efficienctly access this sort of info
for a repository stack.
Signed-off-by: Brian Harring <ferringb@gmail.com>
-rw-r--r-- | src/pkgcore/repository/filtered.py | 22 | ||||
-rw-r--r-- | tests/repository/test_filtered.py | 22 |
2 files changed, 43 insertions, 1 deletions
diff --git a/src/pkgcore/repository/filtered.py b/src/pkgcore/repository/filtered.py index 2e700d7e4..81f5b7e7f 100644 --- a/src/pkgcore/repository/filtered.py +++ b/src/pkgcore/repository/filtered.py @@ -5,12 +5,15 @@ filtering repository __all__ = ("tree",) from itertools import filterfalse +import typing -from snakeoil.klass import DirProxy, GetAttrProxy +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 class tree(prototype.tree): @@ -33,6 +36,7 @@ class tree(prototype.tree): self._filterfunc = filter else: self._filterfunc = filterfalse + super().__init__() def itermatch(self, restrict, **kwds): # note that this lets the repo do the initial filtering. @@ -54,6 +58,22 @@ class tree(prototype.tree): 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") diff --git a/tests/repository/test_filtered.py b/tests/repository/test_filtered.py index 312e2528b..7a04c21b9 100644 --- a/tests/repository/test_filtered.py +++ b/tests/repository/test_filtered.py @@ -1,4 +1,5 @@ from pkgcore.ebuild.atom import atom +from pkgcore.ebuild.restricts import CategoryDep from pkgcore.ebuild.cpv import VersionedCPV from pkgcore.repository import filtered from pkgcore.repository.util import SimpleTree @@ -57,3 +58,24 @@ class TestVisibility: ) ) assert sorted(vrepo) == sorted(repo.itermatch(atom("dev-util/bsdiff"))) + + def test_categories_api(self): + # filter to just dev-util/diffball; this confirms that empty categories are filter, + # and that filtering of a package (leaving one in a category still) doesn't filter the category. + _, vrepo = self.setup_repos( + packages.OrRestriction(CategoryDep("dev-lib"), atom("dev-util/bsdiff")) + ) + assert sorted(vrepo.categories) == sorted( + [ + "dev-lib", + "dev-util", + ] + ), "category filtering must not filter dev-lib even if there are no packages left post filtering" + + def test_packages_api(self): + _, vrepo = self.setup_repos(atom("dev-util/diffball")) + assert sorted(vrepo.packages["dev-util"]) == ["bsdiff"] + + def test_versions_api(self): + _, vrepo = self.setup_repos(atom("=dev-util/diffball-1.0")) + assert sorted(vrepo.versions[("dev-util", "diffball")]) == ["0.7"] |