Re-factor the option parsing following a suggestion from Greg.
Eliminate the <topic>.parse altogether.

Signed-off-by: Jean-Marc Eurin <[email protected]>


git-svn-id: http://test.kernel.org/svn/autotest/trunk@3081 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/cli/topic_common.py b/cli/topic_common.py
index 7167525..bf47ce3 100755
--- a/cli/topic_common.py
+++ b/cli/topic_common.py
@@ -135,6 +135,67 @@
     pass
 
 
+class item_parse_info(object):
+    def __init__(self, attribute_name, inline_option='',
+                 filename_option='', use_leftover=False):
+        """Object keeping track of the parsing options that will
+        make up the content of the atest attribute:
+        atttribute_name: the atest attribute name to populate    (label)
+        inline_option: the option containing the items           (--label)
+        filename_option: the option containing the filename      (--blist)
+        use_leftover: whether to add the leftover arguments or not."""
+        self.attribute_name = attribute_name
+        self.filename_option = filename_option
+        self.inline_option = inline_option
+        self.use_leftover = use_leftover
+
+
+    def get_values(self, options, leftover=[]):
+        """Returns the value for that attribute by accumualting all
+        the values found through the inline option, the parsing of the
+        file and the leftover"""
+        def __get_items(string, split_re='[\s,]\s*'):
+            return (item.strip() for item in re.split(split_re, string)
+                    if item)
+
+        if self.use_leftover:
+            add_on = leftover
+            leftover = []
+        else:
+            add_on = []
+
+        # Start with the add_on
+        result = set()
+        for items in add_on:
+            # Don't split on space here because the add-on
+            # may have some spaces (like the job name)
+            result.update(__get_items(items, split_re='[,]'))
+
+        # Process the inline_option, if any
+        try:
+            items = getattr(options, self.inline_option)
+            result.update(__get_items(items))
+        except (AttributeError, TypeError):
+            pass
+
+        # Process the file list, if any and not empty
+        # The file can contain space and/or comma separated items
+        try:
+            flist = getattr(options, self.filename_option)
+            file_content = []
+            for line in open(flist).readlines():
+                file_content += __get_items(line)
+            if len(file_content) == 0:
+                raise CliError("Empty file %s" % flist)
+            result.update(file_content)
+        except (AttributeError, TypeError):
+            pass
+        except IOError:
+            raise CliError("Could not open file %s" % flist)
+
+        return list(result), leftover
+
+
 class atest(object):
     """Common class for generic processing
     Should only be instantiated by itself for usage
@@ -255,6 +316,7 @@
         self.kill_on_failure = False
         self.web_server = ''
         self.verbose = False
+        self.topic_parse_info = item_parse_info(attribute_name='not_used')
 
         self.parser = optparse.OptionParser(self._get_usage())
         self.parser.add_option('-g', '--debug',
@@ -279,82 +341,30 @@
                                dest='web_server', default=None)
 
 
-    def _file_list(self, options, opt_file='', opt_list='', add_on=[]):
-        """Returns a list containing the unique items from the
-        options.<opt_list>, from the file options.<opt_file>,
-        and from the space separated add_on strings.
-        The opt_list can be space or comma separated list.
-        Used for host, acls, labels... arguments"""
-        def __get_items(string, split_on='[\s,]\s*'):
-            return [item.strip() for item in re.split(split_on, string)
-                    if item]
-
-        # Start with the add_on
-        result = set()
-        for items in add_on:
-            # Don't split on space here because the add-on
-            # may have some spaces (like the job name)
-            #result.update(item.strip() for item in items.split(',') if item)
-            result.update(__get_items(items, split_on='[,]'))
-
-        # Process the opt_list, if any
-        try:
-            items = getattr(options, opt_list)
-            result.update(__get_items(items))
-        except (AttributeError, TypeError):
-            pass
-
-        # Process the file list, if any and not empty
-        # The file can contain space and/or comma separated items
-        try:
-            flist = getattr(options, opt_file)
-            file_content = []
-            for line in open(flist).readlines():
-                file_content += __get_items(line)
-            if len(file_content) == 0:
-                self.invalid_syntax("Empty file %s" % flist)
-            result.update(file_content)
-        except (AttributeError, TypeError):
-            pass
-        except IOError:
-            self.invalid_syntax("Could not open file %s" % flist)
-
-        return list(result)
-
-
     def _get_usage(self):
         return "atest %s %s [options] %s" % (self.msg_topic.lower(),
                                              self.usage_action,
                                              self.msg_items)
 
 
-    def parse_with_flist(self, flists, req_items):
-        """Flists is a list of tuples containing:
-        (attribute, opt_fname, opt_list, use_leftover)
+    def parse(self, parse_info=[], req_items=None):
+        """parse_info is a list of item_parse_info objects
 
-        self.<atttribute> will be populated with a set
-        containing the lines of the file named
-        options.<opt_fname> and the options.<opt_list> values
-        and the leftover from the parsing if use_leftover is
-        True.  There should only be one use_leftover set to
-        True in the list.
-        Also check if the req_items is not empty after parsing."""
-        (options, leftover) = atest.parse(self)
-        if leftover is None:
-            leftover = []
+        There should only be one use_leftover set to True in the list.
 
-        for (attribute, opt_fname, opt_list, use_leftover) in flists:
-            if use_leftover:
-                add_on = leftover
-                leftover = []
-            else:
-                add_on = []
+        Also check that the req_items is not empty after parsing."""
+        (options, leftover) = self.parse_global()
 
-            setattr(self, attribute,
-                    self._file_list(options,
-                                    opt_file=opt_fname,
-                                    opt_list=opt_list,
-                                    add_on=add_on))
+        all_parse_info = parse_info[:]
+        all_parse_info.append(self.topic_parse_info)
+
+        try:
+            for item_parse_info in all_parse_info:
+                values, leftover = item_parse_info.get_values(options,
+                                                              leftover)
+                setattr(self, item_parse_info.attribute_name, values)
+        except CliError, s:
+            self.invalid_syntax(s)
 
         if (req_items and not getattr(self, req_items, None)):
             self.invalid_syntax('%s %s requires at least one %s' %
@@ -365,8 +375,8 @@
         return (options, leftover)
 
 
-    def parse(self):
-        """Parse all the arguments.
+    def parse_global(self):
+        """Parse the global arguments.
 
         It consumes what the common object needs to know, and
         let the children look at all the options.  We could