diff options
| author | Miloslav Trmač <mitr@redhat.com> | 2009-07-14 14:05:51 +0200 |
|---|---|---|
| committer | Martin Sivak <msivak@redhat.com> | 2009-07-17 16:39:49 +0200 |
| commit | bacf876d7492986e38cf3ba2f6ff9cbf44b28957 (patch) | |
| tree | 7ae0eebfa1dda79a3757ace6b56aa1701032233a /pyfirstaidkit | |
| parent | 8c737c21ed85cccb729ed6761a63de6be0142800 (diff) | |
| download | firstaidkit-bacf876d7492986e38cf3ba2f6ff9cbf44b28957.tar.gz firstaidkit-bacf876d7492986e38cf3ba2f6ff9cbf44b28957.tar.xz firstaidkit-bacf876d7492986e38cf3ba2f6ff9cbf44b28957.zip | |
Add question support.
Signed-off-by: Martin Sivak <msivak@redhat.com>
Diffstat (limited to 'pyfirstaidkit')
| -rw-r--r-- | pyfirstaidkit/errors.py | 4 | ||||
| -rw-r--r-- | pyfirstaidkit/reporting.py | 109 |
2 files changed, 110 insertions, 3 deletions
diff --git a/pyfirstaidkit/errors.py b/pyfirstaidkit/errors.py index 02bbf27..e49d978 100644 --- a/pyfirstaidkit/errors.py +++ b/pyfirstaidkit/errors.py @@ -44,3 +44,7 @@ class GeneralPluginException(FAKException): def __init__(self, plugin, message): self.message="There was an exception in plugin %s with message %s"% \ (plugin,message) + +class NoAnswerException(FAKException): + def __init__(self): + self.message="No answer provided by user." diff --git a/pyfirstaidkit/reporting.py b/pyfirstaidkit/reporting.py index ae73629..5c859ee 100644 --- a/pyfirstaidkit/reporting.py +++ b/pyfirstaidkit/reporting.py @@ -20,6 +20,8 @@ import logging import thread import weakref +from errors import * + Logger = logging.getLogger("firstaidkit") #semantics values @@ -41,7 +43,11 @@ EXCEPTION = 5 TABLE = 6 #types for arbitrary table-like organized iterables TREE = 7 #nested iterables organized as tree ISSUE = 8 #New issue object was created or changed -QUESTION = 999 #type of message which contains respond-to field +CHOICE_QUESTION = 990 #a Question object, "reply" specifies a Reports object +TEXT_QUESTION = 991 +FILENAME_QUESTION = 992 +PASSWORD_QUESTION = 993 +ANSWER = 999 #Data sent in reply to a *_QUESTION END = 1000 #End of operations, final message class Origin(object): @@ -52,11 +58,51 @@ class Origin(object): def __init__(self, name): self.name = name +class Question(object): + """A pending question to the user. + + Object identity is used to match questions and replies.""" + + def __init__(self, prompt): + self.prompt = prompt + + def send_answer(self, question_message, answer, origin = None): + assert question_message["message"] is self + question_message["reply"].put \ + (answer, origin, FIRSTAIDKIT, ANSWER, + importance = question_message["importance"], inreplyto = self) + question_message["reply"].end(level = FIRSTAIDKIT) + +class ChoiceQuestion(Question): + """A question that offers multiple options. + + Each option is a tuple of (return value, description).""" + + def __init__(self, prompt, options): + super(ChoiceQuestion, self).__init__(prompt) + assert len(options) > 0 + self.options = options + +class TextQuestion(Question): + """A question that asks for a string.""" + pass # No special behavior + +class FilenameQuestion(TextQuestion): + """A question that asks for a file name.""" + pass # No special behavior + +class PasswordQuestion(Question): + """A question that asks for a password.""" + + def __init__(self, prompt, confirm): + super(PasswordQuestion, self).__init__(prompt) + self.confirm = confirm + class Reports(object): """Instances of this class are used as reporting mechanism by which the plugins can comminucate back to whatever frontend we are using. - Message has four parts: + Message has the following parts: origin - who sent the message (instance of the plugin, Pluginsystem, ...) level - which level of First Aid Kit sent the message (PLUGIN, TASKER, ..) action - what action does the message describe @@ -69,7 +115,9 @@ class Reports(object): (on step x from y steps) or None to hide the progress for START and STOP, there is no mandatory message and the importance specifies the level - reply - the instance of Queue.Queue, which should receive the replies + for *_QUESTION, this is a Qustion object + reply - an instance of Reports that should receive the replies + inreplyto - in replies, "message" from the associated question message title - title of the message """ @@ -223,3 +271,58 @@ class Reports(object): return self.put(message, origin, level, EXCEPTION, importance = importance, inreplyto = inreplyto) + def __blocking_question(self, fn, args, kwargs): + mb = self.openMailbox() + try: + question = fn(mb, *args, **kwargs) + r = mb.get() + assert r["action"] in (ANSWER, END) + if r["action"] == END: + raise NoAnswerException() + assert r["inreplyto"] is question + answer = r["message"] + r = mb.get() + assert r["action"] == END + finally: + mb.closeMailbox() + return answer + + def choice_question(self, reply_mb, prompt, options, origin, level = PLUGIN, + importance = logging.ERROR): + q = ChoiceQuestion(prompt, options) + self.put(q, origin, level, CHOICE_QUESTION, importance = importance, + reply = reply_mb) + return q + + def choice_question_wait(self, *args, **kwargs): + return self.__blocking_question(self.choice_question, args, kwargs) + + def text_question(self, reply_mb, prompt, origin, level = PLUGIN, + importance = logging.ERROR): + q = TextQuestion(prompt) + self.put(q, origin, level, TEXT_QUESTION, importance = importance, + reply = reply_mb) + return q + + def text_question_wait(self, *args, **kwargs): + return self.__blocking_question(self.text_question, args, kwargs) + + def password_question(self, reply_mb, prompt, origin, level = PLUGIN, + importance = logging.ERROR, confirm = False): + q = PasswordQuestion(prompt, confirm) + self.put(q, origin, level, PASSWORD_QUESTION, importance = importance, + reply = reply_mb) + return q + + def password_question_wait(self, *args, **kwargs): + return self.__blocking_question(self.password_question, args, kwargs) + + def filename_question(self, reply_mb, prompt, origin, level = PLUGIN, + importance = logging.ERROR): + q = FilenameQuestion(prompt) + self.put(q, origin, level, FILENAME_QUESTION, importance = importance, + reply = reply_mb) + return q + + def filename_question_wait(self, *args, **kwargs): + return self.__blocking_question(self.filename_question, args, kwargs) |
