jenkins-bot has submitted this change and it was merged.
Change subject: [FEAT] input_choice: Support exceptions as options ......................................................................
[FEAT] input_choice: Support exceptions as options
Each option can now be an exception (subclassing ChoiceException) and it'll automatically raise it when selected. The QuitKeyboardInterrupt does subclass it and is already integrated into it.
Moved the QuitKeyboardInterrupt into pywikibot.userinterfaces.terminal_interface_base and it is aliased in the pywikibot.bot module.
This removes the ability to set the automatic_quit parameter to an int (pywikibot.bot doesn't even document this feature) as the option can be simply a ChoiceException or QuitKeyboardInterrupt.
Change-Id: I2ebb7a2839577b721a8a73d772e48c5b2fcce486 --- M pywikibot/__init__.py M pywikibot/bot.py M pywikibot/userinterfaces/terminal_interface.py M pywikibot/userinterfaces/terminal_interface_base.py M scripts/catall.py 5 files changed, 60 insertions(+), 32 deletions(-)
Approvals: John Vandenberg: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py index bd05c51..266a054 100644 --- a/pywikibot/__init__.py +++ b/pywikibot/__init__.py @@ -33,7 +33,7 @@ from pywikibot.bot import ( output, warning, error, critical, debug, stdout, exception, input, input_choice, input_yn, inputChoice, handle_args, showHelp, ui, log, - calledModuleName, Bot, CurrentPageBot, WikidataBot, QuitKeyboardInterrupt, + calledModuleName, Bot, CurrentPageBot, WikidataBot, # the following are flagged as deprecated on usage handleArgs, ) @@ -757,3 +757,7 @@ 'UserActionRefuse', pywikibot.exceptions._EmailUserError, warning_message='UserActionRefuse is deprecated; ' 'use UserRightsError and/or NotEmailableError') +wrapper._add_deprecated_attr( + 'QuitKeyboardInterrupt', pywikibot.bot.QuitKeyboardInterrupt, + warning_message='pywikibot.QuitKeyboardInterrupt is deprecated; ' + 'use pywikibot.bot.QuitKeyboardInterrupt instead') diff --git a/pywikibot/bot.py b/pywikibot/bot.py index ca0afba..b58351d 100644 --- a/pywikibot/bot.py +++ b/pywikibot/bot.py @@ -52,9 +52,12 @@ # search for user interface module in the 'userinterfaces' subdirectory uiModule = __import__("pywikibot.userinterfaces.%s_interface" % config.userinterface, - fromlist=['UI']) + fromlist=['UI', 'ChoiceException', 'QuitKeyboardInterrupt']) ui = uiModule.UI() pywikibot.argvu = ui.argvu() + +ChoiceException = uiModule.ChoiceException +QuitKeyboardInterrupt = uiModule.QuitKeyboardInterrupt
# It's not possible to use pywikibot.exceptions.PageRelatedError as that is @@ -585,7 +588,8 @@ @type question: basestring @param answers: The valid answers each containing a full length answer and a shortcut. Each value must be unique. - @type answers: Iterable containing an iterable of length two + @type answers: iterable containing a sequence of length two or instances of + ChoiceException @param default: The result if no answer was entered. It must not be in the valid answers and can be disabled by setting it to None. If it should be linked with the valid answers it must be its shortcut. @@ -594,7 +598,7 @@ returned. @type return_shortcut: bool @param automatic_quit: Adds the option 'Quit' ('q') and throw a - L{QuitKeyboardInterrupt} if selected. + L{QuitKeyboardInterrupt} if selected. @type automatic_quit: bool @param force: Automatically use the default @type force: bool @@ -1132,11 +1136,6 @@ from pywikibot import i18n webbrowser.open(page.full_url()) i18n.input('pywikibot-enter-finished-browser') - - -class QuitKeyboardInterrupt(KeyboardInterrupt): - - """The user has cancelled processing at a prompt."""
class BaseBot(object): diff --git a/pywikibot/userinterfaces/terminal_interface.py b/pywikibot/userinterfaces/terminal_interface.py index 9a5fbf1..768b5e8 100644 --- a/pywikibot/userinterfaces/terminal_interface.py +++ b/pywikibot/userinterfaces/terminal_interface.py @@ -20,4 +20,10 @@ else: from .terminal_interface_unix import UnixUI as UI
-__all__ = ('UI',) +from pywikibot.userinterfaces.terminal_interface_base import ( + ChoiceException, QuitKeyboardInterrupt, +) + +__all__ = ( + 'UI', 'ChoiceException', 'QuitKeyboardInterrupt', +) diff --git a/pywikibot/userinterfaces/terminal_interface_base.py b/pywikibot/userinterfaces/terminal_interface_base.py index 2ce3c5d..fa69a1f 100755 --- a/pywikibot/userinterfaces/terminal_interface_base.py +++ b/pywikibot/userinterfaces/terminal_interface_base.py @@ -46,6 +46,25 @@ colorTagR = re.compile('\03{(?P<name>%s)}' % '|'.join(colors))
+class ChoiceException(Exception): + + """A choice for input_choice which result in this exception.""" + + def __init__(self, option, shortcut): + """Constructor using the given option and shortcut in input_choice.""" + self.option = option + self.shortcut = shortcut + + +class QuitKeyboardInterrupt(ChoiceException, KeyboardInterrupt): + + """The user has cancelled processing at a prompt.""" + + def __init__(self): + """Constructor using the 'quit' ('q') in input_choice.""" + super(QuitKeyboardInterrupt, self).__init__('quit', 'q') + + class UI:
"""Base for terminal user interfaces.""" @@ -258,7 +277,7 @@ else: text = self._raw_input() except KeyboardInterrupt: - raise pywikibot.QuitKeyboardInterrupt() + raise QuitKeyboardInterrupt() if PY2: text = text.decode(self.encoding) return text @@ -272,19 +291,20 @@ @type question: basestring @param options: All available options. Each entry contains the full length answer and a shortcut of only one character. The shortcut - must not appear in the answer. - @type options: iterable containing iterables of length 2 + must not appear in the answer. Alternatively they may be a + ChoiceException (or subclass) instance which has a full option and + shortcut. It will raise that exception when selected. + @type options: iterable containing sequences of length 2 or + ChoiceException @param default: The default answer if no was entered. None to require an answer. @type default: basestring @param return_shortcut: Whether the shortcut or the index in the option should be returned. @type return_shortcut: bool - @param automatic_quit: Adds the option 'Quit' ('q') and throw a - L{QuitKeyboardInterrupt} if selected. If it's an integer it - doesn't add the option but throw the exception when the option was - selected. - @type automatic_quit: bool or int + @param automatic_quit: Adds the option 'Quit' ('q') if True and throws a + L{QuitKeyboardInterrupt} if selected. + @type automatic_quit: bool @param force: Automatically use the default @type force: bool @return: If return_shortcut the shortcut of options or the value of @@ -295,23 +315,21 @@ options = list(options) if len(options) == 0: raise ValueError(u'No options are given.') - if automatic_quit is True: - options += [('Quit', 'q')] - quit_index = len(options) - 1 - elif automatic_quit is not False: - quit_index = automatic_quit - else: - quit_index = None + if automatic_quit: + options += [QuitKeyboardInterrupt()] if default: default = default.lower() valid = {} default_index = -1 formatted_options = [] for i, option in enumerate(options): - if len(option) != 2: - raise ValueError(u'Option #{0} does not consist of an option ' - u'and shortcut.'.format(i)) - option, shortcut = option + if isinstance(option, ChoiceException): + option, shortcut = option.option, option.shortcut + else: + if len(option) != 2: + raise ValueError('Option #{0} does not consist of an ' + 'option and shortcut.'.format(i)) + option, shortcut = option if option.lower() in valid: raise ValueError( u'Multiple identical options ({0}).'.format(option)) @@ -342,8 +360,8 @@ answer = default_index else: answer = valid.get(answer.lower(), None) - if quit_index == answer: - raise pywikibot.QuitKeyboardInterrupt() + if isinstance(options[answer], ChoiceException): + raise options[answer] elif not return_shortcut: return answer elif answer < 0: diff --git a/scripts/catall.py b/scripts/catall.py index 29bb9a5..a45eb28 100755 --- a/scripts/catall.py +++ b/scripts/catall.py @@ -30,6 +30,7 @@
import pywikibot from pywikibot import i18n, textlib +from pywikibot.bot import QuitKeyboardInterrupt
def choosecats(pagetext): @@ -61,7 +62,7 @@ chosen = None done = True elif choice == "q": - raise pywikibot.QuitKeyboardInterrupt + raise QuitKeyboardInterrupt else: chosen.append(choice) return chosen