aboutsummaryrefslogtreecommitdiff
path: root/lava/parameter.py
diff options
context:
space:
mode:
authorAntonio Terceiro <antonio.terceiro@linaro.org>2013-11-18 18:47:24 -0300
committerAntonio Terceiro <antonio.terceiro@linaro.org>2013-11-18 18:47:24 -0300
commit99ea8ab8541c3144c5e62cec8cdd327dc13c4388 (patch)
tree67c033d678e6ea7b0223d9608e5bf7dcd4752f20 /lava/parameter.py
parent49c36d653c19c018e473d7a1a27bdf5cb607c4be (diff)
Imported Upstream version 0.8upstream/0.8
Diffstat (limited to 'lava/parameter.py')
-rw-r--r--lava/parameter.py256
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