import os from pytest import fixture # , raises from pathlib import Path from rougail import Rougail ######################### from rougail.user_data_commandline import RougailUserDataCommandline as RougailUserData from json import load, dump, loads, dumps ######################### from rougail_tests.utils import get_structures_list, get_rougail_config, get_values_for_config, config_to_dict EXT = "cmdline_opts" excludes = [ '60_5family_dynamic_unknown_suffix', # needs to load all option before load data ] test_ok = get_structures_list(excludes) # test_ok = [Path('../rougail-tests/structures/60_5family_dynamic_unknown_suffix')] def idfn(fixture_value): return fixture_value.name @fixture(scope="module", params=test_ok, ids=idfn) def test_dir(request): return request.param def _test_structural_files(test_dir, namespace, ext, *, level, need_exclude=False): rougailconfig = get_rougail_config(test_dir, namespace) if not rougailconfig: return # rougailconfig['tiramisu_cache'] = "cache.py" ################################## rougailconfig['step.user_data'] = ['commandline'] ################################## dir_name = 'test' if namespace: dir_name += '_namespace' elif (test_dir / 'force_namespace').is_file(): return rougail = Rougail(rougailconfig) config = rougail.run() ################################## root_path = Path('tests') / 'results' / dir_name / test_dir.name makedict = root_path / 'makedict' / f'{level}.json' filename = root_path / 'file' if need_exclude: filename = filename / f'{level}_exclude.{EXT}' else: filename = filename / f'{level}.{EXT}' try: populate(filename, makedict, rougailconfig, level, need_exclude, namespace) except SubMulti: return with filename.open() as file_content: arguments = load(file_content) print('arguments', arguments, type(arguments)) ################################## # loads variables in the tiramisu config generated_user_data = RougailUserData(config, rougailconfig=rougailconfig, arguments=arguments, prog="test_load").run() print(generated_user_data) errors = rougail.user_datas(generated_user_data) #expected output expected_filename = Path('tests') / 'results' / dir_name / test_dir.name / 'makedict' / f'{level}.json' with expected_filename.open() as json_file: expected = load(json_file) # here is the effective test errors_file = Path('tests') / 'results' / dir_name / test_dir.name / 'errors' / f'{level}.json' if need_exclude: errors = loads(dumps(errors).replace('all_exclude.yml', 'all.yml')) if not errors_file.is_file(): errors_file.parent.mkdir(parents=True, exist_ok=True) with open(errors_file, 'a') as json_file: dump(errors, json_file, indent=4) with open(errors_file) as json_file: expected_errors = load(json_file) # expected_errors = { # 'errors': [], # 'warnings': [], # } assert expected_errors == errors, errors_file # config.property.read_only() config_dict = dict(config_to_dict(config.value.get())) assert expected == config_dict, expected_filename def populate(filename, makedict_file, rougailconfig, level, need_exclude, namespace): if filename.is_file() and makedict_file.is_file(): return config = Rougail(rougailconfig).run() values = get_values_for_config(config, not need_exclude, level, follower_with_index=True) print(filename) if not filename.is_file(): filename.parent.mkdir(parents=True, exist_ok=True) ############################################## v = values_to_commandline(values) print('========================') print('========================') print('========================') print(v) print('========================') ############################################## with filename.open('w') as fh: ############################################## dump(v, fh, indent=4) ############################################## if not makedict_file.is_file(): makedict_file.parent.mkdir(parents=True, exist_ok=True) config.property.read_only() config_dict = dict(config_to_dict(config.value.get())) with makedict_file.open('w') as fh: dump(config_dict, fh, indent=4) fh.write('\n') class SubMulti(Exception): pass ############################################## def values_to_commandline(values): print(values) def parse(root_path, values_, level=-1): level += 1 for key, value in values_.items(): if level == 0: sub_root_path = key else: sub_root_path = root_path + '.' + key if isinstance(value, dict): yield from parse(sub_root_path, value, level) elif isinstance(value, list): print("+++++++++++++++++++++", sub_root_path, value) if value and isinstance(value[0], dict): keys = [] for ls in value: for k in ls: if k not in keys: keys.append(k) for k in keys: leader_values = [] for val in value: sub_val = val.get(k, "") if not isinstance(sub_val, tuple): # it's a leader leader_values.append(sub_val) if isinstance(sub_val, list) or (isinstance(sub_val, tuple) and isinstance(sub_val[1], list)): raise SubMulti("submulti is not allowed for environment user_datas") if leader_values: yield "--" + (sub_root_path + '.' + k) for val in value: yield convert_str(val.get(k, "")) for idx, val in enumerate(value): val = val.get(k, "") if isinstance(val, tuple): # it's a follower yield "--" + (sub_root_path + '.' + k) yield str(val[0]) yield convert_str(val[1]) else: yield "--" + sub_root_path for val in value: yield convert_str(val) elif value is None or value == 'None': yield "--" + sub_root_path # yield "" elif isinstance(value, bool): if value: yield "--" + sub_root_path else: yield "--" + sub_root_path.rsplit(".", 1)[0] + '.no-' + sub_root_path.rsplit(".", 1)[-1] else: yield "--" + sub_root_path yield convert_str(value) return list(parse(None, values)) def convert_str(val): if isinstance(val, bool): return {True: 'true', False: 'false'}.get(val) if val is None: return "" return str(val) ############################################## def test_structural_files_all(test_dir): "tests the output" _test_structural_files(test_dir, True, EXT, level='all') # # #def test_structural_files_all_exclude(test_dir): # "tests the output" # _test_structural_files(test_dir, True, EXT, level='all', need_exclude=True) def test_structural_files_mandatories(test_dir): "tests the output" _test_structural_files(test_dir, True, EXT, level='mandatories')