← Back to team overview

apport-hackers team mailing list archive

[Merge] lp:~chad.smith/apport/add-multichar-response-for-long-lists into lp:apport

 

Chad Smith has proposed merging lp:~chad.smith/apport/add-multichar-response-for-long-lists into lp:apport.

Requested reviews:
  Apport upstream developers (apport-hackers)
Related bugs:
  Bug #1722564 in Apport: "apport question will not accept multi-character responses"
  https://bugs.launchpad.net/apport/+bug/1722564

For more details, see:
https://code.launchpad.net/~chad.smith/apport/add-multichar-response-for-long-lists/+merge/332729

In cloud-init we have apport cli prompts what cloud are you on. Since there are two character responses required for options >= 10 we can't have apport limit the response to a single character.

This branch fixes lp: #1722564 by forcing apport to readline instead of read(1) for a given prompt if that prompt is > 10 choices (1-9 + the letter C (cancel)).

-- 
Your team Apport upstream developers is requested to review the proposed merge of lp:~chad.smith/apport/add-multichar-response-for-long-lists into lp:apport.
=== modified file 'bin/apport-cli'
--- bin/apport-cli	2016-12-10 11:28:27 +0000
+++ bin/apport-cli	2017-10-24 16:32:48 +0000
@@ -34,8 +34,12 @@
         self.buttons = []
         self.visible = False
 
-    def raw_input_char(self, prompt):
-        '''raw_input, but read only one character'''
+    def raw_input_char(self, prompt, multi_char=False):
+        '''raw_input, but read a single character unless multi_char is True.
+
+        @param: prompt: the text presented to the user to solict a response.
+        @param: multi_char: Boolean True if we need to read until <enter>.
+        '''
 
         sys.stdout.write(prompt)
         sys.stdout.write(' ')
@@ -48,14 +52,16 @@
         attributes[6][termios.VMIN] = 1
         attributes[6][termios.VTIME] = 0
         termios.tcsetattr(file, termios.TCSANOW, attributes)
-
         try:
-            ch = str(sys.stdin.read(1))
+            if multi_char:
+                response = str(sys.stdin.readline()).strip()
+            else:
+                response = str(sys.stdin.read(1))
         finally:
             termios.tcsetattr(file, termios.TCSANOW, saved_attributes)
 
         sys.stdout.write('\n')
-        return ch
+        return response
 
     def show(self):
         self.visible = True
@@ -82,9 +88,19 @@
                 for index, button in enumerate(self.buttons):
                     print('  %s: %s' % (self.keys[index], button))
 
-                response = self.raw_input_char(_('Please choose (%s):') % ('/'.join(self.keys)))
+                if len(self.keys) <= 10:
+                    # A 10 option prompt would can still be a single character
+                    # response because the 10 options listed will be 1-9 and C.
+                    # Therefore there are 10 unique responses which can be
+                    # given.
+                    multi_char = False
+                else:
+                    multi_char = True
+                response = self.raw_input_char(
+                   _('Please choose (%s):') % ('/'.join(self.keys)),
+                   multi_char)
                 try:
-                    return self.keys.index(response[0].upper()) + 1
+                    return self.keys.index(response.upper()) + 1
                 except ValueError:
                     pass
         except KeyboardInterrupt:


Follow ups