Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: pym/portage/dbapi/
Date: Wed, 28 Feb 2018 18:41:07
Message-Id: 1519838539.e3960e27f1b75120c2c0511b6207bd2ebdcc26a3.zmedico@gentoo
1 commit: e3960e27f1b75120c2c0511b6207bd2ebdcc26a3
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Sun Feb 25 22:27:13 2018 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Wed Feb 28 17:22:19 2018 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=e3960e27
7
8 portdbapi: add async_aux_get method (bug 648790)
9
10 Add async_aux_get method that returns a Future and otherwise
11 behaves identically to aux_get. Use async_aux_get to implement
12 the synchronous aux_get method.
13
14 Bug: https://bugs.gentoo.org/648790
15 Reviewed-by: Alec Warner <antarus <AT> gentoo.org>
16
17 pym/portage/dbapi/porttree.py | 99 ++++++++++++++++++++++++++++++++++---------
18 1 file changed, 78 insertions(+), 21 deletions(-)
19
20 diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py
21 index f5979d2d0..f8ff4833b 100644
22 --- a/pym/portage/dbapi/porttree.py
23 +++ b/pym/portage/dbapi/porttree.py
24 @@ -45,6 +45,7 @@ import traceback
25 import warnings
26 import errno
27 import collections
28 +import functools
29
30 try:
31 from urllib.parse import urlparse
32 @@ -577,11 +578,46 @@ class portdbapi(dbapi):
33 "stub code for returning auxilliary db information, such as SLOT, DEPEND, etc."
34 'input: "sys-apps/foo-1.0",["SLOT","DEPEND","HOMEPAGE"]'
35 'return: ["0",">=sys-libs/bar-1.0","http://www.foo.com"] or raise PortageKeyError if error'
36 + # For external API consumers, self._event_loop returns a new event
37 + # loop on each access, so a local reference is needed in order
38 + # to avoid instantiating more than one.
39 + loop = self._event_loop
40 + return loop.run_until_complete(
41 + self.async_aux_get(mycpv, mylist, mytree=mytree,
42 + myrepo=myrepo, loop=loop))
43 +
44 + def async_aux_get(self, mycpv, mylist, mytree=None, myrepo=None, loop=None):
45 + """
46 + Asynchronous form form of aux_get.
47 +
48 + @param mycpv: cpv for an ebuild
49 + @type mycpv: str
50 + @param mylist: list of metadata keys
51 + @type mylist: list
52 + @param mytree: The canonical path of the tree in which the ebuild
53 + is located, or None for automatic lookup
54 + @type mytree: str
55 + @param myrepo: name of the repo in which the ebuild is located,
56 + or None for automatic lookup
57 + @type myrepo: str
58 + @param loop: event loop (defaults to global event loop)
59 + @type loop: EventLoop
60 + @return: list of metadata values
61 + @rtype: asyncio.Future (or compatible)
62 + """
63 + # Don't default to self._event_loop here, since that creates a
64 + # local event loop for thread safety, and that could easily lead
65 + # to simultaneous instantiation of multiple event loops here.
66 + # Callers of this method certainly want the same event loop to
67 + # be used for all calls.
68 + loop = loop or global_event_loop()
69 + future = loop.create_future()
70 cache_me = False
71 if myrepo is not None:
72 mytree = self.treemap.get(myrepo)
73 if mytree is None:
74 - raise PortageKeyError(myrepo)
75 + future.set_exception(PortageKeyError(myrepo))
76 + return future
77
78 if mytree is not None and len(self.porttrees) == 1 \
79 and mytree == self.porttrees[0]:
80 @@ -596,43 +632,64 @@ class portdbapi(dbapi):
81 mylist).difference(self._aux_cache_keys):
82 aux_cache = self._aux_cache.get(mycpv)
83 if aux_cache is not None:
84 - return [aux_cache.get(x, "") for x in mylist]
85 + future.set_result([aux_cache.get(x, "") for x in mylist])
86 + return future
87 cache_me = True
88
89 try:
90 cat, pkg = mycpv.split("/", 1)
91 except ValueError:
92 # Missing slash. Can't find ebuild so raise PortageKeyError.
93 - raise PortageKeyError(mycpv)
94 + future.set_exception(PortageKeyError(mycpv))
95 + return future
96
97 myebuild, mylocation = self.findname2(mycpv, mytree)
98
99 if not myebuild:
100 writemsg("!!! aux_get(): %s\n" % \
101 _("ebuild not found for '%s'") % mycpv, noiselevel=1)
102 - raise PortageKeyError(mycpv)
103 + future.set_exception(PortageKeyError(mycpv))
104 + return future
105
106 mydata, ebuild_hash = self._pull_valid_cache(mycpv, myebuild, mylocation)
107 - doregen = mydata is None
108 -
109 - if doregen:
110 - if myebuild in self._broken_ebuilds:
111 - raise PortageKeyError(mycpv)
112 -
113 - proc = EbuildMetadataPhase(cpv=mycpv,
114 - ebuild_hash=ebuild_hash, portdb=self,
115 - repo_path=mylocation, scheduler=self._event_loop,
116 - settings=self.doebuild_settings)
117 -
118 - proc.start()
119 - proc.wait()
120
121 + if mydata is not None:
122 + self._aux_get_return(
123 + future, mycpv, mylist, myebuild, ebuild_hash,
124 + mydata, mylocation, cache_me, None)
125 + return future
126 +
127 + if myebuild in self._broken_ebuilds:
128 + future.set_exception(PortageKeyError(mycpv))
129 + return future
130 +
131 + proc = EbuildMetadataPhase(cpv=mycpv,
132 + ebuild_hash=ebuild_hash, portdb=self,
133 + repo_path=mylocation, scheduler=loop,
134 + settings=self.doebuild_settings)
135 +
136 + proc.addExitListener(functools.partial(self._aux_get_return,
137 + future, mycpv, mylist, myebuild, ebuild_hash, mydata, mylocation,
138 + cache_me))
139 + future.add_done_callback(functools.partial(self._aux_get_cancel, proc))
140 + proc.start()
141 + return future
142 +
143 + @staticmethod
144 + def _aux_get_cancel(proc, future):
145 + if future.cancelled() and proc.returncode is None:
146 + proc.cancel()
147 +
148 + def _aux_get_return(self, future, mycpv, mylist, myebuild, ebuild_hash,
149 + mydata, mylocation, cache_me, proc):
150 + if future.cancelled():
151 + return
152 + if proc is not None:
153 if proc.returncode != os.EX_OK:
154 self._broken_ebuilds.add(myebuild)
155 - raise PortageKeyError(mycpv)
156 -
157 + future.set_exception(PortageKeyError(mycpv))
158 + return
159 mydata = proc.metadata
160 -
161 mydata["repository"] = self.repositories.get_name_for_location(mylocation)
162 mydata["_mtime_"] = ebuild_hash.mtime
163 eapi = mydata.get("EAPI")
164 @@ -651,7 +708,7 @@ class portdbapi(dbapi):
165 aux_cache[x] = mydata.get(x, "")
166 self._aux_cache[mycpv] = aux_cache
167
168 - return returnme
169 + future.set_result(returnme)
170
171 def getFetchMap(self, mypkg, useflags=None, mytree=None):
172 """