diff options
author | Antonio Terceiro <antonio.terceiro@linaro.org> | 2013-11-18 18:47:24 -0300 |
---|---|---|
committer | Antonio Terceiro <antonio.terceiro@linaro.org> | 2013-11-18 18:47:24 -0300 |
commit | 99ea8ab8541c3144c5e62cec8cdd327dc13c4388 (patch) | |
tree | 67c033d678e6ea7b0223d9608e5bf7dcd4752f20 /lava/parameter.py | |
parent | 49c36d653c19c018e473d7a1a27bdf5cb607c4be (diff) |
Imported Upstream version 0.8upstream/0.8
Diffstat (limited to 'lava/parameter.py')
-rw-r--r-- | lava/parameter.py | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/lava/parameter.py b/lava/parameter.py new file mode 100644 index 0000000..dfb0883 --- /dev/null +++ b/lava/parameter.py @@ -0,0 +1,256 @@ +# Copyright (C) 2013 Linaro Limited +# +# Author: Antonio Terceiro <antonio.terceiro@linaro.org> +# +# This file is part of lava-tool. +# +# lava-tool is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# as published by the Free Software Foundation +# +# lava-tool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with lava-tool. If not, see <http://www.gnu.org/licenses/>. + +""" +Parameter class and its accessory methods/functions. +""" + +import sys +import types + +from lava_tool.utils import to_list + +# Character used to join serialized list parameters. +LIST_SERIALIZE_DELIMITER = "," + + +class Parameter(object): + + """A parameter with an optional dependency.""" + + def __init__(self, id, value=None, depends=None): + """Creates a new parameter. + + :param id: The name of this parameter. + :param value: The value of this parameter. Defaults to None. + :param depends: If this Parameter depends on another one. Defaults + to None. + :type Parameter + """ + self.id = id + self.value = value + self.depends = depends + self.asked = False + # Whether to store or not the parameter in the user config file. + self.store = True + + def set(self, value): + """Sets the value of the parameter. + + :param value: The value to set. + """ + self.value = value + + def prompt(self, old_value=None): + """Gets the parameter value from the user. + + To get user input, the builtin `raw_input` function will be used. Input + will also be stripped of possible whitespace chars. If Enter or any + sort of whitespace chars in typed, the old Parameter value will be + returned. + + :param old_value: The old parameter value. + :return The input as typed by the user, or the old value. + """ + if not self.asked: + if old_value is not None: + prompt = "{0} [{1}]: ".format(self.id, old_value) + else: + prompt = "{0}: ".format(self.id) + + user_input = self.get_user_input(prompt) + + if user_input is not None: + if len(user_input) == 0 and old_value: + # Keep the old value when user press enter or another + # whitespace char. + self.value = old_value + else: + self.value = user_input + + self.asked = True + + return self.value + + @classmethod + def get_user_input(cls, prompt=""): + """Asks the user for input data. + + :param prompt: The prompt that should be given to the user. + :return A string with what the user typed. + """ + data = None + try: + data = raw_input(prompt).strip() + except EOFError: + # Force to return None. + data = None + except KeyboardInterrupt: + sys.exit(-1) + return data + + @classmethod + def serialize(cls, value): + """Serializes the passed value to be friendly written to file. + + Lists are serialized as a comma separated string of values. + + :param value: The value to serialize. + :return The serialized value as string. + """ + serialized = "" + if isinstance(value, list): + serialized = LIST_SERIALIZE_DELIMITER.join( + str(x) for x in value if x) + else: + serialized = str(value) + return serialized + + @classmethod + def deserialize(cls, value): + """Deserialize a value into a list. + + The value must have been serialized with the class instance serialize() + method. + + :param value: The string value to be deserialized. + :type str + :return A list of values. + """ + deserialized = [] + if isinstance(value, str): + deserialized = filter(None, (x.strip() for x in value.split( + LIST_SERIALIZE_DELIMITER))) + else: + deserialized = list(value) + return deserialized + + +class SingleChoiceParameter(Parameter): + + """A parameter implemeting a single choice between multiple choices.""" + + def __init__(self, id, choices): + super(SingleChoiceParameter, self).__init__(id) + self.choices = to_list(choices) + + def prompt(self, prompt, old_value=None): + """Asks the user for their choice.""" + # Sliglty different than the other parameters: here we first present + # the user with what the choices are about. + print >> sys.stdout, prompt + + index = 1 + for choice in self.choices: + print >> sys.stdout, "\t{0:d}. {1}".format(index, choice) + index += 1 + + choices_len = len(self.choices) + while True: + user_input = self.get_user_input("Choice: ") + + if len(user_input) == 0 and old_value: + choice = old_value + break + elif user_input in [str(x) for x in range(1, choices_len + 1)]: + choice = self.choices[int(user_input) - 1] + break + + return choice + + +class ListParameter(Parameter): + + """A specialized Parameter to handle list values.""" + + # This is used as a deletion character. When we have an old value and the + # user enters this char, it sort of deletes the value. + DELETE_CHAR = "-" + + def __init__(self, id, value=None, depends=None): + super(ListParameter, self).__init__(id, depends=depends) + self.value = [] + if value: + self.set(value) + + def set(self, value): + """Sets the value of the parameter. + + :param value: The value to set. + """ + self.value = to_list(value) + + def add(self, value): + """Adds a new value to the list of values of this parameter. + + :param value: The value to add. + """ + if isinstance(value, list): + self.value.extend(value) + else: + self.value.append(value) + + def prompt(self, old_value=None): + """Gets the parameter in a list form. + + To exit the input procedure it is necessary to insert an empty line. + + :return The list of values. + """ + + if not self.asked: + if old_value is not None: + # We might get the old value read from file via ConfigParser, + # and usually it comes in string format. + old_value = self.deserialize(old_value) + + print >> sys.stdout, "Values for '{0}': ".format(self.id) + + index = 1 + while True: + user_input = None + if old_value is not None and (0 < len(old_value) >= index): + prompt = "{0:>3d}.\n\told: {1}\n\tnew: ".format( + index, old_value[index - 1]) + user_input = self.get_user_input(prompt) + else: + prompt = "{0:>3d}. ".format(index) + user_input = self.get_user_input(prompt) + + if user_input is not None: + # The user has pressed Enter. + if len(user_input) == 0: + if old_value is not None and \ + (0 < len(old_value) >= index): + user_input = old_value[index - 1] + else: + break + + if len(user_input) == 1 and user_input == \ + self.DELETE_CHAR and (0 < len(old_value) >= index): + # We have an old value, user presses the DELETE_CHAR + # and we do not store anything. This is done to delete + # an old entry. + pass + else: + self.value.append(user_input) + index += 1 + + self.asked = True + + return self.value |