1# Copyright 2016 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Sequenced feedback request."""
6
7from __future__ import print_function
8
9import input_handlers
10import request
11import textwrap
12
13
14class _RequestAction(object):
15    """An interface of a single action in a sequenced feedback request."""
16
17    def execute(self):
18        """Performs the action."""
19        raise NotImplementedError
20
21
22class _QuestionRequestAction(_RequestAction):
23    """A question to be presented to a user."""
24
25    def __init__(self, blurb, input_handler, prompt=None):
26        self.input_handler = input_handler
27        blurb_supp, prompt_supp = input_handler.get_choices_supplements()
28
29        # Initialize the question blurb string.
30        self.blurb = self._format_text(blurb)
31        if blurb_supp:
32            self.blurb += '\n' + blurb_supp
33
34        # Initialize the input prompt string.
35        if prompt is None:
36            prompt = ''
37        if prompt_supp:
38            if prompt:
39                prompt += ' '
40            prompt += prompt_supp
41        self.prompt = self._format_text(prompt)
42        if self.prompt:
43            self.prompt += ' '
44
45    def _format_text(self, text):
46        """Formats a blob of text for writing to standard output."""
47        return textwrap.fill(text.strip())
48
49
50    def execute(self):
51        if self.blurb:
52            print(self.blurb, end=('\n' if self.prompt else ' '))
53        while True:
54            try:
55                return self.input_handler.process(raw_input(self.prompt))
56            except input_handlers.InputError:
57                print('Invalid input, try again')
58
59
60class SequencedFeedbackRequest(request.FeedbackRequest):
61    """A request consisting of a sequence of interactive actions."""
62
63    def __init__(self, *args):
64        super(SequencedFeedbackRequest, self).__init__(*args)
65        self._actions = []
66
67
68    def _append_action(self, action):
69        self._actions.append(action)
70
71
72    def append_question(self, blurb, input_handler, prompt=None):
73        """Appends a question to the request sequence.
74
75        @param blurb: The text to print prior to asking for input.
76        @param input_handler: The input handler object.
77        @param prompt: String to print when polling for input.
78        """
79        attrs = {'test': self.test, 'dut': self.dut}
80        blurb = blurb or ''
81        self._append_action(_QuestionRequestAction(
82                blurb % attrs, input_handler,
83                prompt=(prompt and prompt % attrs)))
84
85
86    def execute(self):
87        """Executes the sequence of request actions.
88
89        @return: The return value of the last action.
90
91        @raise request.FeedbackRequestError: Failed during sequence execution.
92        """
93        ret = None
94        for action in self._actions:
95            ret = action.execute()
96        return ret
97