commit:     1a00ddf5fb089724a127c8dc72d63f10ae72abbf
Author:     Alexander Berntsen <bernalex <AT> gentoo <DOT> org>
AuthorDate: Thu May  8 15:47:58 2014 +0000
Commit:     Alexander Berntsen <bernalex <AT> gentoo <DOT> org>
CommitDate: Sat Jun 14 20:49:14 2014 +0000
URL:        
http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=1a00ddf5

emerge: Implement "--alert"

Implement "--alert" (short option "-A"), which adds a terminal bell
character ('\a') to all prompts, when it is set to True or "y". It may
be used without an option, like e.g. --ask, to mean True.

The patch refactors userquery to a class, UserQuery, to accommodate
--alert. It also adds the option to the emerge man page.

A quick example is to do 'emerge -PAc portage'.

If you have your terminal emulator set up to make '\a' into a window
manager urgency hint, move your cursor to a different window to get the
effect. 'sleep 2 && emerge' is another way to test this.

The --alert option is especially useful if you, like me, tend to fire up
a big world update when you get to the office in the morning (or night),
and then immediately change your focus to something else. If you now do
'emerge -auAD world', emerge will courteously point out when it has
finished calculating the graph, and again when it has finished emerging.

Signed-off-by: Alexander Berntsen <bernalex <AT> gentoo.org>

---
 man/emerge.1             |  5 ++++
 pym/_emerge/UserQuery.py | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
 pym/_emerge/actions.py   | 19 ++++++++-----
 pym/_emerge/depgraph.py  |  9 ++++--
 pym/_emerge/main.py      | 13 +++++++++
 pym/_emerge/unmerge.py   |  5 ++--
 pym/_emerge/userquery.py | 55 -------------------------------------
 7 files changed, 110 insertions(+), 67 deletions(-)

diff --git a/man/emerge.1 b/man/emerge.1
index abb0ed8..bbcf569 100644
--- a/man/emerge.1
+++ b/man/emerge.1
@@ -297,6 +297,11 @@ re\-distributable. With default
 configuration, this would result in an effective
 \fBACCEPT_RESTRICT\fR value of "* -bindist".
 .TP
+.BR "\-\-alert "
+Add a terminal bell character ('\\a') to all interactive prompts. This is
+especially useful if dependency resolution is taking a long time, and
+you want emerge to alert you when it is finished.
+.TP
 .BR "\-\-alphabetical "
 When displaying USE and other flag output, combines the enabled and
 disabled lists into one list and sorts the whole list alphabetically.

diff --git a/pym/_emerge/UserQuery.py b/pym/_emerge/UserQuery.py
new file mode 100644
index 0000000..c866a0d
--- /dev/null
+++ b/pym/_emerge/UserQuery.py
@@ -0,0 +1,71 @@
+# Copyright 1999-2014 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from __future__ import print_function
+
+import signal
+import sys
+
+from portage.output import bold, create_color_func
+
+
+class UserQuery(object):
+       """The UserQuery class is used to prompt the user with a set of 
responses,
+       as well as accepting and handling the responses."""
+
+       def __init__(self, myopts):
+               self.myopts = myopts
+
+       def query(self, prompt, enter_invalid, responses=None, colours=None):
+               """Display a prompt and a set of responses, then waits for user 
input
+               and check it against the responses. The first match is returned.
+
+               An empty response will match the first value in the list of 
responses,
+               unless enter_invalid is True. The input buffer is *not* cleared 
prior
+               to the prompt!
+
+               prompt: The String to display as a prompt.
+               responses: a List of Strings with the acceptable responses.
+               colours: a List of Functions taking and returning a String, 
used to
+               process the responses for display. Typically these will be 
functions
+               like red() but could be e.g. lambda x: "DisplayString".
+
+               If responses is omitted, it defaults to ["Yes", "No"], [green, 
red].
+               If only colours is omitted, it defaults to [bold, ...].
+
+               Returns a member of the List responses. (If called without 
optional
+               arguments, it returns "Yes" or "No".)
+
+               KeyboardInterrupt is converted to SystemExit to avoid 
tracebacks being
+               printed."""
+               if responses is None:
+                       responses = ["Yes", "No"]
+                       colours = [
+                               create_color_func("PROMPT_CHOICE_DEFAULT"),
+                               create_color_func("PROMPT_CHOICE_OTHER")
+                       ]
+               elif colours is None:
+                       colours=[bold]
+               colours=(colours*len(responses))[:len(responses)]
+               if "--alert" in self.myopts:
+                       prompt = '\a' + prompt
+               print(bold(prompt), end=' ')
+               try:
+                       while True:
+                               if sys.hexversion >= 0x3000000:
+                                       
response=input("["+"/".join([colours[i](responses[i])
+                                                                 for i in 
range(len(responses))])+"] ")
+                               else:
+                                       
response=raw_input("["+"/".join([colours[i](responses[i])
+                                                                         for i 
in range(len(responses))])+"] ")
+                               if response or not enter_invalid:
+                                       for key in responses:
+                                               # An empty response will match 
the
+                                               # first value in responses.
+                                               if 
response.upper()==key[:len(response)].upper():
+                                                       return key
+                               print("Sorry, response '%s' not understood." % 
response,
+                 end=' ')
+               except (EOFError, KeyboardInterrupt):
+                       print("Interrupted.")
+                       sys.exit(128 + signal.SIGINT)

diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
index 4ca2f1c..b935139 100644
--- a/pym/_emerge/actions.py
+++ b/pym/_emerge/actions.py
@@ -84,7 +84,7 @@ from _emerge.sync.old_tree_timestamp import 
old_tree_timestamp_warn
 from _emerge.unmerge import unmerge
 from _emerge.UnmergeDepPriority import UnmergeDepPriority
 from _emerge.UseFlagDisplay import pkg_use_display
-from _emerge.userquery import userquery
+from _emerge.UserQuery import UserQuery
 
 if sys.hexversion >= 0x3000000:
        long = int
@@ -387,8 +387,9 @@ def action_build(settings, trees, mtimedb,
                        else:
                                prompt="Would you like to merge these packages?"
                print()
+               uq = UserQuery(myopts)
                if prompt is not None and "--ask" in myopts and \
-                       userquery(prompt, enter_invalid) == "No":
+                       uq.query(prompt, enter_invalid) == "No":
                        print()
                        print("Quitting.")
                        print()
@@ -468,6 +469,7 @@ def action_build(settings, trees, mtimedb,
 
 def action_config(settings, trees, myopts, myfiles):
        enter_invalid = '--ask-enter-invalid' in myopts
+       uq = UserQuery(myopts)
        if len(myfiles) != 1:
                print(red("!!! config can only take a single package atom at 
this time\n"))
                sys.exit(1)
@@ -497,7 +499,7 @@ def action_config(settings, trees, myopts, myfiles):
                                print(options[-1]+") "+pkg)
                        print("X) Cancel")
                        options.append("X")
-                       idx = userquery("Selection?", enter_invalid, 
responses=options)
+                       idx = uq.query("Selection?", enter_invalid, 
responses=options)
                        if idx == "X":
                                sys.exit(128 + signal.SIGINT)
                        pkg = pkgs[int(idx)-1]
@@ -512,7 +514,7 @@ def action_config(settings, trees, myopts, myfiles):
 
        print()
        if "--ask" in myopts:
-               if userquery("Ready to configure %s?" % pkg, enter_invalid) == 
"No":
+               if uq.query("Ready to configure %s?" % pkg, enter_invalid) == 
"No":
                        sys.exit(128 + signal.SIGINT)
        else:
                print("Configuring pkg...")
@@ -1364,7 +1366,8 @@ def action_deselect(settings, trees, opts, atoms):
                        if '--ask' in opts:
                                prompt = "Would you like to remove these " + \
                                        "packages from your world favorites?"
-                               if userquery(prompt, enter_invalid) == 'No':
+                               uq = UserQuery(opts)
+                               if uq.query(prompt, enter_invalid) == 'No':
                                        return 128 + signal.SIGINT
 
                        remaining = set(world_set)
@@ -2402,7 +2405,8 @@ def _sync_repo(emerge_config, repo):
 
                        if (retries==0):
                                if "--ask" in myopts:
-                                       if userquery("Do you want to sync your 
Portage tree " + \
+                                       uq = UserQuery(myopts)
+                                       if uq.query("Do you want to sync your 
Portage tree " + \
                                                "with the mirror at\n" + 
blue(dosyncuri) + bold("?"),
                                                enter_invalid) == "No":
                                                print()
@@ -3841,7 +3845,8 @@ def run_action(emerge_config):
                                                (access_desc,), noiselevel=-1)
                                        if portage.data.secpass < 1 and not 
need_superuser:
                                                
portage.data.portage_group_warning()
-                                       if userquery("Would you like to add 
--pretend to options?",
+                                       uq = UserQuery(emerge_config.opts)
+                                       if uq.query("Would you like to add 
--pretend to options?",
                                                "--ask-enter-invalid" in 
emerge_config.opts) == "No":
                                                return 128 + signal.SIGINT
                                        emerge_config.opts["--pretend"] = True

diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index bede7c6..8177b74 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -73,7 +73,7 @@ from _emerge.SetArg import SetArg
 from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice
 from _emerge.UnmergeDepPriority import UnmergeDepPriority
 from _emerge.UseFlagDisplay import pkg_use_display
-from _emerge.userquery import userquery
+from _emerge.UserQuery import UserQuery
 
 from _emerge.resolver.backtracking import Backtracker, BacktrackParameter
 from _emerge.resolver.package_tracker import PackageTracker, 
PackageTrackerDbapiWrapper
@@ -520,6 +520,9 @@ class depgraph(object):
                self._event_loop = (portage._internal_caller and
                        global_event_loop() or EventLoop(main=False))
 
+               self.uq = UserQuery(myopts)
+               self.query = UserQuery.query
+
        def _load_vdb(self):
                """
                Load installed package metadata if appropriate. This used to be 
called
@@ -7655,7 +7658,7 @@ class depgraph(object):
                if ask and write_to_file and file_to_write_to:
                        prompt = "\nWould you like to add these " + \
                                "changes to your config files?"
-                       if userquery(prompt, enter_invalid) == 'No':
+                       if self.query(prompt, enter_invalid) == 'No':
                                write_to_file = False
 
                if write_to_file and file_to_write_to:
@@ -7922,7 +7925,7 @@ class depgraph(object):
                                        "favorites?"
                                enter_invalid = '--ask-enter-invalid' in \
                                        self._frozen_config.myopts
-                               if userquery(prompt, enter_invalid) == "No":
+                               if self.query(prompt, enter_invalid) == "No":
                                        skip = True
 
                        if not skip:

diff --git a/pym/_emerge/main.py b/pym/_emerge/main.py
index eddb16c..1a920f7 100644
--- a/pym/_emerge/main.py
+++ b/pym/_emerge/main.py
@@ -124,6 +124,7 @@ def insert_optional_args(args):
        new_args = []
 
        default_arg_opts = {
+               '--alert'                : y_or_n,
                '--ask'                  : y_or_n,
                '--autounmask'           : y_or_n,
                '--autounmask-keep-masks': y_or_n,
@@ -169,6 +170,7 @@ def insert_optional_args(args):
        # since existence of -n makes it too ambiguous.
        short_arg_opts_n = {
                'a' : y_or_n,
+               'A' : y_or_n,
                'b' : y_or_n,
                'g' : y_or_n,
                'G' : y_or_n,
@@ -300,6 +302,12 @@ def parse_opts(tmpcmdline, silent=False):
        true_y = ("True", "y")
        argument_options = {
 
+               "--alert": {
+                       "shortopt" : "-A",
+                       "help"    : "alert (terminal bell) on prompts",
+                       "choices" : true_y_or_n
+               },
+
                "--ask": {
                        "shortopt" : "-a",
                        "help"    : "prompt before performing any actions",
@@ -675,6 +683,11 @@ def parse_opts(tmpcmdline, silent=False):
 
        myoptions, myargs = parser.parse_known_args(args=tmpcmdline)
 
+       if myoptions.alert in true_y:
+               myoptions.alert = True
+       else:
+               myoptions.alert = None
+
        if myoptions.ask in true_y:
                myoptions.ask = True
        else:

diff --git a/pym/_emerge/unmerge.py b/pym/_emerge/unmerge.py
index b04f8f3..8f98563 100644
--- a/pym/_emerge/unmerge.py
+++ b/pym/_emerge/unmerge.py
@@ -17,8 +17,8 @@ from portage.versions import cpv_sort_key, _pkg_str
 
 from _emerge.emergelog import emergelog
 from _emerge.Package import Package
+from _emerge.UserQuery import UserQuery
 from _emerge.UninstallFailure import UninstallFailure
-from _emerge.userquery import userquery
 from _emerge.countdown import countdown
 
 def _unmerge_display(root_config, myopts, unmerge_action,
@@ -529,7 +529,8 @@ def unmerge(root_config, myopts, unmerge_action,
                #we're done... return
                return os.EX_OK
        if "--ask" in myopts:
-               if userquery("Would you like to unmerge these packages?",
+               uq = UserQuery(myopts)
+               if uq.query("Would you like to unmerge these packages?",
                        enter_invalid) == "No":
                        # enter pretend mode for correct formatting of results
                        myopts["--pretend"] = True

diff --git a/pym/_emerge/userquery.py b/pym/_emerge/userquery.py
deleted file mode 100644
index efae80a..0000000
--- a/pym/_emerge/userquery.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 1999-2012 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-from __future__ import print_function
-
-import signal
-import sys
-
-from portage.output import bold, create_color_func
-
-def userquery(prompt, enter_invalid, responses=None, colours=None):
-       """Displays a prompt and a set of responses, then waits for a response
-       which is checked against the responses and the first to match is
-       returned. An empty response will match the first value in responses,
-       unless enter_invalid is True. The input buffer is *not* cleared prior
-       to the prompt!
-
-       prompt: a String.
-       responses: a List of Strings.
-       colours: a List of Functions taking and returning a String, used to
-       process the responses for display. Typically these will be functions
-       like red() but could be e.g. lambda x: "DisplayString".
-       If responses is omitted, defaults to ["Yes", "No"], [green, red].
-       If only colours is omitted, defaults to [bold, ...].
-
-       Returns a member of the List responses. (If called without optional
-       arguments, returns "Yes" or "No".)
-       KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
-       printed."""
-       if responses is None:
-               responses = ["Yes", "No"]
-               colours = [
-                       create_color_func("PROMPT_CHOICE_DEFAULT"),
-                       create_color_func("PROMPT_CHOICE_OTHER")
-               ]
-       elif colours is None:
-               colours=[bold]
-       colours=(colours*len(responses))[:len(responses)]
-       print(bold(prompt), end=' ')
-       try:
-               while True:
-                       if sys.hexversion >= 0x3000000:
-                               
response=input("["+"/".join([colours[i](responses[i]) for i in 
range(len(responses))])+"] ")
-                       else:
-                               
response=raw_input("["+"/".join([colours[i](responses[i]) for i in 
range(len(responses))])+"] ")
-                       if response or not enter_invalid:
-                               for key in responses:
-                                       # An empty response will match the
-                                       # first value in responses.
-                                       if 
response.upper()==key[:len(response)].upper():
-                                               return key
-                       print("Sorry, response '%s' not understood." % 
response, end=' ')
-       except (EOFError, KeyboardInterrupt):
-               print("Interrupted.")
-               sys.exit(128 + signal.SIGINT)

Reply via email to