-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcfg_parser.py
More file actions
78 lines (70 loc) · 2.26 KB
/
Copy pathcfg_parser.py
File metadata and controls
78 lines (70 loc) · 2.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import os
import json
import yaml
import itertools
from typing import Union
# Recursively makes a list of experiments from a dictionary of config settings.
# If it finds a list somewhere in the dictionary it expands it:
# For example:
# {'a': [1,2], 'b': 3}
# Results in:
# [
# {'a': 1, 'b': 3},
# {'a': 2, 'b': 3}
# ]
#
# And:
# {'a': [1,2], 'b': [3,4]}
# Results in:
# [
# {'a': 1, 'b': 3},
# {'a': 1, 'b': 4},
# {'a': 2, 'b': 3},
# {'a': 2, 'b': 4}
# ]
# If lists are needed inside the config, but no expansion, use tuples instead
def is_float(a_string):
try:
float(a_string)
return True
except ValueError:
return False
def dict_parser(x):
if type(x) is dict:
children = [dict_parser(val) for val in x.values()]
return [dict(zip(x.keys(), tup)) for tup in itertools.product(*children)]
elif type(x) is list:
return list(itertools.chain(*map(dict_parser, x)))
else:
return [x]
def dict_access_multi(dic, keys):
if len(keys) == 0:
return dic
return dict_access_multi(dic[keys[0]], keys[1:])
def read_file(fpath):
with open(fpath) as f:
extension = os.path.splitext(fpath)[1].strip(".")
if extension == 'json':
orig = json.loads(f.read())
elif extension in ['yaml', 'yml']:
orig = yaml.load(f, Loader = yaml.FullLoader)
else:
raise ValueError(f"Config extension unrecognized: '.{extension}'. Must be '.yaml' or '.json'!")
return orig
def parse(config_data:Union[list,dict]=None, fpath: str=None):
if fpath is not None:
orig = read_file(fpath)
elif config_data is not None:
orig = config_data
else:
raise ValueError("Config must be given either as a file or as a dictionary!")
serialized=dict_parser(orig)
for cfg in serialized:
if "experiment_name" in cfg:
cfg["experiment_name"]+=cfg["experiment_name_base"]
for ext in cfg["experiment_name_extension"]:
val=str(dict_access_multi(cfg, ext.split("/")))
if not is_float(val):
val=val.split("/")[-1].split(".")[0]
cfg["experiment_name"]+=f'_{ext.split("/")[-1]}-{val}'
return serialized