def input_choice(self, question, options, default=None,
                     return_shortcut=True, automatic_quit=True, force=False):
        """
        Ask the user and returns a value from the options.

        Depending on the options setting return_shortcut to False may not be
        sensible when the option supports multiple values as it'll return an
        ambiguous index.

        @param question: The question, without trailing whitespace.
        @type question: basestring
        @param options: Iterable of all available options. Each entry contains
            the full length answer and a shortcut of only one character.
            Alternatively they may be Option (or subclass) instances or
            ChoiceException instances which have a full option and shortcut
            and will be raised if selected.
        @type options: iterable containing sequences of length 2 or
            iterable containing Option instances or ChoiceException as well.
            Singletons of Option and its subclasses are also accepted.
        @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') 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
            default (if it's not None). Otherwise the index of the answer in
            options. If default is not a shortcut, it'll return -1.
        @rtype: int (if not return_shortcut), lowercased basestring (otherwise)
        """
        if force and default is None:
            raise ValueError('With no default option it cannot be forced')
        if isinstance(options, Option):
            options = [options]
        else:  # make a copy
            options = list(options)
        if len(options) == 0:
            raise ValueError(u'No options are given.')
        if automatic_quit:
            options += [QuitKeyboardInterrupt()]
        if default:
            default = default.lower()
        for i, option in enumerate(options):
            if not isinstance(option, Option):
                if len(option) != 2:
                    raise ValueError(u'Option #{0} does not consist of an '
                                     u'option and shortcut.'.format(i))
                options[i] = StandardOption(*option)
            # TODO: Test for uniquity

        handled = False
        while not handled:
            for option in options:
                if isinstance(option, OutputOption) and option.before_question:
                    option.output()
            output = Option.formatted(question, options, default)
            if force:
                self.output(output + '\n')
                answer = default
            else:
                answer = self.input(output) or default
            # something entered or default is defined
            if answer:
                for index, option in enumerate(options):
                    if option.handled(answer):
                        answer = option.result(answer)
                        handled = option.stop
                        break

        if isinstance(answer, ChoiceException):
            raise answer
        elif not return_shortcut:
            return index
        else:
            return answer
Beispiel #2
0
    def input_choice(self,
                     question: str,
                     options,
                     default: str = None,
                     return_shortcut: bool = True,
                     automatic_quit: bool = True,
                     force: bool = False):
        """
        Ask the user and returns a value from the options.

        Depending on the options setting return_shortcut to False may not be
        sensible when the option supports multiple values as it'll return an
        ambiguous index.

        @param question: The question, without trailing whitespace.
        @param options: Iterable of all available options. Each entry contains
            the full length answer and a shortcut of only one character.
            Alternatively they may be Option (or subclass) instances or
            ChoiceException instances which have a full option and shortcut
            and will be raised if selected.
        @type options: iterable containing sequences of length 2 or
            iterable containing Option instances or ChoiceException as well.
            Singletons of Option and its subclasses are also accepted.
        @param default: The default answer if no was entered. None to require
            an answer.
        @param return_shortcut: Whether the shortcut or the index in the option
            should be returned.
        @param automatic_quit: Adds the option 'Quit' ('q') if True and throws
            a L{QuitKeyboardInterrupt} if selected.
        @param force: Automatically use the default
        @return: If return_shortcut the shortcut of options or the value of
            default (if it's not None). Otherwise the index of the answer in
            options. If default is not a shortcut, it'll return -1.
        @rtype: int (if not return_shortcut), lowercased str (otherwise)
        """
        if force and default is None:
            raise ValueError('With no default option it cannot be forced')
        if isinstance(options, Option):
            options = [options]
        else:  # make a copy
            options = list(options)
        if not options:
            raise ValueError('No options are given.')
        if automatic_quit:
            options += [QuitKeyboardInterrupt()]
        if default:
            default = default.lower()
        for i, option in enumerate(options):
            if not isinstance(option, Option):
                if len(option) != 2:
                    raise ValueError('Option #{0} does not consist of an '
                                     'option and shortcut.'.format(i))
                options[i] = StandardOption(*option)
            # TODO: Test for uniquity

        handled = False
        while not handled:
            for option in options:
                if isinstance(option, OutputOption) and option.before_question:
                    option.output()
            output = Option.formatted(question, options, default)
            if force:
                self.output(output + '\n')
                answer = default
            else:
                answer = self.input(output) or default
            # something entered or default is defined
            if answer:
                for index, option in enumerate(options):
                    if option.handled(answer):
                        answer = option.result(answer)
                        handled = option.stop
                        break

        if isinstance(answer, ChoiceException):
            raise answer
        if not return_shortcut:
            return index
        return answer
    def input_choice(self,
                     question: str,
                     options: Union[Iterable[Union[Tuple[
                         str, str], 'pywikibot.bot_choice.Option']],
                                    'pywikibot.bot_choice.Option'],
                     default: Optional[str] = None,
                     return_shortcut: bool = True,
                     automatic_quit: bool = True,
                     force: bool = False) -> Any:
        """
        Ask the user and returns a value from the options.

        Depending on the options setting return_shortcut to False may not be
        sensible when the option supports multiple values as it'll return an
        ambiguous index.

        :param question: The question, without trailing whitespace.
        :param options: Iterable of all available options. Each entry contains
            the full length answer and a shortcut of only one character.
            Alternatively they may be Option (or subclass) instances or
            ChoiceException instances which have a full option and shortcut
            and will be raised if selected.
        :param default: The default answer if no was entered. None to require
            an answer.
        :param return_shortcut: Whether the shortcut or the index in the option
            should be returned.
        :param automatic_quit: Adds the option 'Quit' ('q') if True and throws
            a :py:obj:`QuitKeyboardInterrupt` if selected.
        :param force: Automatically use the default
        :return: If return_shortcut the shortcut of options or the value of
            default (if it's not None). Otherwise the index of the answer in
            options. If default is not a shortcut, it'll return -1.
        """
        def output_option(option, before_question):
            """Print an OutputOption before or after question."""
            if isinstance(option, OutputOption) \
               and option.before_question is before_question:
                self.stream_output(option.out + '\n')

        if force and default is None:
            raise ValueError('With no default option it cannot be forced')
        if isinstance(options, Option):
            options = [options]
        else:  # make a copy
            options = list(options)
        if not options:
            raise ValueError('No options are given.')
        if automatic_quit:
            options += [QuitKeyboardInterrupt()]
        if default:
            default = default.lower()
        for i, option in enumerate(options):
            if not isinstance(option, Option):
                if len(option) != 2:
                    raise ValueError('Option #{} does not consist of an '
                                     'option and shortcut.'.format(i))
                options[i] = StandardOption(*option)
            # TODO: Test for uniquity

        handled = False

        # lock stream output
        with self.lock:
            while not handled:
                for option in options:
                    output_option(option, before_question=True)
                output = Option.formatted(question, options, default)
                if force:
                    self.stream_output(output + '\n')
                    answer = default
                else:
                    answer = self.input(output) or default
                # something entered or default is defined
                if answer:
                    for index, option in enumerate(options):
                        if option.handled(answer):
                            answer = option.result(answer)
                            output_option(option, before_question=False)
                            handled = option.stop
                            break

        if isinstance(answer, ChoiceException):
            raise answer
        if not return_shortcut:
            return index
        return answer