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/acl.py b/cli/acl.py
index b5832fd..a6a01df 100755
--- a/cli/acl.py
+++ b/cli/acl.py
@@ -38,14 +38,10 @@
default=None,
metavar='ACL_FLIST')
-
- def parse(self, flists=None, req_items='acls'):
- """Consume the common acl options"""
- if flists:
- flists.append(('acls', 'alist', '', True))
- else:
- flists = [('acls', 'alist', '', True)]
- return self.parse_with_flist(flists, req_items)
+ self.topic_parse_info = topic_common.item_parse_info(
+ attribute_name='acls',
+ filename_option='alist',
+ use_leftover=True)
def get_items(self):
@@ -75,10 +71,13 @@
def parse(self):
- flists = [('users', '', 'user', False),
- ('hosts', '', 'machine', False)]
- (options, leftover) = super(acl_list, self).parse(flists,
- req_items=None)
+ user_info = topic_common.item_parse_info(attribute_name='users',
+ inline_option='user')
+ host_info = topic_common.item_parse_info(attribute_name='hosts',
+ inline_option='machine')
+
+ (options, leftover) = super(acl_list, self).parse([user_info,
+ host_info])
if ((self.users and (self.hosts or self.acls)) or
(self.hosts and self.acls)):
@@ -140,7 +139,7 @@
def parse(self):
- (options, leftover) = super(acl_create, self).parse()
+ (options, leftover) = super(acl_create, self).parse(req_items='acls')
if not options.desc:
self.invalid_syntax('Must specify a description to create an ACL.')
@@ -187,10 +186,15 @@
def parse(self):
- flists = [('users', 'ulist', 'user', False),
- ('hosts', 'mlist', 'machine', False)]
-
- (options, leftover) = super(acl_add_or_remove, self).parse(flists)
+ user_info = topic_common.item_parse_info(attribute_name='users',
+ inline_option='user',
+ filename_option='ulist')
+ host_info = topic_common.item_parse_info(attribute_name='hosts',
+ inline_option='machine',
+ filename_option='mlist')
+ (options, leftover) = super(acl_add_or_remove,
+ self).parse([user_info, host_info],
+ req_items='acls')
if (not getattr(self, 'users', None) and
not getattr(self, 'hosts', None)):
diff --git a/cli/atomicgroup.py b/cli/atomicgroup.py
index 429569b..8384d13 100644
--- a/cli/atomicgroup.py
+++ b/cli/atomicgroup.py
@@ -35,12 +35,10 @@
type='string', default=None,
metavar='ATOMIC_GROUP_FLIST')
-
- def parse(self, flists=None, req_items='atomicgroups'):
- if not flists:
- flists = []
- flists.append(('atomicgroups', 'glist', '', True))
- return self.parse_with_flist(flists, req_items)
+ self.topic_parse_info = topic_common.item_parse_info(
+ attribute_name='atomicgroups',
+ filename_option='glist',
+ use_leftover=True)
def get_items(self):
@@ -62,7 +60,7 @@
def parse(self):
- options, leftover = super(atomicgroup_list, self).parse(req_items=None)
+ options, leftover = super(atomicgroup_list, self).parse()
self.show_invalid = options.show_invalid
return options, leftover
@@ -125,8 +123,13 @@
def parse(self):
- flists = [('labels', 'label_list', 'label', False)]
- options, leftover = super(atomicgroup_add_or_remove, self).parse(flists)
+ label_info = topic_common.item_parse_info(attribute_name='labels',
+ inline_option='label',
+ filename_option='label_list')
+
+ options, leftover = super(atomicgroup_add_or_remove,
+ self).parse([label_info],
+ req_items='atomicgroups')
if not getattr(self, 'labels', None):
self.invalid_syntax('%s %s requires at least one label' %
(self.msg_topic,
diff --git a/cli/cli_mock.py b/cli/cli_mock.py
index c616bee..27b16ac 100755
--- a/cli/cli_mock.py
+++ b/cli/cli_mock.py
@@ -26,12 +26,14 @@
class cli_unittest(unittest.TestCase):
def setUp(self):
+ super(cli_unittest, self).setUp()
self.god = mock.mock_god(debug=CLI_UT_DEBUG)
self.god.stub_class_method(rpc.afe_comm, 'run')
self.god.stub_function(sys, 'exit')
def tearDown(self):
+ super(cli_unittest, self).tearDown()
self.god.unstub_all()
diff --git a/cli/host.py b/cli/host.py
index 35bee49..94c2016 100755
--- a/cli/host.py
+++ b/cli/host.py
@@ -47,14 +47,10 @@
default=None,
metavar='MACHINE_FLIST')
-
- def parse(self, flists=None, req_items='hosts'):
- """Consume the common host options"""
- if flists:
- flists.append(('hosts', 'mlist', '', True))
- else:
- flists = [('hosts', 'mlist', '', True)]
- return self.parse_with_flist(flists, req_items)
+ self.topic_parse_info = topic_common.item_parse_info(
+ attribute_name='hosts',
+ filename_option='mlist',
+ use_leftover=True)
def _parse_lock_options(self, options):
@@ -132,7 +128,7 @@
def parse(self):
"""Consume the specific options"""
- (options, leftover) = super(host_list, self).parse(req_items=None)
+ (options, leftover) = super(host_list, self).parse()
self.labels = options.label
self.status = options.status
self.acl = options.acl
@@ -263,7 +259,7 @@
def parse(self):
"""Consume the specific options"""
- (options, leftover) = super(host_jobs, self).parse(req_items=None)
+ (options, leftover) = super(host_jobs, self).parse()
self.max_queries = options.max_query
return (options, leftover)
@@ -416,9 +412,16 @@
def parse(self):
- flists = [('labels', 'blist', 'labels', False),
- ('acls', 'alist', 'acls', False)]
- (options, leftover) = super(host_create, self).parse(flists)
+ label_info = topic_common.item_parse_info(attribute_name='labels',
+ inline_option='labels',
+ filename_option='blist')
+ acl_info = topic_common.item_parse_info(attribute_name='acls',
+ inline_option='acls',
+ filename_option='alist')
+
+ (options, leftover) = super(host_create, self).parse([label_info,
+ acl_info],
+ req_items='hosts')
self._parse_lock_options(options)
self.locked = options.lock
diff --git a/cli/job.py b/cli/job.py
index 506cc15..ca6aaf5 100755
--- a/cli/job.py
+++ b/cli/job.py
@@ -44,6 +44,14 @@
class job_list_stat(action_common.atest_list, job):
+ def __init__(self):
+ super(job_list_stat, self).__init__()
+
+ self.topic_parse_info = topic_common.item_parse_info(
+ attribute_name='jobs',
+ use_leftover=True)
+
+
def __split_jobs_between_ids_names(self):
job_ids = []
job_names = []
@@ -95,8 +103,7 @@
def parse(self):
- (options, leftover) = self.parse_with_flist([('jobs', '', '', True)],
- None)
+ options, leftover = super(job_list, self).parse()
self.all = options.all
self.data['running'] = options.running
if options.user:
@@ -107,7 +114,7 @@
elif not options.all and not self.jobs:
self.data['owner'] = getpass.getuser()
- return (options, leftover)
+ return options, leftover
def execute(self):
@@ -136,15 +143,13 @@
def parse(self):
- (options, leftover) = self.parse_with_flist(flists=[('jobs', '', '',
- True)],
- req_items='jobs')
+ options, leftover = super(job_stat, self).parse(req_items='jobs')
if not self.jobs:
self.invalid_syntax('Must specify at least one job.')
self.show_control_file = options.control_file
- return (options, leftover)
+ return options, leftover
def _merge_results(self, summary, qes):
@@ -281,10 +286,17 @@
def parse(self):
- flists = [('hosts', 'mlist', 'machine', False),
- ('jobname', '', '', True)]
- (options, leftover) = self.parse_with_flist(flists,
- req_items='jobname')
+ host_info = topic_common.item_parse_info(attribute_name='hosts',
+ inline_option='machine',
+ filename_option='mlist')
+ job_info = topic_common.item_parse_info(attribute_name='jobname',
+ use_leftover=True)
+ oth_info = topic_common.item_parse_info(attribute_name='one_time_hosts',
+ inline_option='one_time_hosts')
+
+ options, leftover = super(job_create,
+ self).parse([host_info, job_info, oth_info],
+ req_items='jobname')
self.data = {}
if len(self.jobname) > 1:
self.invalid_syntax('Too many arguments specified, only expected '
@@ -299,9 +311,9 @@
self.op_action = 'clone'
self.msg_items = 'jobid'
self.reuse_hosts = options.reuse_hosts
- return (options, leftover)
+ return options, leftover
- if (len(self.hosts) == 0 and not options.one_time_hosts
+ if (len(self.hosts) == 0 and not self.one_time_hosts
and not options.labels and not options.atomic_group):
self.invalid_syntax('Must specify at least one machine '
'or an atomic group '
@@ -355,9 +367,8 @@
if options.timeout:
self.data['timeout'] = options.timeout
- if options.one_time_hosts:
- one_time_hosts = self._file_list(options, opt_list='one_time_hosts')
- self.data['one_time_hosts'] = one_time_hosts
+ if self.one_time_hosts:
+ self.data['one_time_hosts'] = self.one_time_hosts
if options.labels:
labels = options.labels.split(',')
labels = [label.strip() for label in labels if label.strip()]
@@ -386,7 +397,7 @@
else:
self.data['control_type'] = 'Client'
- return (options, leftover)
+ return options, leftover
def execute(self):
@@ -473,8 +484,10 @@
msg_done = 'Aborted'
def parse(self):
- (options, leftover) = self.parse_with_flist([('jobids', '', '', True)],
- req_items='jobids')
+ job_info = topic_common.item_parse_info(attribute_name='jobids',
+ use_leftover=True)
+ options, leftover = super(job_abort, self).parse([job_info],
+ req_items='jobids')
def execute(self):
diff --git a/cli/label.py b/cli/label.py
index a4d6ac2..244f795 100755
--- a/cli/label.py
+++ b/cli/label.py
@@ -38,14 +38,10 @@
default=None,
metavar='LABEL_FLIST')
-
- def parse(self, flists=None, req_items='labels'):
- """Consume the common label options"""
- if flists:
- flists.append(('labels', 'blist', '', True))
- else:
- flists = [('labels', 'blist', '', True)]
- return self.parse_with_flist(flists, req_items)
+ self.topic_parse_info = topic_common.item_parse_info(
+ attribute_name='labels',
+ filename_option='blist',
+ use_leftover=True)
def get_items(self):
@@ -85,9 +81,9 @@
def parse(self):
- flists = [('hosts', '', 'machine', False)]
- (options, leftover) = super(label_list, self).parse(flists,
- req_items=None)
+ host_info = topic_common.item_parse_info(attribute_name='hosts',
+ inline_option='machine')
+ (options, leftover) = super(label_list, self).parse([host_info])
if options.all and options.platform_only:
self.invalid_syntax('Only specify one of --all,'
@@ -154,7 +150,8 @@
def parse(self):
- (options, leftover) = super(label_create, self).parse()
+ (options, leftover) = super(label_create,
+ self).parse(req_items='labels')
self.data_item_key = 'name'
self.data['platform'] = options.platform
self.data['only_if_needed'] = options.only_if_needed
@@ -184,8 +181,13 @@
def parse(self):
- flists = [('hosts', 'mlist', 'machine', False)]
- (options, leftover) = super(label_add_or_remove, self).parse(flists)
+ host_info = topic_common.item_parse_info(attribute_name='hosts',
+ inline_option='machine',
+ filename_option='mlist')
+ (options, leftover) = super(label_add_or_remove,
+ self).parse([host_info],
+ req_items='labels')
+
if not getattr(self, 'hosts', None):
self.invalid_syntax('%s %s requires at least one host' %
(self.msg_topic,
diff --git a/cli/test.py b/cli/test.py
index 5767889..ac1605a 100755
--- a/cli/test.py
+++ b/cli/test.py
@@ -37,10 +37,10 @@
default=None,
metavar='TEST_FLIST')
-
- def parse(self, req_items=None):
- """Consume the common test options"""
- return self.parse_with_flist([('tests', 'blist', '', True)], req_items)
+ self.topic_parse_info = topic_common.item_parse_info(
+ attribute_name='tests',
+ filename_option='tlist',
+ use_leftover=True)
def get_items(self):
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
diff --git a/cli/topic_common_unittest.py b/cli/topic_common_unittest.py
index 99b516d..972f22d 100755
--- a/cli/topic_common_unittest.py
+++ b/cli/topic_common_unittest.py
@@ -10,9 +10,227 @@
from autotest_lib.cli import cli_mock, topic_common, rpc
from autotest_lib.frontend.afe.json_rpc import proxy
-class topic_common_unittest(cli_mock.cli_unittest):
+
+class item_parse_info_unittest(cli_mock.cli_unittest):
+ def __test_parsing_flist_bad(self, options):
+ parse_info = topic_common.item_parse_info
+ test_parse_info = parse_info(attribute_name='testing',
+ filename_option='flist')
+ self.assertRaises(topic_common.CliError,
+ test_parse_info.get_values, options, [])
+
+
+ def __test_parsing_flist_good(self, options, expected):
+ parse_info = topic_common.item_parse_info
+ test_parse_info = parse_info(attribute_name='testing',
+ filename_option='flist')
+ result, leftover = test_parse_info.get_values(options, [])
+
+ self.assertEqualNoOrder(expected, result)
+ os.unlink(options.flist)
+
+
+ def __test_parsing_inline_good(self, options, expected):
+ parse_info = topic_common.item_parse_info
+ test_parse_info = parse_info(attribute_name='testing',
+ inline_option='inline')
+ result, leftover = test_parse_info.get_values(options, [])
+
+ self.assertEqualNoOrder(expected, result)
+
+
+ def __test_parsing_leftover_good(self, leftover, expected):
+ class opt(object):
+ pass
+ parse_info = topic_common.item_parse_info
+ test_parse_info = parse_info(attribute_name='testing',
+ inline_option='inline',
+ use_leftover=True)
+ result, leftover = test_parse_info.get_values(opt(), leftover)
+
+ self.assertEqualNoOrder(expected, result)
+
+
+ def __test_parsing_all_good(self, options, leftover, expected):
+ parse_info = topic_common.item_parse_info
+ test_parse_info = parse_info(attribute_name='testing',
+ inline_option='inline',
+ filename_option='flist',
+ use_leftover=True)
+ result, leftover = test_parse_info.get_values(options, leftover)
+
+ self.assertEqualNoOrder(expected, result)
+ os.unlink(options.flist)
+
+
+ def __test_parsing_all_bad(self, options, leftover):
+ parse_info = topic_common.item_parse_info
+ test_parse_info = parse_info(attribute_name='testing',
+ inline_option='inline',
+ filename_option='flist',
+ use_leftover=True)
+ self.assertRaises(topic_common.CliError,
+ test_parse_info.get_values, options, leftover)
+
+
+ def test_file_list_wrong_file(self):
+ class opt(object):
+ flist = './does_not_exist'
+ self.__test_parsing_flist_bad(opt())
+
+
+ def test_file_list_empty_file(self):
+ class opt(object):
+ flist = cli_mock.create_file('')
+ self.__test_parsing_flist_bad(opt())
+
+
+ def test_file_list_ok(self):
+ class opt(object):
+ flist = cli_mock.create_file('a\nb\nc\n')
+ self.__test_parsing_flist_good(opt(), ['a', 'b', 'c'])
+
+
+ def test_file_list_one_line_space(self):
+ class opt(object):
+ flist = cli_mock.create_file('a b c\nd e\nf\n')
+ self.__test_parsing_flist_good(opt(), ['a', 'b', 'c', 'd', 'e', 'f'])
+
+
+ def test_file_list_one_line_comma(self):
+ class opt(object):
+ flist = cli_mock.create_file('a,b,c\nd,e\nf\n')
+ self.__test_parsing_flist_good(opt(), ['a', 'b', 'c', 'd', 'e', 'f'])
+
+
+ def test_file_list_one_line_mix(self):
+ class opt(object):
+ flist = cli_mock.create_file('a,b c\nd,e\nf\ng h,i')
+ self.__test_parsing_flist_good(opt(), ['a', 'b', 'c', 'd', 'e',
+ 'f', 'g', 'h', 'i'])
+
+
+ def test_file_list_one_line_comma_space(self):
+ class opt(object):
+ flist = cli_mock.create_file('a, b c\nd,e\nf\ng h,i')
+ self.__test_parsing_flist_good(opt(), ['a', 'b', 'c', 'd', 'e',
+ 'f', 'g', 'h', 'i'])
+
+
+ def test_file_list_line_end_comma_space(self):
+ class opt(object):
+ flist = cli_mock.create_file('a, b c\nd,e, \nf,\ng h,i ,')
+ self.__test_parsing_flist_good(opt(), ['a', 'b', 'c', 'd', 'e',
+ 'f', 'g', 'h', 'i'])
+
+
+ def test_file_list_no_eof(self):
+ class opt(object):
+ flist = cli_mock.create_file('a\nb\nc')
+ self.__test_parsing_flist_good(opt(), ['a', 'b', 'c'])
+
+
+ def test_file_list_blank_line(self):
+ class opt(object):
+ flist = cli_mock.create_file('\na\nb\n\nc\n')
+ self.__test_parsing_flist_good(opt(), ['a', 'b', 'c'])
+
+
+ def test_file_list_opt_list_one(self):
+ class opt(object):
+ inline = 'a'
+ self.__test_parsing_inline_good(opt(), ['a'])
+
+
+ def test_file_list_opt_list_space(self):
+ class opt(object):
+ inline = 'a b c'
+ self.__test_parsing_inline_good(opt(), ['a', 'b', 'c'])
+
+
+ def test_file_list_opt_list_mix_space_comma(self):
+ class opt(object):
+ inline = 'a b,c,d e'
+ self.__test_parsing_inline_good(opt(), ['a', 'b', 'c', 'd', 'e'])
+
+
+ def test_file_list_opt_list_mix_comma_space(self):
+ class opt(object):
+ inline = 'a b,c, d e'
+ self.__test_parsing_inline_good(opt(), ['a', 'b', 'c', 'd', 'e'])
+
+
+ def test_file_list_opt_list_end_comma_space(self):
+ class opt(object):
+ inline = 'a b, ,c,, d e, '
+ self.__test_parsing_inline_good(opt(), ['a', 'b', 'c', 'd', 'e'])
+
+
+ def test_file_list_add_on_space(self):
+ self.__test_parsing_leftover_good(['a','c','b'],
+ ['a', 'b', 'c'])
+
+
+ def test_file_list_add_on_mix_space_comma(self):
+ self.__test_parsing_leftover_good(['a', 'c','b,d'],
+ ['a', 'b', 'c', 'd'])
+
+
+ def test_file_list_add_on_mix_comma_space(self):
+ self.__test_parsing_leftover_good(['a', 'c', 'b,', 'd'],
+ ['a', 'b', 'c', 'd'])
+
+
+ def test_file_list_add_on_end_comma_space(self):
+ self.__test_parsing_leftover_good(['a', 'c', 'b,', 'd,', ','],
+ ['a', 'b', 'c', 'd'])
+
+
+ def test_file_list_all_opt(self):
+ class opt(object):
+ flist = cli_mock.create_file('f\ng\nh\n')
+ inline = 'a b,c,d e'
+ self.__test_parsing_all_good(opt(), ['i', 'j'],
+ ['a', 'b', 'c', 'd', 'e',
+ 'f', 'g', 'h', 'i', 'j'])
+
+
+ def test_file_list_all_opt_empty_file(self):
+ class opt(object):
+ flist = cli_mock.create_file('')
+ inline = 'a b,c,d e'
+ self.__test_parsing_all_bad(opt(), ['i', 'j'])
+
+
+ def test_file_list_all_opt_in_common(self):
+ class opt(object):
+ flist = cli_mock.create_file('f\nc\na\n')
+ inline = 'a b,c,d e'
+ self.__test_parsing_all_good(opt(), ['i','j,d'],
+ ['a', 'b', 'c', 'd', 'e', 'f', 'i', 'j'])
+
+
+ def test_file_list_all_opt_in_common_space(self):
+ class opt(object):
+ flist = cli_mock.create_file('a b c\nd,e\nf\ng')
+ inline = 'a b,c,d h'
+ self.__test_parsing_all_good(opt(), ['i','j,d'],
+ ['a', 'b', 'c', 'd', 'e',
+ 'f', 'g', 'h', 'i', 'j'])
+
+
+ def test_file_list_all_opt_in_common_weird(self):
+ class opt(object):
+ flist = cli_mock.create_file('a b c\nd,e\nf\ng, \n, ,,')
+ inline = 'a b,c,d h, , ,, '
+ self.__test_parsing_all_good(opt(), ['i','j,d'],
+ ['a', 'b', 'c', 'd', 'e',
+ 'f', 'g', 'h', 'i', 'j'])
+
+
+class atest_unittest(cli_mock.cli_unittest):
def setUp(self):
- super(topic_common_unittest, self).setUp()
+ super(atest_unittest, self).setUp()
self.atest = topic_common.atest()
self.atest.afe = rpc.afe_comm()
if 'AUTOTEST_WEB' in os.environ:
@@ -21,270 +239,7 @@
def tearDown(self):
self.atest = None
- super(topic_common_unittest, self).tearDown()
-
-
- def test_file_list_wrong_file(self):
- self.god.mock_io()
- class opt(object):
- mlist = './does_not_exist'
- options = opt()
- sys.exit.expect_call(1).and_raises(cli_mock.ExitException)
- self.assertRaises(cli_mock.ExitException,
- self.atest._file_list, options, opt_file='mlist')
- self.god.check_playback()
- (output, err) = self.god.unmock_io()
- self.assert_(err.find('./does_not_exist') >= 0)
-
-
- def test_file_list_empty_file(self):
- self.god.mock_io()
- class opt(object):
- flist = cli_mock.create_file('')
- options = opt()
- sys.exit.expect_call(1).and_raises(cli_mock.ExitException)
- self.assertRaises(cli_mock.ExitException,
- self.atest._file_list, options, opt_file='flist')
- self.god.check_playback()
- (output, err) = self.god.unmock_io()
- self.assert_(err.find(options.flist) >= 0)
-
-
- def test_file_list_ok(self):
- class opt(object):
- filename = cli_mock.create_file('a\nb\nc\n')
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c'],
- self.atest._file_list(options,
- opt_file='filename'))
- os.unlink(options.filename)
-
-
- def test_file_list_one_line_space(self):
- class opt(object):
- filename = cli_mock.create_file('a b c\nd e\nf\n')
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e', 'f'],
- self.atest._file_list(options,
- opt_file='filename'))
- os.unlink(options.filename)
-
-
- def test_file_list_one_line_comma(self):
- class opt(object):
- filename = cli_mock.create_file('a,b,c\nd,e\nf\n')
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e', 'f'],
- self.atest._file_list(options,
- opt_file='filename'))
- os.unlink(options.filename)
-
-
- def test_file_list_one_line_mix(self):
- class opt(object):
- filename = cli_mock.create_file('a,b c\nd,e\nf\ng h,i')
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e',
- 'f', 'g', 'h', 'i'],
- self.atest._file_list(options,
- opt_file='filename'))
- os.unlink(options.filename)
-
-
- def test_file_list_one_line_comma_space(self):
- class opt(object):
- filename = cli_mock.create_file('a, b c\nd,e\nf\ng h,i')
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e',
- 'f', 'g', 'h', 'i'],
- self.atest._file_list(options,
- opt_file='filename'))
- os.unlink(options.filename)
-
-
- def test_file_list_line_end_comma_space(self):
- class opt(object):
- filename = cli_mock.create_file('a, b c\nd,e, \nf,\ng h,i ,')
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e',
- 'f', 'g', 'h', 'i'],
- self.atest._file_list(options,
- opt_file='filename'))
- os.unlink(options.filename)
-
-
- def test_file_list_no_eof(self):
- class opt(object):
- filename = cli_mock.create_file('a\nb\nc')
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c'],
- self.atest._file_list(options,
- opt_file='filename'))
- os.unlink(options.filename)
-
-
- def test_file_list_blank_line(self):
- class opt(object):
- filename = cli_mock.create_file('\na\nb\n\nc\n')
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c'],
- self.atest._file_list(options,
- opt_file='filename'))
- os.unlink(options.filename)
-
-
- def test_file_list_opt_list_one(self):
- class opt(object):
- hlist = 'a'
- options = opt()
- self.assertEqualNoOrder(['a'],
- self.atest._file_list(options,
- opt_list='hlist'))
-
-
- def test_file_list_opt_list_space(self):
- class opt(object):
- hlist = 'a b c'
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c'],
- self.atest._file_list(options,
- opt_list='hlist'))
-
-
- def test_file_list_opt_list_mix_space_comma(self):
- class opt(object):
- alist = 'a b,c,d e'
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e'],
- self.atest._file_list(options,
- opt_list='alist'))
-
-
- def test_file_list_opt_list_mix_comma_space(self):
- class opt(object):
- alist = 'a b,c, d e'
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e'],
- self.atest._file_list(options,
- opt_list='alist'))
-
-
- def test_file_list_opt_list_end_comma_space(self):
- class opt(object):
- alist = 'a b, ,c,, d e, '
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e'],
- self.atest._file_list(options,
- opt_list='alist'))
-
-
- def test_file_list_add_on_space(self):
- class opt(object):
- pass
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c'],
- self.atest._file_list(options,
- add_on=['a','c','b']))
-
-
- def test_file_list_add_on_mix_space_comma(self):
- class opt(object):
- pass
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd'],
- self.atest._file_list(options,
- add_on=['a', 'c',
- 'b,d']))
-
-
- def test_file_list_add_on_mix_comma_space(self):
- class opt(object):
- pass
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd'],
- self.atest._file_list(options,
- add_on=['a', 'c',
- 'b,', 'd']))
-
-
- def test_file_list_add_on_end_comma_space(self):
- class opt(object):
- pass
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd'],
- self.atest._file_list(options,
- add_on=['a', 'c', 'b,',
- 'd,', ',']))
-
-
- def test_file_list_all_opt(self):
- class opt(object):
- afile = cli_mock.create_file('f\ng\nh\n')
- alist = 'a b,c,d e'
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e',
- 'f', 'g', 'h', 'i', 'j'],
- self.atest._file_list(options,
- opt_file='afile',
- opt_list='alist',
- add_on=['i', 'j']))
-
-
- def test_file_list_all_opt_empty_file(self):
- self.god.mock_io()
- class opt(object):
- hfile = cli_mock.create_file('')
- hlist = 'a b,c,d e'
- options = opt()
- sys.exit.expect_call(1).and_raises(cli_mock.ExitException)
- self.assertRaises(cli_mock.ExitException,
- self.atest._file_list,
- options,
- opt_file='hfile',
- opt_list='hlist',
- add_on=['i', 'j'])
- (output, err) = self.god.unmock_io()
- self.god.check_playback()
- self.assert_(err.find(options.hfile) >= 0)
-
-
- def test_file_list_all_opt_in_common(self):
- class opt(object):
- afile = cli_mock.create_file('f\nc\na\n')
- alist = 'a b,c,d e'
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e',
- 'f', 'i', 'j'],
- self.atest._file_list(options,
- opt_file='afile',
- opt_list='alist',
- add_on=['i','j,d']))
-
-
- def test_file_list_all_opt_in_common_space(self):
- class opt(object):
- afile = cli_mock.create_file('a b c\nd,e\nf\ng')
- alist = 'a b,c,d h'
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e',
- 'f', 'g', 'h', 'i', 'j'],
- self.atest._file_list(options,
- opt_file='afile',
- opt_list='alist',
- add_on=['i','j,d']))
-
-
- def test_file_list_all_opt_in_common_weird(self):
- class opt(object):
- afile = cli_mock.create_file('a b c\nd,e\nf\ng, \n, ,,')
- alist = 'a b,c,d h, , ,, '
- options = opt()
- self.assertEqualNoOrder(['a', 'b', 'c', 'd', 'e',
- 'f', 'g', 'h', 'i', 'j'],
- self.atest._file_list(options,
- opt_file='afile',
- opt_list='alist',
- add_on=['i','j,d']))
+ super(atest_unittest, self).tearDown()
def test_invalid_arg_kill(self):
@@ -411,16 +366,15 @@
'This is partly bad', 'item0', 'item1'])
- def test_parse_with_flist_add_on(self):
+ def test_parse_add_on(self):
flist = cli_mock.create_file('host1\nhost2\nleft2')
sys.argv = ['atest', '--web', 'fooweb', '--parse',
'--kill-on-failure', 'left1', 'left2', '-M', flist]
self.atest.parser.add_option('-M', '--mlist', type='string')
- (options, leftover) = self.atest.parse_with_flist([('hosts',
- 'mlist',
- [],
- True)],
- None)
+ item_info = topic_common.item_parse_info(attribute_name='hosts',
+ filename_option='mlist',
+ use_leftover=True)
+ (options, leftover) = self.atest.parse([item_info])
self.assertEqualNoOrder(self.atest.hosts,
['left1', 'left2', 'host1', 'host2'])
@@ -434,16 +388,14 @@
self.assertEqual(leftover, [])
- def test_parse_with_flist_no_add_on(self):
+ def test_parse_no_add_on(self):
flist = cli_mock.create_file('host1\nhost2\nleft2')
sys.argv = ['atest', '--web', 'fooweb', '--parse', '-g',
'--kill-on-failure', 'left1', 'left2', '-M', flist]
self.atest.parser.add_option('-M', '--mlist', type='string')
- (options, leftover) = self.atest.parse_with_flist([('hosts',
- 'mlist',
- [],
- False)],
- None)
+ item_info = topic_common.item_parse_info(attribute_name='hosts',
+ filename_option='mlist')
+ (options, leftover) = self.atest.parse([item_info])
self.assertEqualNoOrder(self.atest.hosts,
['left2', 'host1', 'host2'])
@@ -457,7 +409,7 @@
self.assertEqual(leftover, ['left1', 'left2'])
- def test_parse_with_flists_add_on_first(self):
+ def test_parse_add_on_first(self):
flist = cli_mock.create_file('host1\nhost2\nleft2')
ulist = cli_mock.create_file('user1\nuser2\nuser3\n')
sys.argv = ['atest', '-g', '--parse', '--ulist', ulist,
@@ -466,15 +418,14 @@
self.atest.parser.add_option('-M', '--mlist', type='string')
self.atest.parser.add_option('-U', '--ulist', type='string')
self.atest.parser.add_option('-u', '--user', type='string')
- (options, leftover) = self.atest.parse_with_flist([('hosts',
- 'mlist',
- '',
- True),
- ('users',
- 'ulist',
- 'user',
- False)],
- None)
+ host_info = topic_common.item_parse_info(attribute_name='hosts',
+ filename_option='mlist',
+ use_leftover=True)
+ user_info = topic_common.item_parse_info(attribute_name='users',
+ inline_option='user',
+ filename_option='ulist')
+
+ (options, leftover) = self.atest.parse([host_info, user_info])
self.assertEqualNoOrder(self.atest.hosts,
['left1', 'left2', 'host1', 'host2'])
self.assertEqualNoOrder(self.atest.users,
@@ -493,7 +444,7 @@
self.assertEqual(leftover, [])
- def test_parse_with_flists_add_on_second(self):
+ def test_parse_add_on_second(self):
flist = cli_mock.create_file('host1\nhost2\nleft2')
ulist = cli_mock.create_file('user1\nuser2\nuser3\n')
sys.argv = ['atest', '-g', '--parse', '-U', ulist,
@@ -502,15 +453,14 @@
self.atest.parser.add_option('-M', '--mlist', type='string')
self.atest.parser.add_option('-U', '--ulist', type='string')
self.atest.parser.add_option('-u', '--user', type='string')
- (options, leftover) = self.atest.parse_with_flist([('users',
- 'ulist',
- 'user',
- False),
- ('hosts',
- 'mlist',
- '',
- True)],
- None)
+ host_info = topic_common.item_parse_info(attribute_name='hosts',
+ filename_option='mlist',
+ use_leftover=True)
+ user_info = topic_common.item_parse_info(attribute_name='users',
+ inline_option='user',
+ filename_option='ulist')
+ (options, leftover) = self.atest.parse([host_info, user_info])
+
self.assertEqualNoOrder(self.atest.hosts,
['left1', 'left2', 'host1', 'host2'])
self.assertEqualNoOrder(self.atest.users,
@@ -529,7 +479,7 @@
self.assertEqual(leftover, [])
- def test_parse_with_flists_all_opts(self):
+ def test_parse_all_opts(self):
flist = cli_mock.create_file('host1\nhost2\nleft2')
ulist = cli_mock.create_file('user1\nuser2\nuser3\n')
sys.argv = ['atest', '-g', '--parse', '--ulist', ulist,
@@ -538,15 +488,13 @@
self.atest.parser.add_option('-M', '--mlist', type='string')
self.atest.parser.add_option('-U', '--ulist', type='string')
self.atest.parser.add_option('-u', '--user', type='string')
- (options, leftover) = self.atest.parse_with_flist([('users',
- 'ulist',
- 'user',
- False),
- ('hosts',
- 'mlist',
- '',
- True)],
- None)
+ host_info = topic_common.item_parse_info(attribute_name='hosts',
+ filename_option='mlist',
+ use_leftover=True)
+ user_info = topic_common.item_parse_info(attribute_name='users',
+ inline_option='user',
+ filename_option='ulist')
+ (options, leftover) = self.atest.parse([host_info, user_info])
self.assertEqualNoOrder(self.atest.hosts,
['left1', 'left2', 'host1', 'host2'])
self.assertEqualNoOrder(self.atest.users,
@@ -565,7 +513,7 @@
self.assertEqual(leftover, [])
- def test_parse_with_flists_no_add_on(self):
+ def test_parse_no_add_on(self):
flist = cli_mock.create_file('host1\nhost2\nleft2')
ulist = cli_mock.create_file('user1\nuser2\nuser3\n')
sys.argv = ['atest', '-U', ulist,
@@ -573,15 +521,13 @@
self.atest.parser.add_option('-M', '--mlist', type='string')
self.atest.parser.add_option('-U', '--ulist', type='string')
self.atest.parser.add_option('-u', '--user', type='string')
- (options, leftover) = self.atest.parse_with_flist([('hosts',
- 'mlist',
- '',
- False),
- ('users',
- 'ulist',
- 'user',
- False)],
- None)
+ host_info = topic_common.item_parse_info(attribute_name='hosts',
+ filename_option='mlist',
+ use_leftover=True)
+ user_info = topic_common.item_parse_info(attribute_name='users',
+ inline_option='user',
+ filename_option='ulist')
+ (options, leftover) = self.atest.parse([host_info, user_info])
self.assertEqualNoOrder(self.atest.hosts,
['left2', 'host1', 'host2'])
self.assertEqualNoOrder(self.atest.users,
@@ -599,21 +545,17 @@
self.assertEqual(leftover, [])
- def test_parse_with_flists_no_flist_add_on(self):
+ def test_parse_no_flist_add_on(self):
sys.argv = ['atest', '-g', '--parse', '-u', 'myuser,youruser',
'--kill-on-failure', 'left1', 'left2']
self.atest.parser.add_option('-M', '--mlist', type='string')
self.atest.parser.add_option('-U', '--ulist', type='string')
self.atest.parser.add_option('-u', '--user', type='string')
- (options, leftover) = self.atest.parse_with_flist([('users',
- '',
- 'user',
- False),
- ('hosts',
- '',
- '',
- True)],
- None)
+ host_info = topic_common.item_parse_info(attribute_name='hosts',
+ use_leftover=True)
+ user_info = topic_common.item_parse_info(attribute_name='users',
+ inline_option='user')
+ (options, leftover) = self.atest.parse([host_info, user_info])
self.assertEqualNoOrder(self.atest.hosts,
['left1', 'left2'])
self.assertEqualNoOrder(self.atest.users,
@@ -631,20 +573,16 @@
self.assertEqual(leftover, [])
- def test_parse_with_flists_no_flist_no_add_on(self):
+ def test_parse_no_flist_no_add_on(self):
sys.argv = ['atest', '-u', 'myuser,youruser', '--kill-on-failure',
'-a', 'acl1,acl2']
self.atest.parser.add_option('-u', '--user', type='string')
self.atest.parser.add_option('-a', '--acl', type='string')
- (options, leftover) = self.atest.parse_with_flist([('users',
- '',
- 'user',
- False),
- ('acls',
- '',
- 'acl',
- False)],
- None)
+ acl_info = topic_common.item_parse_info(attribute_name='acls',
+ inline_option='acl')
+ user_info = topic_common.item_parse_info(attribute_name='users',
+ inline_option='user')
+ (options, leftover) = self.atest.parse([user_info, acl_info])
self.assertEqualNoOrder(self.atest.acls,
['acl1', 'acl2'])
self.assertEqualNoOrder(self.atest.users,
@@ -661,14 +599,13 @@
self.assertEqual(leftover, [])
- def test_parse_with_flists_req_items_ok(self):
+ def test_parse_req_items_ok(self):
sys.argv = ['atest', '-u', 'myuser,youruser']
self.atest.parser.add_option('-u', '--user', type='string')
- (options, leftover) = self.atest.parse_with_flist([('users',
- '',
- 'user',
- False)],
- 'users')
+ user_info = topic_common.item_parse_info(attribute_name='users',
+ inline_option='user')
+ (options, leftover) = self.atest.parse([user_info],
+ req_items='users')
self.assertEqualNoOrder(self.atest.users,
['myuser', 'youruser'])
@@ -682,15 +619,18 @@
self.assertEqual(leftover, [])
- def test_parse_with_flists_req_items_missing(self):
+ def test_parse_req_items_missing(self):
sys.argv = ['atest', '-u', 'myuser,youruser', '--kill-on-failure']
self.atest.parser.add_option('-u', '--user', type='string')
+ acl_info = topic_common.item_parse_info(attribute_name='acls',
+ inline_option='acl')
+ user_info = topic_common.item_parse_info(attribute_name='users',
+ inline_option='user')
self.god.mock_io()
sys.exit.expect_call(1).and_raises(cli_mock.ExitException)
self.assertRaises(cli_mock.ExitException,
- self.atest.parse_with_flist,
- [('users', '', 'user', False),
- ('acls', '', 'acl', False)],
+ self.atest.parse,
+ [user_info, acl_info],
'acls')
self.assertEqualNoOrder(self.atest.users,
['myuser', 'youruser'])
diff --git a/cli/user.py b/cli/user.py
index 8257c79..0e4fd49 100755
--- a/cli/user.py
+++ b/cli/user.py
@@ -36,14 +36,10 @@
default=None,
metavar='USER_FLIST')
-
- def parse(self, flists=None, req_items='users'):
- """Consume the common user options"""
- if flists:
- flists.append(('users', 'ulist', '', True))
- else:
- flists = [('users', 'ulist', '', True)]
- return self.parse_with_flist(flists, req_items)
+ self.topic_parse_info = topic_common.item_parse_info(
+ attribute_name='users',
+ filename_option='ulist',
+ use_leftover=True)
def get_items(self):
@@ -70,7 +66,7 @@
def parse(self):
- (options, leftover) = super(user_list, self).parse(req_items=None)
+ (options, leftover) = super(user_list, self).parse()
self.acl = options.acl
self.access_level = options.access_level
return (options, leftover)