16f455262ded933c1699fea410a9ddaf967df6330Aviv Keshet# pylint: disable-msg=C0111
299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh# Copyright 2008 Google Inc. Released under the GPL v2
399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
489d5d21ec72e55ca0ca9e50d488210e2c5bb34e7J. Richard Barnetteimport warnings
589d5d21ec72e55ca0ca9e50d488210e2c5bb34e7J. Richard Barnettewith warnings.catch_warnings():
689d5d21ec72e55ca0ca9e50d488210e2c5bb34e7J. Richard Barnette    # The 'compiler' module is gone in Python 3.0.  Let's not say
789d5d21ec72e55ca0ca9e50d488210e2c5bb34e7J. Richard Barnette    # so in every log file.
889d5d21ec72e55ca0ca9e50d488210e2c5bb34e7J. Richard Barnette    warnings.simplefilter("ignore", DeprecationWarning)
989d5d21ec72e55ca0ca9e50d488210e2c5bb34e7J. Richard Barnette    import compiler
1089d5d21ec72e55ca0ca9e50d488210e2c5bb34e7J. Richard Barnetteimport logging, textwrap
1199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
12ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shifrom autotest_lib.client.common_lib import enum
1399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
148ad52b6b61905f9f6b05af76e9607cdd29c038d0Scott ZawalskiREQUIRED_VARS = set(['author', 'doc', 'name', 'time', 'test_type'])
154238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard BarnetteOBSOLETE_VARS = set(['experimental'])
1699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
173dd8beb386f7298ffe84d7410d00cce26973e170Aviv KeshetCONTROL_TYPE = enum.Enum('Server', 'Client', start_value=1)
183dd8beb386f7298ffe84d7410d00cce26973e170Aviv KeshetCONTROL_TYPE_NAMES =  enum.Enum(*CONTROL_TYPE.names, string_values=True)
193dd8beb386f7298ffe84d7410d00cce26973e170Aviv Keshet
2099c2c6f54e962fe4e7701cd9aaa645fdabacd203mblighclass ControlVariableException(Exception):
2199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    pass
2299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
2399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
2499c2c6f54e962fe4e7701cd9aaa645fdabacd203mblighclass ControlData(object):
25ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi    # Available TIME settings in control file, the list must be in lower case
26ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi    # and in ascending order, test running faster comes first.
27ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi    TEST_TIME_LIST = ['fast', 'short', 'medium', 'long', 'lengthy']
28ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi    TEST_TIME = enum.Enum(*TEST_TIME_LIST, string_values=False)
29ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi
30ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi    @staticmethod
31ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi    def get_test_time_index(time):
32ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi        """
33ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi        Get the order of estimated test time, based on the TIME setting in
34ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi        Control file. Faster test gets a lower index number.
35ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi        """
36ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi        try:
37ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi            return ControlData.TEST_TIME.get_value(time.lower())
38ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi        except AttributeError:
39ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi            # Raise exception if time value is not a valid TIME setting.
40ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi            error_msg = '%s is not a valid TIME.' % time
41ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi            logging.error(error_msg)
42ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi            raise ControlVariableException(error_msg)
43ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi
44ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi
45d7cd983031fc77a247d022aef67b481892681ddcmbligh    def __init__(self, vars, path, raise_warnings=False):
4699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        # Defaults
47d7cd983031fc77a247d022aef67b481892681ddcmbligh        self.path = path
4899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self.dependencies = set()
494238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette        # TODO(jrbarnette): This should be removed once outside
504238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette        # code that uses can be changed.
5199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self.experimental = False
5299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self.run_verify = True
5399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self.sync_count = 1
54861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        self.test_parameters = set()
558ad52b6b61905f9f6b05af76e9607cdd29c038d0Scott Zawalski        self.test_category = ''
568ad52b6b61905f9f6b05af76e9607cdd29c038d0Scott Zawalski        self.test_class = ''
576f455262ded933c1699fea410a9ddaf967df6330Aviv Keshet        self.retries = 0
58e3bc24b7b77480d4bb0b1562bb30ea79eff85626Fang Deng        self.job_retries = 0
59ec1d47d85cc83f30631518d8fbb6406036a3ac39Dan Shi        # Default to require server-side package. Unless require_ssp is
60ec1d47d85cc83f30631518d8fbb6406036a3ac39Dan Shi        # explicitly set to False, server-side package will be used for the
61ec1d47d85cc83f30631518d8fbb6406036a3ac39Dan Shi        # job. This can be overridden by global config
62ec1d47d85cc83f30631518d8fbb6406036a3ac39Dan Shi        # AUTOSERV/enable_ssp_container
63ec1d47d85cc83f30631518d8fbb6406036a3ac39Dan Shi        self.require_ssp = None
6413248c5b1b6978647bc8ae040db6b221f488a7e0Shuqian Zhao        self.attributes = set()
6599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
6699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        diff = REQUIRED_VARS - set(vars)
674238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette        if diff:
684238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette            warning = ('WARNING: Not all required control '
694238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette                       'variables were specified in %s.  Please define '
704238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette                       '%s.') % (self.path, ', '.join(diff))
714238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette            if raise_warnings:
724238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette                raise ControlVariableException(warning)
734238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette            print textwrap.wrap(warning, 80)
744238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette
754238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette        obsolete = OBSOLETE_VARS & set(vars)
764238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette        if obsolete:
774238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette            warning = ('WARNING: Obsolete variables were '
784238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette                       'specified in %s.  Please remove '
794238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette                       '%s.') % (self.path, ', '.join(obsolete))
8099c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            if raise_warnings:
8199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh                raise ControlVariableException(warning)
8299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            print textwrap.wrap(warning, 80)
8399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
8499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        for key, val in vars.iteritems():
8599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            try:
8699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh                self.set_attr(key, val, raise_warnings)
8799c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            except Exception, e:
8899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh                if raise_warnings:
8999c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh                    raise
904238478cce8e1c0ddd29748be570abba5b6e9fc6J. Richard Barnette                print 'WARNING: %s; skipping' % e
9199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
9299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
9399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_attr(self, attr, val, raise_warnings=False):
9499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        attr = attr.lower()
9599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        try:
9699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            set_fn = getattr(self, 'set_%s' % attr)
9799c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            set_fn(val)
9899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        except AttributeError:
9999c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            # This must not be a variable we care about
10099c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            pass
10199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
10299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
10399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def _set_string(self, attr, val):
10499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        val = str(val)
10599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        setattr(self, attr, val)
10699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
10799c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
10899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def _set_option(self, attr, val, options):
10999c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        val = str(val)
11099c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        if val.lower() not in [x.lower() for x in options]:
11199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            raise ValueError("%s must be one of the following "
11299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh                             "options: %s" % (attr,
11399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh                             ', '.join(options)))
11499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        setattr(self, attr, val)
11599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
11699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
11799c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def _set_bool(self, attr, val):
11899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        val = str(val).lower()
11999c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        if val == "false":
12099c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            val = False
12199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        elif val == "true":
12299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            val = True
12399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        else:
12499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            msg = "%s must be either true or false" % attr
12599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            raise ValueError(msg)
12699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        setattr(self, attr, val)
12799c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
12899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
12999c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def _set_int(self, attr, val, min=None, max=None):
13099c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        val = int(val)
13199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        if min is not None and min > val:
13299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            raise ValueError("%s is %d, which is below the "
13399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh                             "minimum of %d" % (attr, val, min))
13499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        if max is not None and max < val:
13599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh            raise ValueError("%s is %d, which is above the "
13699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh                             "maximum of %d" % (attr, val, max))
13799c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        setattr(self, attr, val)
13899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
13999c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
14099c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def _set_set(self, attr, val):
14199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        val = str(val)
14299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        items = [x.strip() for x in val.split(',')]
14399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        setattr(self, attr, set(items))
14499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
14599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
14699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_author(self, val):
14799c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self._set_string('author', val)
14899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
14999c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
15099c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_dependencies(self, val):
15199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self._set_set('dependencies', val)
15299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
15399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
15499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_doc(self, val):
15599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self._set_string('doc', val)
15699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
15799c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
15899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_name(self, val):
15999c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self._set_string('name', val)
16099c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
16199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
16299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_run_verify(self, val):
16399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self._set_bool('run_verify', val)
16499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
16599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
16699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_sync_count(self, val):
16799c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self._set_int('sync_count', val, min=1)
16899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
16999c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
1706fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone    def set_suite(self, val):
1716fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone        self._set_string('suite', val)
1726fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone
1736fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone
17499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_time(self, val):
175ef5b53f9c7fe279a7b89f9e9c731e7c1ea523d92Dan Shi        self._set_option('time', val, ControlData.TEST_TIME_LIST)
17699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
17799c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
17899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_test_class(self, val):
17999c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self._set_string('test_class', val.lower())
18099c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
18199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
18299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_test_category(self, val):
18399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh        self._set_string('test_category', val.lower())
18499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
18599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
18699c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    def set_test_type(self, val):
1873dd8beb386f7298ffe84d7410d00cce26973e170Aviv Keshet        self._set_option('test_type', val, list(CONTROL_TYPE.names))
18899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
189861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li
190d3e8a3bf27615ef88c80efdf7b3dcbf52c30f071Eric Li    def set_test_parameters(self, val):
191d3e8a3bf27615ef88c80efdf7b3dcbf52c30f071Eric Li        self._set_set('test_parameters', val)
192d3e8a3bf27615ef88c80efdf7b3dcbf52c30f071Eric Li
19399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
1946f455262ded933c1699fea410a9ddaf967df6330Aviv Keshet    def set_retries(self, val):
1956f455262ded933c1699fea410a9ddaf967df6330Aviv Keshet        self._set_int('retries', val)
1966f455262ded933c1699fea410a9ddaf967df6330Aviv Keshet
197ec1d47d85cc83f30631518d8fbb6406036a3ac39Dan Shi
198e3bc24b7b77480d4bb0b1562bb30ea79eff85626Fang Deng    def set_job_retries(self, val):
199e3bc24b7b77480d4bb0b1562bb30ea79eff85626Fang Deng        self._set_int('job_retries', val)
200e3bc24b7b77480d4bb0b1562bb30ea79eff85626Fang Deng
2016f455262ded933c1699fea410a9ddaf967df6330Aviv Keshet
202ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    def set_bug_template(self, val):
203ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        if type(val) == dict:
204ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B            setattr(self, 'bug_template', val)
20593f4209487841147d8fae40ce28beb310663b77ambligh
20693f4209487841147d8fae40ce28beb310663b77ambligh
207ec1d47d85cc83f30631518d8fbb6406036a3ac39Dan Shi    def set_require_ssp(self, val):
208ec1d47d85cc83f30631518d8fbb6406036a3ac39Dan Shi        self._set_bool('require_ssp', val)
209ec1d47d85cc83f30631518d8fbb6406036a3ac39Dan Shi
210ec1d47d85cc83f30631518d8fbb6406036a3ac39Dan Shi
21113248c5b1b6978647bc8ae040db6b221f488a7e0Shuqian Zhao    def set_attributes(self, val):
2129e6812115fcc52d762827002f525d0836b2c2003Shuqian Zhao        # Add subsystem:default if subsystem is not specified.
21313248c5b1b6978647bc8ae040db6b221f488a7e0Shuqian Zhao        self._set_set('attributes', val)
2149e6812115fcc52d762827002f525d0836b2c2003Shuqian Zhao        if not any(a.startswith('subsystem') for a in self.attributes):
2159e6812115fcc52d762827002f525d0836b2c2003Shuqian Zhao            self.attributes.add('subsystem:default')
21613248c5b1b6978647bc8ae040db6b221f488a7e0Shuqian Zhao
21713248c5b1b6978647bc8ae040db6b221f488a7e0Shuqian Zhao
218ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth Bdef _extract_const(expr):
219ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    assert(expr.__class__ == compiler.ast.Const)
220ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    assert(expr.value.__class__ in (str, int, float, unicode))
221ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    return str(expr.value).strip()
222ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B
223ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B
224ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth Bdef _extract_dict(expr):
225ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    assert(expr.__class__ == compiler.ast.Dict)
226ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    assert(expr.items.__class__ == list)
227ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    cf_dict = {}
228ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    for key, value in expr.items:
229ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        try:
230ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B            key = _extract_const(key)
231ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B            val = _extract_expression(value)
232ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        except (AssertionError, ValueError):
233ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B            pass
234ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        else:
235ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B            cf_dict[key] = val
236ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    return cf_dict
23793f4209487841147d8fae40ce28beb310663b77ambligh
23893f4209487841147d8fae40ce28beb310663b77ambligh
239ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth Bdef _extract_list(expr):
240ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    assert(expr.__class__ == compiler.ast.List)
241ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    list_values = []
242ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    for value in expr.nodes:
243ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        try:
244ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B            list_values.append(_extract_expression(value))
245ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        except (AssertionError, ValueError):
246ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B            pass
247ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    return list_values
248ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B
249ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B
250ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth Bdef _extract_name(expr):
251ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    assert(expr.__class__ == compiler.ast.Name)
252ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    assert(expr.name in ('False', 'True', 'None'))
253ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    return str(expr.name)
254ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B
255ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B
256ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth Bdef _extract_expression(expr):
257ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    if expr.__class__ == compiler.ast.Const:
258ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        return _extract_const(expr)
259ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    if expr.__class__ == compiler.ast.Name:
260ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        return _extract_name(expr)
261ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    if expr.__class__ == compiler.ast.Dict:
262ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        return _extract_dict(expr)
263ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    if expr.__class__ == compiler.ast.List:
264ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        return _extract_list(expr)
265ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    raise ValueError('Unknown rval %s' % expr)
266ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B
267ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B
268ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth Bdef _extract_assignment(n):
26993f4209487841147d8fae40ce28beb310663b77ambligh    assert(n.__class__ == compiler.ast.Assign)
27093f4209487841147d8fae40ce28beb310663b77ambligh    assert(n.nodes.__class__ == list)
27193f4209487841147d8fae40ce28beb310663b77ambligh    assert(len(n.nodes) == 1)
27293f4209487841147d8fae40ce28beb310663b77ambligh    assert(n.nodes[0].__class__ == compiler.ast.AssName)
27393f4209487841147d8fae40ce28beb310663b77ambligh    assert(n.nodes[0].flags.__class__ == str)
27493f4209487841147d8fae40ce28beb310663b77ambligh    assert(n.nodes[0].name.__class__ == str)
27593f4209487841147d8fae40ce28beb310663b77ambligh
276ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B    val = _extract_expression(n.expr)
27793f4209487841147d8fae40ce28beb310663b77ambligh    key = n.nodes[0].name.lower()
27893f4209487841147d8fae40ce28beb310663b77ambligh
27993f4209487841147d8fae40ce28beb310663b77ambligh    return (key, val)
28093f4209487841147d8fae40ce28beb310663b77ambligh
28193f4209487841147d8fae40ce28beb310663b77ambligh
2826fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masonedef parse_control_string(control, raise_warnings=False):
2836fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone    try:
2846fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone        mod = compiler.parse(control)
2856fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone    except SyntaxError, e:
2866fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone        raise ControlVariableException("Error parsing data because %s" % e)
2876fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone    return finish_parse(mod, '', raise_warnings)
2886fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone
2896fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone
29099c2c6f54e962fe4e7701cd9aaa645fdabacd203mblighdef parse_control(path, raise_warnings=False):
291d7cd983031fc77a247d022aef67b481892681ddcmbligh    try:
292d7cd983031fc77a247d022aef67b481892681ddcmbligh        mod = compiler.parseFile(path)
293d7cd983031fc77a247d022aef67b481892681ddcmbligh    except SyntaxError, e:
2944b5c31e1821307b880b57a41f6d8ea21948fc9e8mbligh        raise ControlVariableException("Error parsing %s because %s" %
2954b5c31e1821307b880b57a41f6d8ea21948fc9e8mbligh                                       (path, e))
2966fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone    return finish_parse(mod, path, raise_warnings)
2976fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone
29899c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
2996fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masonedef finish_parse(mod, path, raise_warnings):
30099c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    assert(mod.__class__ == compiler.ast.Module)
30199c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    assert(mod.node.__class__ == compiler.ast.Stmt)
30299c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    assert(mod.node.nodes.__class__ == list)
30399c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh
30499c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    vars = {}
30599c2c6f54e962fe4e7701cd9aaa645fdabacd203mbligh    for n in mod.node.nodes:
306ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        try:
307ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B            key, val = _extract_assignment(n)
308ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B            vars[key] = val
309ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B        except (AssertionError, ValueError):
310ee70731b31f66ecf8043b9fa6d1f86a52753a22fPrashanth B            pass
311d7cd983031fc77a247d022aef67b481892681ddcmbligh    return ControlData(vars, path, raise_warnings)
312