Skip to content

再帰関数1#

参考#

sample.py
import json
import os,re,yaml
from pprint import pprint


# 対象ファイルを検索する関数
def search_file(ptrn, target_dir):
    path_list = [
    os.path.join(dirPath + os.sep + file)
    for dirPath, dirs, files in os.walk(target_dir)
    for file in files
    # パターンにマッチしたファイルのみ抽出
    if ptrn.search(file)
    ]
    return path_list


# yaml ファイルを読み込み、辞書を返す関数
def read_datafile(yaml_file):
    with open(yaml_file, 'r',encoding="utf-8") as f:
        datafile = yaml.safe_load(f)
    return datafile


# 解析結果をファイルに書き込む関数
def write_file(filename, parse_result):
    with open(filename, "w", encoding='utf-8') as f:
        for i in parse_result:
            f.write(i)
            f.write("\n")

# yaml ファイル内のアイテムを選別する関数
def select_item(arg):
    if arg == 'failed':
        return None
    elif arg == 'device':
        return None
    elif arg == '%VARIABLES{device}':
        return None
    elif re.search(r'\!= passed',arg):
        return None
    else:
        return arg

# 再帰的にyaml ファイルを解析する関数
def get_procedure(datafile):
    result =[]
    if isinstance(datafile, str):
        datafile = select_item(datafile)
        if datafile != None:
            result.append(datafile)
    elif isinstance(datafile, int):
        result.append(f"sleep time : {datafile}")
    elif isinstance(datafile, list):
        for item in datafile:
            result += get_procedure(item)
    elif isinstance(datafile, dict):
        for value in datafile.values():
            result += get_procedure(value)
    return result

# yaml ファイル解析後のリストから不要な文字列を削除する関数
def remove_strings(procedure):
    # 試験項番(!!! )を '%VARIABLES{device_list}'に打つ、といった不要な手順は削除
    arranged_list = []
    for index,content in enumerate(procedure):
        if content == '%VARIABLES{device_list}':
            if '!!!' in procedure[(index+1)]:
                continue
            else:
                arranged_list.append(content)
        else:
            arranged_list.append(content)
    return arranged_list


# !!! ごとに2次元配列に変換する関数
def arranged_list(procedure):
    procedure_number = re.compile(r'!!! \d+ at \d+-\d+-\d+|!!! \d+ at \d+-\d+-\d+_\S+')
    arranged_list = []

    for content in procedure:
        if procedure_number.search(content):
            testcase_number = procedure_number.search(content).group()
            arranged_list.append([testcase_number])
            continue
        else:
            arranged_list[(len(arranged_list)-1)].append(content)

    return arranged_list


# topology 情報の解析関数
def read_topology(topology_file):
    topology = read_datafile(topology_file)
    devices = {}
    links = {}

    for device in topology['devices']:
        alias = topology['devices'][device]['alias']
        devices[alias] = device
        if 'IXIA' in device:
            ixia_port_list = topology['devices'][device]['connections']['tgn']['ixia_port_list']

    for alias in topology['topology']:
        links[alias] = {}
        port_info = topology['topology'][alias]['interfaces']
        for key,value in port_info.items():
            links[alias].update({value['link'] :key})

    return [devices,links,ixia_port_list]


# 手順書内変数を取り出し関数
def takeout_vars(vars_list):
    ptrn1 = re.compile(r'{vars_\d+_\d+_(\d+|\d+_\w+)\.nodes\.|}\||}')
    ptrn2 = re.compile(r'%{vars_\d+_\d+_(\d+|\d+_\w+)\.(nodes|links)\.|}\||}')
    ptrn3 = re.compile(
        r'%VARIABLES{\w+\.\w+\.\w+\[%{vars_\d+_\d+_\d+.nodes\.|}\].name}|'
        r'(%VARIABLES{|})|'
        r'(%{vars_\d+_\d+_\d+.nodes\.|})'
        ) 
    port_var_dict = {}
    template_vars_dict = {}

    for vars_dict in vars_list:
        if vars_dict['function'] == 'get_devices':
            device_list = vars_dict['arguments']['regex'].split('%')
            device_list = [device for device in device_list if device != ''] 
            device_list = [ptrn1.sub('',device) for device in device_list]
        elif vars_dict['function'] == 'get_single_interface':
            port_var = vars_dict['save'][0]['variable_name']
            arguments = vars_dict['arguments']
            arguments['device'] = ptrn2.sub('',arguments['device'])
            arguments['link_name'] = ptrn2.sub('',arguments['link_name'])
            port_var_dict[port_var] = arguments
        elif vars_dict['function'] == 'configure_by_jinja2':
            template_vars = vars_dict['arguments']
            del template_vars['templates_dir']
            for k,v in template_vars.items():
                template_vars[k] = ptrn3.sub('',v)
            template_vars_dict[template_vars['device']] = template_vars

    return [device_list, port_var_dict, template_vars_dict]


def translate_vars():
    pass


if __name__ == '__main__':
    file_ptrn = re.compile(r"yaml")
    sep_str = os.sep
    target_dir = f'.{sep_str}testcases{sep_str}'
    path_list = search_file(file_ptrn, target_dir)

    topology = read_topology('testbed_topology.yaml')
    # topology内変数
    devices = topology[0]
    links = topology[1]
    ixia_port_list = topology[2]

    for i in path_list:
        testnumber = i.split(sep_str)[3]
        testnumber_underbar = re.sub(r"-", r"_",testnumber)
        yaml_file = read_datafile(i)
        test_sections = yaml_file[f'TriggerBlitz_tc{testnumber}']['test_sections']
        procedure_vars = yaml_file[f'vars_{testnumber_underbar}']
        # 変数定義部分解析
        def_secition = test_sections.pop(0)['tc3_init_configuration'] # 変数定義セクションを取り出す
        vars_list = [(i['api']) for i in def_secition if 'api' in i]
        # 手順書内変数
        vars_list = takeout_vars(vars_list)
        device_list = vars_list[0]
        port_vars = vars_list[1]
        template_vars = vars_list[2]

        # TODO: link 変数の変換方法を検討
        """_summary_
        # topology 内変数
        devices: 
        links: 
        ixia_port_list: 

        # 手順書内変数
        vars_list: 
        device_list: 
        port_vars: 
        template_vars: 
        """





        # TODO: (1) procedure_vars を vars_list と紐付け
        # TODO: (1) での紐付け後に topology 情報補と紐付けた辞書の作成


        # 手順部分解析
        # TODO: 手順書内変数変換
        procedure = get_procedure(test_sections)
        procedure = remove_strings(procedure)
        procedure = arranged_list(procedure)