iter_owners: event loop for spinner, bug #461412
authorZac Medico <zmedico@gentoo.org>
Wed, 13 Mar 2013 05:56:43 +0000 (22:56 -0700)
committerZac Medico <zmedico@gentoo.org>
Wed, 13 Mar 2013 05:56:43 +0000 (22:56 -0700)
pym/_emerge/depgraph.py
pym/_emerge/stdout_spinner.py
pym/portage/dbapi/vartree.py

index 7e3a0eb1a49143e486a42f77d3b2fd3bda55ac0c..dfef6a76cd7b52c8e317c4d1e62307567f5c820e 100644 (file)
@@ -41,6 +41,8 @@ from portage.util import ensure_dirs
 from portage.util import writemsg_level, write_atomic
 from portage.util.digraph import digraph
 from portage.util._async.TaskScheduler import TaskScheduler
+from portage.util._eventloop.EventLoop import EventLoop
+from portage.util._eventloop.global_event_loop import global_event_loop
 from portage.versions import catpkgsplit
 
 from _emerge.AtomArg import AtomArg
@@ -518,6 +520,9 @@ class depgraph(object):
                self._select_atoms = self._select_atoms_highest_available
                self._select_package = self._select_pkg_highest_available
 
+               self._event_loop = (portage._internal_caller and
+                       global_event_loop() or EventLoop(main=False))
+
        def _load_vdb(self):
                """
                Load installed package metadata if appropriate. This used to be called
@@ -2594,7 +2599,22 @@ class depgraph(object):
                                        continue
                                yield arg, atom
 
-       def select_files(self, myfiles):
+       def select_files(self, args):
+               # Use the global event loop for spinner progress
+               # indication during file owner lookups (bug #461412).
+               spinner_id = None
+               try:
+                       spinner = self._frozen_config.spinner
+                       if spinner is not None and \
+                               spinner.update is not spinner.update_quiet:
+                               spinner_id = self._event_loop.idle_add(
+                                       self._frozen_config.spinner.update)
+                       return self._select_files(args)
+               finally:
+                       if spinner_id is not None:
+                               self._event_loop.source_remove(spinner_id)
+
+       def _select_files(self, myfiles):
                """Given a list of .tbz2s, .ebuilds sets, and deps, populate
                self._dynamic_config._initial_arg_list and call self._resolve to create the 
                appropriate depgraph and return a favorite list."""
index 5ad31f00174eb1528d1ab42a042ead412adb2010..670686adf75b09113ad83907d06089ae0888ffbd 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 1999-2009 Gentoo Foundation
+# Copyright 1999-2013 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 import platform
@@ -53,17 +53,18 @@ class stdout_spinner(object):
        def update_basic(self):
                self.spinpos = (self.spinpos + 1) % 500
                if self._return_early():
-                       return
+                       return True
                if (self.spinpos % 100) == 0:
                        if self.spinpos == 0:
                                sys.stdout.write(". ")
                        else:
                                sys.stdout.write(".")
                sys.stdout.flush()
+               return True
 
        def update_scroll(self):
                if self._return_early():
-                       return
+                       return True
                if(self.spinpos >= len(self.scroll_sequence)):
                        sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
                                len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
@@ -71,13 +72,15 @@ class stdout_spinner(object):
                        sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
                sys.stdout.flush()
                self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
+               return True
 
        def update_twirl(self):
                self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
                if self._return_early():
-                       return
+                       return True
                sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
                sys.stdout.flush()
+               return True
 
        def update_quiet(self):
-               return
+               return True
index a2fbf86df8bd51651e6173c8f49cbb1df67465f4..f918c2c664aba95251a3ee71605cc028f0929b97 100644 (file)
@@ -1260,18 +1260,35 @@ class vardbapi(dbapi):
                                        name = os.path.basename(path.rstrip(os.path.sep))
                                path_info_list.append((path, name, is_basename))
 
+                       # Do work via the global event loop, so that it can be used
+                       # for indication of progress during the search (bug #461412).
+                       event_loop = (portage._internal_caller and
+                               global_event_loop() or EventLoop(main=False))
                        root = self._vardb._eroot
-                       for cpv in self._vardb.cpv_all():
-                               dblnk =  self._vardb._dblink(cpv)
 
+                       def search_pkg(cpv):
+                               dblnk = self._vardb._dblink(cpv)
                                for path, name, is_basename in path_info_list:
                                        if is_basename:
                                                for p in dblnk.getcontents():
                                                        if os.path.basename(p) == name:
-                                                               yield dblnk, p[len(root):]
+                                                               search_pkg.results.append((dblnk, p[len(root):]))
                                        else:
                                                if dblnk.isowner(path):
-                                                       yield dblnk, path
+                                                       search_pkg.results.append((dblnk, path))
+                               search_pkg.complete = True
+                               return False
+
+                       search_pkg.results = []
+
+                       for cpv in self._vardb.cpv_all():
+                               del search_pkg.results[:]
+                               search_pkg.complete = False
+                               event_loop.idle_add(search_pkg, cpv)
+                               while not search_pkg.complete:
+                                       event_loop.iteration()
+                               for result in search_pkg.results:
+                                       yield result
 
 class vartree(object):
        "this tree will scan a var/db/pkg database located at root (passed to init)"