-
Notifications
You must be signed in to change notification settings - Fork 0
/
make-json.py
executable file
·124 lines (105 loc) · 4.66 KB
/
make-json.py
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python3
import os
import json
import subprocess
with open("./public/lmod-paths.json", "r", encoding="utf8") as f:
lmod_paths = json.load(f)
LMOD_SPIDER = lmod_paths["spider"]
with open("./public/arch2modulepath.json", "r", encoding="utf8") as f:
ARCH2MODULEPATH = json.load(f)
# when a hidden module adds a new branch to the hierarchy,
# Lmod spider does not give the hidden property to the modules in that new branch
HIDDEN_PARENT_DIRS = ["/modules/uri_modulefiles/all", "/modules/uri_modulefiles"]
VERSION_BLACKLIST = []
# spack generated modules add new directories to MODULEPATH using their absolute paths
# put the symlink into those absolute paths by finding/replacing
#PATH_REPLACEMENTS = {readlink_recursive("/modules/spack_modulefiles"): "/modules/spack_modulefiles"}
PATH_REPLACEMENTS = {}
def do_path_replacements(x):
x = os.path.realpath(x)
for find_this, replace_with_this in PATH_REPLACEMENTS.items():
if x.startswith(find_this):
# strip off leading characters, then prepend replacement
x = replace_with_this + x[len(find_this) :]
return x
def nested_dict_append(_dict, key1, key2, value):
if key1 not in _dict.keys():
_dict[key1] = {}
if key2 not in _dict[key1].keys():
_dict[key1][key2] = []
_dict[key1][key2].append(value)
# build the dicts
modules = {}
hidden_modules = {}
directory_prereqs = {}
for arch, modulepath in ARCH2MODULEPATH.items():
cmd = [LMOD_SPIDER, "-o", "spider-json", modulepath]
print(cmd)
json_str = subprocess.check_output(cmd)
module_name2modulefile = json.loads(json_str)
if module_name2modulefile == []: # no modules
continue
for module_name, modulefile2module_info in module_name2modulefile.items():
for modulefile, modulefile_info in modulefile2module_info.items():
parent_dir = do_path_replacements(modulefile_info["mpath"])
if "parentAA" in modulefile_info:
# this is always a nested list but I don't know why
(prereqs,) = modulefile_info["parentAA"]
assert len(prereqs) > 0
if parent_dir in directory_prereqs:
assert (
directory_prereqs[parent_dir] == prereqs
), "no directory should have 2 different definitions for prerequisite modules!"
directory_prereqs[parent_dir] = prereqs
if "/" in modulefile_info["fullName"]:
[name, version] = modulefile_info["fullName"].rsplit("/", 1)
else:
name = modulefile_info["fullName"]
version = "0.0"
if version in VERSION_BLACKLIST:
continue
name_version = f"{name}/{version}"
if modulefile_info["hidden"]:
nested_dict_append(hidden_modules, arch, parent_dir, name_version)
else:
nested_dict_append(modules, arch, parent_dir, name_version)
# hide the hidden directories
for _dir in HIDDEN_PARENT_DIRS:
found = False
for arch, parent_dir2name in modules.items():
if _dir in parent_dir2name.keys():
found = True
hidden_modules[arch][_dir] = modules[arch][_dir]
modules[arch].pop(_dir)
if not found:
raise KeyError(_dir)
# purge empty dictionaries
empty_arches = []
for arch, parent_dir2name in modules.items():
if len(parent_dir2name.keys()) == 0:
empty_arches.append(arch)
for arch in empty_arches:
modules.pop(arch)
for _dict in [modules, hidden_modules]:
# remove duplicate modules
for arch, parent_dir2name in _dict.items():
for parent_dir, names in parent_dir2name.items():
names = [*set(names)]
# put parent directories in order of how many modules they provide
for arch, parent_dir2name in _dict.items():
_dict[arch] = dict(
sorted(parent_dir2name.items(), key=lambda item: len(item[1]), reverse=True)
)
# put modules in alphabetical order
for arch, parent_dir2name in _dict.items():
for parent_dir, names in parent_dir2name.items():
_dict[arch][parent_dir] = sorted(names)
with open("./public/mfile-layout.json", "w", encoding="utf8") as json_out_file:
json.dump(modules, json_out_file)
with open("./public/mfile-hidden-layout.json", "w", encoding="utf8") as json_out_file:
json.dump(hidden_modules, json_out_file)
with open("./public/directory-prereqs.json", "w", encoding="utf8") as prereqs_file:
json.dump(directory_prereqs, prereqs_file)
print(
"./public/{mfile-layout.json,mfile-hidden-layout.json,directory-prereqs.json} created in your current working directory."
)