dbapi: construct _pkg_str during match on-demand
authorZac Medico <zmedico@gentoo.org>
Tue, 12 Jun 2012 06:40:52 +0000 (23:40 -0700)
committerZac Medico <zmedico@gentoo.org>
Tue, 12 Jun 2012 06:40:52 +0000 (23:40 -0700)
pym/portage/dbapi/__init__.py
pym/portage/dbapi/porttree.py

index a90d59e77634ab38210f3770e1e8973b11c0e7b2..2ab7dc5b66188de405657b3ca498d46d44ee9cb9 100644 (file)
@@ -16,6 +16,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
 
 from portage import os
 from portage import auxdbkeys
+from portage.exception import InvalidData
 from portage.localization import _
 
 class dbapi(object):
@@ -24,6 +25,8 @@ class dbapi(object):
        _use_mutable = False
        _known_keys = frozenset(x for x in auxdbkeys
                if not x.startswith("UNUSED_0"))
+       _pkg_str_aux_keys = ("EAPI", "SLOT", "repository")
+
        def __init__(self):
                pass
 
@@ -125,29 +128,53 @@ class dbapi(object):
 
        def _iter_match(self, atom, cpv_iter):
                cpv_iter = iter(match_from_list(atom, cpv_iter))
+               if atom.repo:
+                       cpv_iter = self._iter_match_repo(atom, cpv_iter)
                if atom.slot:
                        cpv_iter = self._iter_match_slot(atom, cpv_iter)
                if atom.unevaluated_atom.use:
                        cpv_iter = self._iter_match_use(atom, cpv_iter)
-               if atom.repo:
-                       cpv_iter = self._iter_match_repo(atom, cpv_iter)
                return cpv_iter
 
+       def _pkg_str(self, cpv, repo):
+               """
+               This is used to contruct _pkg_str instances on-demand during
+               matching. If cpv is a _pkg_str instance with slot attribute,
+               then simply return it. Otherwise, fetch metadata and construct
+               a _pkg_str instance. This may raise KeyError or InvalidData.
+               """
+               try:
+                       cpv.slot
+               except AttributeError:
+                       pass
+               else:
+                       return cpv
+
+               metadata = dict(zip(self._pkg_str_aux_keys,
+                       self.aux_get(cpv, self._pkg_str_aux_keys, myrepo=repo)))
+
+               return _pkg_str(cpv, slot=metadata["SLOT"],
+                       repo=metadata["repository"], eapi=metadata["EAPI"])
+
        def _iter_match_repo(self, atom, cpv_iter):
                for cpv in cpv_iter:
                        try:
-                               if self.aux_get(cpv, ["repository"], myrepo=atom.repo)[0] == atom.repo:
-                                       yield cpv
-                       except KeyError:
-                               continue
+                               pkg_str = self._pkg_str(cpv, atom.repo)
+                       except (KeyError, InvalidData):
+                               pass
+                       else:
+                               if pkg_str.repo == atom.repo:
+                                       yield pkg_str
 
        def _iter_match_slot(self, atom, cpv_iter):
                for cpv in cpv_iter:
                        try:
-                               if self.aux_get(cpv, ["SLOT"], myrepo=atom.repo)[0] == atom.slot:
-                                       yield cpv
-                       except KeyError:
-                               continue
+                               pkg_str = self._pkg_str(cpv, atom.repo)
+                       except (KeyError, InvalidData):
+                               pass
+                       else:
+                               if pkg_str.slot == atom.slot:
+                                       yield pkg_str
 
        def _iter_match_use(self, atom, cpv_iter):
                """
index c5ee7707bcb5f0f12d9c2073d2bbace6cd608f86..df681152c7e659626d1a583bf634afcdea1d6dfe 100644 (file)
@@ -22,7 +22,8 @@ from portage.cache.cache_errors import CacheError
 from portage.cache.mappings import Mapping
 from portage.dbapi import dbapi
 from portage.exception import PortageException, \
-       FileNotFound, InvalidAtom, InvalidDependString, InvalidPackageName
+       FileNotFound, InvalidAtom, InvalidData, \
+       InvalidDependString, InvalidPackageName
 from portage.localization import _
 
 from portage import eclass_cache, \
@@ -825,18 +826,24 @@ class portdbapi(dbapi):
                                                # ebuild not in this repo, or masked by corruption
                                                continue
 
-                                       if visibility_filter and not self._visible(cpv, metadata):
+                                       try:
+                                               pkg_str = _pkg_str(cpv, slot=metadata["SLOT"],
+                                                       repo=metadata["repository"], eapi=metadata["EAPI"])
+                                       except InvalidData:
+                                               continue
+
+                                       if visibility_filter and not self._visible(pkg_str, metadata):
                                                continue
 
                                        if mydep.slot is not None and \
-                                               mydep.slot != metadata["SLOT"]:
+                                               mydep.slot != pkg_str.slot:
                                                continue
 
                                        if mydep.unevaluated_atom.use is not None and \
-                                               not self._match_use(mydep, cpv, metadata):
+                                               not self._match_use(mydep, pkg_str, metadata):
                                                continue
 
-                                       myval.append(cpv)
+                                       myval.append(pkg_str)
                                        # only yield a given cpv once
                                        break