Example #1
0
class TestInfoFromReport(Resource):
    def __init__(self):
        self.report_service = ReportService()

    def get(self, platform, suite, test):
        result = []
        reports = list(
            self.report_service.find_all_reports({'platform': platform, 'suits.name': suite, 'suits.tests.name': test}))
        test_info = self.report_service.get_test_info(suite, test)
        for report in reports:
            target_suite = [test_suite for test_suite in report['suits'] if test_suite['name'] == suite][0]
            target_test = [selected_test for selected_test in target_suite['tests'] if selected_test['name'] == test][0]
            new_item = {
                'date': report['start_time'],
                'status': target_test['result'],
                'report_id': str(report['_id'])
            }
            if 'message' in target_test:
                new_item['message'] = target_test['message']
                new_item['stack_trace'] = target_test['stack_trace']
            result.append(new_item)

        result = sorted(result, reverse=True, key=itemgetter('date'))
        for item in result:
            item['date'] = item['date'].strftime("%Y-%m-%d %H:%M:%S").__str__()

        return result, 200
Example #2
0
class FailedTests(Resource):
    def __init__(self):
        self.report_service = ReportService()

    def get(self):
        data = self.report_service.get_failed_tests_comparison()
        return json.loads(json.dumps(data, default=json_util.default)), 200
class ReportMonthlyResource (Resource):

    report_service = ReportService()

    @swag_from('../../spec/reports/monthly.yml')
    def get(self):
        try:
            req_data = self.report_service.monthly(request.args)
            if (len(req_data)) != 0:
                res_data = [[i[0] for i in req_data[0].items()]] + [list(i) for i in req_data]
                sheet = p.Sheet(res_data)
                output = make_response(sheet.csv)
                output.headers["Content-Disposition"] = "attachment; filename=export.csv"
                output.headers["Content-type"] = "text/csv"
                return output
            else:
                res_json = {'status': 1, 'message': 'No Data found in the specified range'}
                return jsonify(res_json)

        except Exception as e:
            print(e)
            if e.args:
                res_data = e.args[0]
            else:
                res_data = e
            res_json = {'status': 0, 'error': res_data}
            return jsonify(res_json)
Example #4
0
    def run(self):

        if self.state == TaskStatus.OK:

            parser = configparser.ConfigParser()
            parser.read(self.config_file)
            self.swift_dir = parser['SYSTEM']['SWIFT_Directory']
            self.stma_software_dir = parser['SYSTEM']['STMA_Software_Directory']
            self.dynust_dir = parser['SYSTEM']['DynusT_Software_Directory']
            self.dynastudio_executable = parser['SYSTEM']['DynuStudio_Executable']
            self.dynust_executable_name = parser['SYSTEM']['DynusT_Executable_Name']
            self.common_dir = os.path.join(self.swift_dir, 'CommonData')
            self.threads = int(parser['SYSTEM']['Number_Threads'])

            self.scen_dir = os.path.join(self.swift_dir, 'Scenarios', self.scen)
            self.logger = ReportService(os.path.join(self.scen_dir, self.scen + '_STM_A.log')).get_logger()
            if not self.check_dir(self.scen_dir):
                self.logger.error('Scenario {:s} Not Found at'.format(self.scen_dir))
                self.state = State.ERROR
                return self.state

            self.base_dir = os.path.join(self.swift_dir, 'Scenarios', self.base)
            if not os.path.exists(self.base_dir):
                self.logger.error('Baseline {:s} Not Found at'.format(self.base_dir))
                self.state = State.ERROR
                return self.state

            if self.mode.upper() == 'FULL':
                self.mode = "FULL"
            else:
                self.mode = 'QUICK'

            self.logger.info('Scenario {:s} Execution Starts'.format(self.scen))

            self.logger.info('')
            self.logger.info('TASK {:s}_{:s}_{:s}: START'.format(self.family, self.step_id, self.__class__.__name__))
            self.logger.info('')

            self.logger.info('Scenario Name      = {:s}'.format(self.scen))
            self.logger.info('Baseline Name      = {:s}'.format(self.base))
            self.logger.info('Execution Mode     = {:s}'.format(self.mode))
            self.logger.info('Use Local Network  = {:}'.format(self.local_network))
            self.logger.info('Configuration File = {:s}'.format(self.config_file))
            self.logger.info('Number of Threads  = {:d}'.format(self.threads))
Example #5
0
class ReportForDate(Resource):
    def __init__(self):
        self.report_service = ReportService()

    def get(self, platform, date):
        result = self.report_service.get_report_for_date(platform, date)
        if len(result) > 0:
            return json.loads(json.dumps(result[0], default=json_util.default)), 200
        else:
            return {'message': 'Report was not found'}, 404
Example #6
0
class Report(Resource):
    def __init__(self):
        self.report_service = ReportService()

    @jwt_required
    def get(self, report_id: str):
        try:
            result = self.report_service.find_report({'_id': ObjectId(report_id)}, {'suits': 0})
        except InvalidId:
            return {'message': 'Invalid report id is provided.'}, 400
        if result:
            return json.loads(json.dumps(result, default=json_util.default)), 200
        return {'message': "Requested report was not found!"}, 404

    @jwt_required
    def delete(self, report_id):
        count = self.report_service.delete(report_id)
        if count == 0:
            return {'message': 'report was not deleted'}
        return {'message': 'report was deleted'}, 200
Example #7
0
class HistoricData(Resource):
    def __init__(self):
        self.report_service = ReportService()

    def get(self):
        try:
            result = self.report_service.get_historic_data()
        except InvalidId:
            return {'message': 'Invalid platform is provided.'}, 400
        if result:
            return json.loads(json.dumps(result, default=json_util.default)), 200
        return {'Message': "Requested platform was not found!"}, 404
Example #8
0
    def update_system_keys(self):
        """
        Update the system keys
        :return:
        """
        if self.state == State.ERROR:
            return self.state

        if 'TITLE' not in self.keys:
            self.keys['TITLE'] = Key('TITLE', input_value='')

        if self.keys['TITLE'].input_value:
            self.title = self.keys['TITLE'].input_value
        else:
            self.title = self.name
        self.keys['TITLE'].value = self.title

        if 'PROJECT_DIRECTORY' not in self.keys or self.keys[
                'PROJECT_DIRECTORY'].input_value is None:
            self.keys['PROJECT_DIRECTORY'] = Key('PROJECT_DIRECTORY')
        self.project_dir = self.keys['PROJECT_DIRECTORY'].value

        if 'REPORT_FILE' not in self.keys or not self.keys[
                'REPORT_FILE'].input_value:
            self.keys['REPORT_FILE'] = Key(
                'REPORT_FILE',
                input_value=os.path.basename(self.control_file)[:-4] + '.prn')
        else:
            if self.keys['REPORT_FILE'].input_value.find('.prn') < 0:
                self.keys['REPORT_FILE'].value = self.keys[
                    'REPORT_FILE'].input_value + ".prn"
        self.report_file = os.path.join(self.project_dir,
                                        self.keys['REPORT_FILE'].value)

        if 'RANDOM_SEED' not in self.keys or not self.keys[
                'RANDOM_SEED'].input_value:
            self.keys['RANDOM_SEED'] = Key('RANDOM_SEED')

        self.logger = ReportService(self.report_file).get_logger()
Example #9
0
class Reports(Resource):
    def __init__(self):
        self.report_service = ReportService()

    def get(self, target: str):
        try:
            result = list(
                self.report_service.find_all_reports({'target': target},
                                                     {'suits': 0}))
        except InvalidId:
            return {'message': 'Invalid report id is provided.'}, 400
        if result:
            return json.loads(json.dumps(result,
                                         default=json_util.default)), 200
        return {'Message': "Requested report was not found!"}, 404
class HistoricDataPerPlatform(Resource):
    def __init__(self):
        self.report_service = ReportService()

    def get(self, platform):
        try:
            parse = reqparse.RequestParser()
            parse.add_argument('period', type=int)

            args = parse.parse_args()

            result = self.report_service.get_historic_data(
                platform, args['period'])
        except InvalidId:
            return {'message': 'Invalid platform is provided.'}, 400
        if result:
            return json.loads(json.dumps(result,
                                         default=json_util.default)), 200
        return {'Message': 'Selected time rage does not contain any data'}, 404
Example #11
0
class ControlService(object):

    common_keys = ('TITLE', 'REPORT_FILE', 'PROJECT_DIRECTORY', 'RANDOM_SEED')

    required_keys = ()
    optional_keys = ()

    def __init__(self, name=None, input_control_file=None):
        self.name = name
        self.title = None
        self.exec_dir = os.getcwd()
        self.control_file = input_control_file
        self.control_files = []
        self.keys = {}
        self.tokens = {}
        self.unused_keys = []
        self.highest_group = 0
        self.state = State.OK
        self.project_dir = None
        self.report_file = None
        self.logger = None
        self.seed = 42

    @staticmethod
    def is_comment(line):
        return line.startswith("##") | line.startswith("//")

    @staticmethod
    def strip_comment(line):
        """
        strip the comment
        :param line: a string with comments at the end. Comments symbols not at the beginning
        :return:
        """
        loc_pound_sign = line.find("##")
        loc_slash_sign = line.find("//")

        if loc_pound_sign >= 0:
            return line[:loc_pound_sign]
        elif loc_slash_sign >= 0:
            return line[:loc_slash_sign]
        else:
            return line

    @staticmethod
    def split_key_value(line):
        """
        Replace all tabs with 4 spaces
        :param line:
        :return:
        """

        key_value_pair = re.split(r"[\s]{2,}", line.replace('\t', '    '))
        if len(key_value_pair) > 1:
            return key_value_pair[0], key_value_pair[1]
        else:
            return key_value_pair[0], None

    def replace_tokens(self, s, token='%'):
        s = s.strip()
        substrs = []
        token_count, prev = 0, 0
        for i, ch in enumerate(s):
            if ch == token:
                token_count += 1
                if token_count == 1:
                    if i > 0:
                        substrs.append(s[prev:i])
                        prev = i
                if token_count == 2:
                    substrs.append(s[prev:i + 1])
                    token_count = 0
                    prev = i + 1
            if i == len(s) - 1:
                substrs.append(s[prev:i + 1])

        output = [s for s in substrs if s]
        if token == '%':
            for i, substr in enumerate(substrs):
                if fnmatch(substr, '%*%'):
                    output[i] = os.environ.get(substr[1:-1], '').strip()
        if token == '@':
            for i, substr in enumerate(substrs):
                if fnmatch(substr, '@*@'):
                    output[i] = self.tokens.get(substr, '')
        return ''.join(output)

    def read_control(self, control_file):
        control_file = control_file.strip()
        if self.state == State.ERROR:
            return self.state
        elif not os.path.exists(control_file):
            self.state = State.ERROR
            sys.stderr.write("Control file %s is not found\n" % control_file)
            return self.state
        else:
            with open(control_file, mode='r') as control:
                for line in control:
                    line = line.strip()
                    if line and not self.is_comment(line):
                        key, value = self.split_key_value(
                            self.strip_comment(line))
                        root, _ = self.get_root_key(key)
                        if root not in KEYS_DATABASE:
                            self.unused_keys.append(key)
                        else:
                            if value:
                                key = key.upper()
                                if key.startswith('CONTROL_KEY_FILE'):

                                    # for case: CONTROL_KEY_FILE  @SOME_FILE_NAME@
                                    if fnmatch(value, "*@*@*"):
                                        value = self.replace_tokens(value,
                                                                    token='@')

                                    elif fnmatch(value, "*%*%*"):
                                        value = self.replace_tokens(value,
                                                                    token='%')
                                    value = os.path.join(
                                        self.exec_dir, value
                                    )  # CONTROL_KEY_FILE relative to exec_dir
                                    self.read_control(value)
                                elif fnmatch(key, "*@*@*"):
                                    self.tokens[
                                        key] = value  # Collect program tokens @*@
                                else:
                                    if fnmatch(value, "*%*%*"):
                                        value = self.replace_tokens(value,
                                                                    token='%')
                                    self.keys[key] = Key(key=key,
                                                         input_value=value)
                                    if self.keys[
                                            key].group > self.highest_group:
                                        self.highest_group = self.keys[
                                            key].group
                            else:
                                self.keys[key] = Key(key=key)

    def update_system_keys(self):
        """
        Update the system keys
        :return:
        """
        if self.state == State.ERROR:
            return self.state

        if 'TITLE' not in self.keys:
            self.keys['TITLE'] = Key('TITLE', input_value='')

        if self.keys['TITLE'].input_value:
            self.title = self.keys['TITLE'].input_value
        else:
            self.title = self.name
        self.keys['TITLE'].value = self.title

        if 'PROJECT_DIRECTORY' not in self.keys or self.keys[
                'PROJECT_DIRECTORY'].input_value is None:
            self.keys['PROJECT_DIRECTORY'] = Key('PROJECT_DIRECTORY')
        self.project_dir = self.keys['PROJECT_DIRECTORY'].value

        if 'REPORT_FILE' not in self.keys or not self.keys[
                'REPORT_FILE'].input_value:
            self.keys['REPORT_FILE'] = Key(
                'REPORT_FILE',
                input_value=os.path.basename(self.control_file)[:-4] + '.prn')
        else:
            if self.keys['REPORT_FILE'].input_value.find('.prn') < 0:
                self.keys['REPORT_FILE'].value = self.keys[
                    'REPORT_FILE'].input_value + ".prn"
        self.report_file = os.path.join(self.project_dir,
                                        self.keys['REPORT_FILE'].value)

        if 'RANDOM_SEED' not in self.keys or not self.keys[
                'RANDOM_SEED'].input_value:
            self.keys['RANDOM_SEED'] = Key('RANDOM_SEED')

        self.logger = ReportService(self.report_file).get_logger()

    @staticmethod
    def parse_integer_list_key(value):
        """
        Parse a range key
        :param value: a string like 1,2,4..5
        :return: a list with all individual values
        """

        res = []
        if ',' in value:
            value_split = value.strip().split(',')
            for v in value_split:
                v_split = v.split('..')
                if len(v_split) == 1:
                    res.append(int(v_split[0]))
                else:
                    lb, hb = int(v_split[0]), int(v_split[1])
                    for k in range(lb, hb + 1):
                        res.append(k)
        else:
            v_split = value.split('..')
            lb, hb = int(v_split[0]), int(v_split[1])
            for k in range(lb, hb + 1):
                res.append(k)
        return res

    @staticmethod
    def parse_float_list_key(value):
        """

        :param value:
        :return:
        """

        res = []
        if ',' in value:
            value_split = value.strip().split(',')
            res = [float(v) for v in value_split]
        else:
            res.append(float(value))
        return res

    @staticmethod
    def parse_boolean_key(value):
        if str(value).upper().find('FALSE') >= 0 or str(value).upper() == '0':
            return False
        return True

    def parse_time_range(self, time_range):
        """
        parse the time range
        :param time_range: parse comma-separated ranges like "0..6, 15..19"
        :type  time_range: str
        :return: "0..6, 15..19" is parsed into [(0, 6), (15, 19)]
        """

        if not isinstance(time_range, str):
            self.logger.error("Time range must be a string")
            return [(-1, -1)]

        parts = time_range.split(",")
        ranges = []

        for part in parts:
            if part.find("..") < 0:
                self.logger.error(
                    "Time range must have both start and end times. Input is %s"
                    % part)
                return [(-1, -1)]
            else:
                start_time, end_time = part.split("..")
                ranges.append((float(start_time), float(end_time)))
        return ranges

    @staticmethod
    def get_root_key(key_name):
        """
        get the root key name
        :param key_name:
        :type  key_name: str
        :return:
        """

        parts = key_name.split("_")
        if parts[-1].isdigit():
            return key_name[:len(key_name) - len(parts[-1]) - 1], int(
                parts[-1])
        else:
            return key_name, 0

    @staticmethod
    def is_output_file(key_name):
        if key_name.find('NEW') >= 0 and key_name.find('_FILE') >= 0:
            return True
        return False

    def update_key_value(self, key):
        if self.state == State.ERROR:
            return self.state

        if key.input_value is not None:
            while key.input_value is not None and fnmatch(
                    key.input_value, "@*@"):
                key.input_value = self.tokens.get(key.input_value)
            while key.input_value is not None and fnmatch(
                    key.input_value, "%*%"):
                key.input_value = self.tokens.get(key.input_value[1:-1])
            if key.value_type == KeyValueTypes.TIME_RANGE:
                val = self.parse_time_range(key.input_value)
                if val[0][0] >= 0:
                    key.value = val
                else:
                    self.state = State.ERROR
            elif key.value_type == KeyValueTypes.STRING:
                converter = str
                key.value = converter(key.input_value)
            elif key.value_type == KeyValueTypes.FLOAT:
                converter = float
                key.value = converter(key.input_value)
            elif key.value_type == KeyValueTypes.INTEGER:
                converter = int
                key.value = converter(key.input_value)
            elif key.value_type == KeyValueTypes.FILE:
                if key.order > Offset.NETWORK_KEYS_OFFSET and self.project_dir and key.input_value:
                    key.value = os.path.join(self.project_dir, key.input_value)
            elif key.value_type == KeyValueTypes.INTEGER_LIST:
                key.value = self.parse_integer_list_key(key.input_value)
            elif key.value_type == KeyValueTypes.FLOAT_LIST:
                key.value = self.parse_float_list_key(key.input_value)
            elif key.value_type == KeyValueTypes.BOOLEAN:
                key.value = self.parse_boolean_key(key.input_value)

    def check_keys(self):
        """
        Populate all keys and check required key;
        :return:

        The key dictionary has all the acceptable keys in fully suffixed notation; If the value is None, the key
        is not set by the user

        """

        if self.state == State.ERROR:
            return self.state

        acceptable_keys = self.common_keys + self.required_keys + self.optional_keys
        single_keys = [
            k for k in acceptable_keys
            if KEYS_DATABASE[k].group == KeyGroupTypes.SINGLE
        ]
        group_suffixes = [
            "_" + str(g) for g in range(1, self.highest_group + 1)
        ]
        group_keys = [
            k for k in acceptable_keys
            if KEYS_DATABASE[k].group == KeyGroupTypes.GROUP
        ]
        full_key_list = single_keys + [
            k + s for k, s in itertools.product(group_keys, group_suffixes)
        ]

        for k in full_key_list:
            if k not in self.keys:
                root_key_name, key_group = self.get_root_key(k)

                key_value = KEYS_DATABASE[root_key_name].default
                if key_group > 1:
                    # take the value of the first defined group if not specified; otherwise default value
                    prev_group = key_group - 1
                    while root_key_name + "_" + str(
                            prev_group) not in self.keys:
                        prev_group -= 1
                    key_value = self.keys[root_key_name + "_" +
                                          str(prev_group)].input_value
                new_key = Key(key=k, input_value=key_value)
                self.keys.update({k: new_key})

        # Update the key value to internal data structures
        for k in self.keys.values():
            self.update_key_value(k)

        # Check required keys for each group. if a value is None, raise an error
        check_key = None
        # found = False
        for req_k in self.required_keys:
            found = False
            is_group_key = KEYS_DATABASE[req_k].group == KeyGroupTypes.GROUP
            if is_group_key:
                for g in group_suffixes:
                    check_key = req_k + g
                    for name, k in self.keys.items():
                        if check_key == name and k.input_value is not None and len(
                                k.input_value) > 0:
                            found = True
                            break
            else:
                check_key = req_k
                for name, k in self.keys.items():
                    if check_key == name and k.value is not None:
                        found = True
                        break
            if not found:
                self.logger.error("Required key %s not found" % check_key)
                self.state = State.ERROR

    def check_files(self):
        if self.state == State.ERROR:
            return self.state

        for k in self.keys.values():
            if k.key == 'PROJECT_DIRECTORY':
                if not os.path.exists(k.value):
                    self.state = State.ERROR
                    self.logger.error("Project Directory %s does not exist" %
                                      k.value)

            if k.value_type == KeyValueTypes.FILE:
                if self.is_output_file(k.key):
                    if k.value and not os.path.exists(os.path.dirname(
                            k.value)):
                        self.state = State.ERROR
                        self.logger.error("Path %s for %s does not exist" %
                                          (os.path.dirname(k.value), k.key))
                elif k.key != 'REPORT_FILE':
                    if k.value and not os.path.exists(k.value):
                        self.state = State.ERROR
                        self.logger.error("File %s for %s does not exist" %
                                          (k.value, k.key))

    def print_keys(self):
        if self.state == State.ERROR:
            return self.state

        keys = [(k, v.value, v.order) for k, v in self.keys.items()]
        keys = sorted(keys, key=lambda k: k[2])
        for k, v, _ in keys:
            self.logger.info("%s = %s" % (k, v))
        for key in self.unused_keys:
            self.logger.warning("Unused key {:s}".format(key))
        self.logger.info("")
        self.logger.info("")

    def execute(self):
        self.read_control(self.control_file)
        self.update_system_keys()
        self.check_keys()
        self.print_keys()
        self.check_files()

        return self.state
Example #12
0
 def __init__(self):
     self.report_service = ReportService()
Example #13
0
class ReportUploader(Resource):
    def __init__(self):
        self.report_service = ReportService()

    def post(self):
        parse = reqparse.RequestParser()
        parse.add_argument('file',
                           type=werkzeug.datastructures.FileStorage,
                           location='files',
                           required=True,
                           help='Parameter file is required.')
        args = parse.parse_args()

        try:
            file_content = args['file'].stream.read().decode('utf-8')
            report_hash = hashlib.md5(file_content.encode('utf-8')).hexdigest()
            existing_report = self.report_service.find_report_by_hash(
                report_hash)
            if existing_report:
                return {
                    "message":
                    'This report was already submitted on {0}'.format(
                        existing_report['added_on'])
                }, 400
            json_report = json.loads(file_content)
            platform = json_report['meta']['platform']
            if platform == 'win' and ('win7' in json_report['meta']['config']):
                platform = 'win7'

            new_report = {
                'hash':
                report_hash,
                'client_ip':
                request.remote_addr,
                'added_on':
                datetime.datetime.now(),
                'start_time':
                datetime.datetime.utcfromtimestamp(
                    json_report['meta']['start_time']),
                'end_time':
                datetime.datetime.utcfromtimestamp(
                    json_report['meta']['end_time']),
                'platform':
                platform,
                'target':
                json_report['meta']['params']['target'],
                'errors':
                json_report['meta']['errors'],
                'failed':
                json_report['meta']['failed'],
                'passed':
                json_report['meta']['passed'],
                'skipped':
                json_report['meta']['skipped'],
                'total':
                json_report['meta']['total'],
                'branch':
                json_report['meta']['iris_branch'],
                'suits': []
            }
            for suite in json_report['tests']['all_tests']:
                new_suite = {'name': suite['name'], 'tests': []}
                for test in suite['children']:
                    new_test = {
                        'name': test['name'],
                        'description': test['description'],
                        'result': test['result'],
                        'time': test['time']
                    }
                    if 'assert' in test:
                        if 'message' in test['assert']:
                            new_test['message'] = test['assert']['message']
                        if 'call_stack' in test['assert']:
                            new_test['stack_trace'] = test['assert'][
                                'call_stack']
                    new_suite['tests'].append(new_test)

                new_report['suits'].append(new_suite)

            report_id = self.report_service.create_report(new_report)
            return {
                'message': 'The report is delivered.',
                'report_id': report_id
            }, 201

        except UnicodeDecodeError:
            return {'message': 'Unsupported report format detected.'}, 400
        except JSONDecodeError:
            return {'message': 'Invalid JSON report format detected.'}, 400
        except KeyError:
            return {'message': 'Invalid Iris report format detected.'}, 400
Example #14
0
File: stma.py Project: xys234/Work
def main(base, scen, mode, local, config_file):
    logger = ReportService('default_log')

    start_time = time.time()
    wf = workflow(base, scen, mode, local, config_file)
    steps = list(wf.keys())

    for name, step in wf.items():
        step.execute()
        if name == 'ConfigureExecution':
            logger = step.logger
            logger.info('----------------STMA WorkFlow------------------')
            for i, s in enumerate(steps):
                logger.info("Step {:d} - {:30s}".format(i + 1, s))

    end_time = time.time()
    execution_time = max((end_time - start_time) / 60.0, 0.0)

    model_status = [s.state for s in wf.values()]
    model_status = {s: st for s, st in zip(steps, model_status)}

    logger.info('----------------STMA Execution Summary------------------')
    stma_status = TaskStatus.OK
    stepid = 0
    for step, status in model_status.items():
        stepid += 1
        logger.info('Step {:d} {:50s} Status = {:10s}'.format(
            stepid, step, str(status)))
        if status != TaskStatus.OK:
            stma_status = TaskStatus.FAIL

    if stma_status == TaskStatus.OK:
        logger.info('STMA Completed in {:.0f} minutes'.format(execution_time))
    else:
        logger.error('STMA Failed in {:.0f} minutes'.format(execution_time))
    return stma_status
Example #15
0
class ConfigureExecution(Task):

    family = 'Setup'

    def __init__(self, base, scen, mode, config_file, local_network='FALSE', step_id='00'):
        super().__init__(step_id=step_id)
        self.base = base
        self.scen = scen
        self.mode = mode.upper()
        self.local_network = local_network

        if local_network.upper() == 'TRUE':
            self.local_network = True
        else:
            self.local_network = False

        self.config_file = config_file

        self.swift_dir = None
        self.stma_software_dir = None
        self.dynust_dir = None
        self.dynastudio_executable = None
        self.dynust_executable_name = None
        self.common_dir = None

        self.base_dir = None
        self.scen_dir = None

        self.config = None
        self.threads = 1
        self.logger = None

    def check_dir(self, d, root_dir=None):
        if not os.path.exists(d):
            os.mkdir(d)
            if not os.path.exists(d):
                if root_dir is not None:
                    self.logger.error('{:60s} Failed to Create'.format(os.path.relpath(d, root_dir)))
                else:
                    self.logger.error('{:60s} Failed to Create'.format(d))
                return False
            else:
                if root_dir is not None:
                    self.logger.info('{:60s} Created'.format(os.path.relpath(d, root_dir)))
                else:
                    self.logger.info('{:60s} Created'.format(d))
                return True
        else:
            if root_dir is not None:
                self.logger.info('{:60s} Checked'.format(os.path.relpath(d, root_dir)))
            else:
                self.logger.info('{:60s} Checked'.format(d))
            return True

    def require(self):

        current_dir = os.getcwd()
        if self.config_file.startswith('.'):
            self.config_file = os.path.join(current_dir, self.config_file)
        if not os.path.exists(self.config_file):
            self.state = State.ERROR
            sys.stderr('STM-A Configuration File {:s} Not Found - STM-A Failed'.format(self.config_file))
            return self.state

    def run(self):

        if self.state == TaskStatus.OK:

            parser = configparser.ConfigParser()
            parser.read(self.config_file)
            self.swift_dir = parser['SYSTEM']['SWIFT_Directory']
            self.stma_software_dir = parser['SYSTEM']['STMA_Software_Directory']
            self.dynust_dir = parser['SYSTEM']['DynusT_Software_Directory']
            self.dynastudio_executable = parser['SYSTEM']['DynuStudio_Executable']
            self.dynust_executable_name = parser['SYSTEM']['DynusT_Executable_Name']
            self.common_dir = os.path.join(self.swift_dir, 'CommonData')
            self.threads = int(parser['SYSTEM']['Number_Threads'])

            self.scen_dir = os.path.join(self.swift_dir, 'Scenarios', self.scen)
            self.logger = ReportService(os.path.join(self.scen_dir, self.scen + '_STM_A.log')).get_logger()
            if not self.check_dir(self.scen_dir):
                self.logger.error('Scenario {:s} Not Found at'.format(self.scen_dir))
                self.state = State.ERROR
                return self.state

            self.base_dir = os.path.join(self.swift_dir, 'Scenarios', self.base)
            if not os.path.exists(self.base_dir):
                self.logger.error('Baseline {:s} Not Found at'.format(self.base_dir))
                self.state = State.ERROR
                return self.state

            if self.mode.upper() == 'FULL':
                self.mode = "FULL"
            else:
                self.mode = 'QUICK'

            self.logger.info('Scenario {:s} Execution Starts'.format(self.scen))

            self.logger.info('')
            self.logger.info('TASK {:s}_{:s}_{:s}: START'.format(self.family, self.step_id, self.__class__.__name__))
            self.logger.info('')

            self.logger.info('Scenario Name      = {:s}'.format(self.scen))
            self.logger.info('Baseline Name      = {:s}'.format(self.base))
            self.logger.info('Execution Mode     = {:s}'.format(self.mode))
            self.logger.info('Use Local Network  = {:}'.format(self.local_network))
            self.logger.info('Configuration File = {:s}'.format(self.config_file))
            self.logger.info('Number of Threads  = {:d}'.format(self.threads))

    def complete(self):
        message = 'TASK {:s}_{:s}_{:s}: STATUS = {:15s}'.format(
            self.family, self.step_id, self.__class__.__name__, str(self.state))
        self.logger.info('')
        self.logger.info('')
        self.logger.info(message)
        self.logger.info('')
        self.logger.info('')

    def execute(self):
        self.require()
        self.run()
        self.complete()
        return self.state