Add an async_xmatch method, and use it to implement the synchronous
xmatch method. Deprecate unused xmatch method parameters. Use the
compat_coroutine decorator for backward compatibility with python2.7
(via PEP 342 enhanced generators).

Bug: https://bugs.gentoo.org/666940
Suggested-by: Daniel Robbins <drobb...@funtoo.org>
Signed-off-by: Zac Medico <zmed...@gentoo.org>
---
 lib/portage/dbapi/porttree.py | 62 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 51 insertions(+), 11 deletions(-)

diff --git a/lib/portage/dbapi/porttree.py b/lib/portage/dbapi/porttree.py
index 56955ec34..fc2980cdb 100644
--- a/lib/portage/dbapi/porttree.py
+++ b/lib/portage/dbapi/porttree.py
@@ -37,6 +37,7 @@ from portage import _unicode_encode
 from portage import OrderedDict
 from portage.util._eventloop.EventLoop import EventLoop
 from portage.util.futures import asyncio
+from portage.util.futures.compat_coroutine import coroutine, coroutine_return
 from portage.util.futures.iter_completed import iter_gather
 from _emerge.EbuildMetadataPhase import EbuildMetadataPhase
 
@@ -1055,8 +1056,41 @@ class portdbapi(dbapi):
                self._better_cache = None
                self.frozen = 0
 
-       def xmatch(self,level,origdep,mydep=None,mykey=None,mylist=None):
-               "caching match function; very trick stuff"
+       def xmatch(self, level, origdep, mydep=DeprecationWarning,
+               mykey=DeprecationWarning, mylist=DeprecationWarning):
+               """
+               Caching match function.
+
+               @param level: xmatch level (bestmatch-visible, 
match-all-cpv-only
+                       match-allmatch-visible, minimum-all, 
minimum-all-ignore-profile,
+                       or minimum-visible)
+               @type level: str
+               @param origdep: dependency to match (may omit category)
+               @type origdep: portage.dep.Atom or str
+               @return: match result(s)
+               @rtype: _pkg_str or list of _pkg_str (depends on level)
+               """
+               loop = self._event_loop
+               return loop.run_until_complete(
+                       self.async_xmatch(level, origdep, mydep=mydep, 
loop=loop))
+
+       @coroutine
+       def async_xmatch(self, level, origdep, mydep=DeprecationWarning, 
loop=None):
+               """
+               Asynchronous form form of xmatch.
+
+               @param level: xmatch level (bestmatch-visible, 
match-all-cpv-only
+                       match-allmatch-visible, minimum-all, 
minimum-all-ignore-profile,
+                       or minimum-visible)
+               @type level: str
+               @param origdep: dependency to match (may omit category)
+               @type origdep: portage.dep.Atom or str
+               @param loop: event loop (defaults to global event loop)
+               @type loop: EventLoop
+               @return: match result(s)
+               @rtype: asyncio.Future (or compatible), which results in a 
_pkg_str
+                       or list of _pkg_str (depends on level)
+               """
                if level == "list-visible":
                        level = "match-visible"
                        warnings.warn("The 'list-visible' mode of "
@@ -1064,21 +1098,25 @@ class portdbapi(dbapi):
                                "has been renamed to match-visible",
                                DeprecationWarning, stacklevel=2)
 
-               if mydep is None:
-                       #this stuff only runs on first call of xmatch()
-                       #create mydep, mykey from origdep
-                       mydep = dep_expand(origdep, mydb=self, 
settings=self.settings)
-                       mykey = mydep.cp
+               if mydep is not DeprecationWarning:
+                       warnings.warn("The 'mydep' parameter of "
+                               "portage.dbapi.porttree.portdbapi.xmatch"
+                               " is deprecated and ignored",
+                               DeprecationWarning, stacklevel=2)
+
+               mydep = dep_expand(origdep, mydb=self, settings=self.settings)
+               mykey = mydep.cp
 
                #if no updates are being made to the tree, we can consult our 
xcache...
                cache_key = None
                if self.frozen:
                        cache_key = (mydep, mydep.unevaluated_atom)
                        try:
-                               return self.xcache[level][cache_key][:]
+                               
coroutine_return(self.xcache[level][cache_key][:])
                        except KeyError:
                                pass
 
+               loop = asyncio._wrap_loop(loop)
                myval = None
                mytree = None
                if mydep.repo is not None:
@@ -1131,12 +1169,14 @@ class portdbapi(dbapi):
 
                        for cpv in iterfunc(mylist):
                                        try:
-                                               metadata = dict(zip(aux_keys,
-                                                       self.aux_get(cpv, 
aux_keys, myrepo=cpv.repo)))
+                                               metadata_list = yield 
self.async_aux_get(cpv,
+                                                       aux_keys, 
myrepo=cpv.repo, loop=loop)
                                        except KeyError:
                                                # ebuild not in this repo, or 
masked by corruption
                                                continue
 
+                                       metadata = dict(zip(aux_keys, 
metadata_list))
+
                                        try:
                                                pkg_str = _pkg_str(cpv, 
metadata=metadata,
                                                        settings=self.settings, 
db=self)
@@ -1176,7 +1216,7 @@ class portdbapi(dbapi):
                                if not isinstance(myval, _pkg_str):
                                        myval = myval[:]
 
-               return myval
+               coroutine_return(myval)
 
        def match(self, mydep, use_cache=1):
                return self.xmatch("match-visible", mydep)
-- 
2.16.4


Reply via email to