Skip to content

Commit ae22684

Browse files
committed
Added simple linter for targets.json
1 parent 9b082ff commit ae22684

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed

tools/targets/lint.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
"""A linting utility for targets.json"""
2+
3+
from os.path import join, abspath, dirname
4+
if __name__ == "__main__":
5+
import sys
6+
ROOT = abspath(join(dirname(__file__), "..", ".."))
7+
sys.path.insert(0, ROOT)
8+
from copy import copy
9+
from yaml import dump
10+
from tools.targets import Target, set_targets_json_location, TARGET_MAP
11+
12+
def must_have_keys(keys, dict):
13+
for key in keys:
14+
if key not in dict:
15+
yield "%s not found, and is required" % key
16+
17+
def may_have_keys(keys, dict):
18+
for key in dict.keys():
19+
if key not in keys:
20+
yield "%s found, and is not allowed" % key
21+
22+
23+
MCU_REQUIRED_KEYS = ["release_versions", "supported_toolchains",
24+
"default_lib", "public", "inherits"]
25+
MCU_ALLOWED_KEYS = ["device_has", "core", "extra_labels", "features", "bootloader_supported", "device_name", "post_binary_hook", "default_toolchain"] + MCU_REQUIRED_KEYS
26+
def check_mcu(mcu_json, strict=False):
27+
"""Generate a list of problems with an mcu"""
28+
if strict:
29+
for err in must_have_keys(MCU_REQUIRED_KEYS, mcu_json):
30+
yield err
31+
for err in may_have_keys(MCU_ALLOWED_KEYS, mcu_json):
32+
yield err
33+
if 'public' in mcu_json and mcu_json['public']:
34+
yield "public must be false"
35+
if ("release_versions" in mcu_json and
36+
"5" in mcu_json["release_versions"] and
37+
"supported_toolchains" in mcu_json):
38+
for tc in ["GCC_ARM", "ARM", "IAR"]:
39+
if tc not in mcu_json["supported_toolchains"]:
40+
yield ("%s not found in supported_toolchains, and is "
41+
"required by mbed OS 5" % tc)
42+
43+
BOARD_REQUIRED_KEYS = ["inherits"]
44+
BOARD_ALLOWED_KEYS = ["supported_form_factors", "is_disk_virtual", "detect_code", "device_name", "extra_labels", "public"] + BOARD_REQUIRED_KEYS
45+
def check_board(board_json, strict=False):
46+
if strict:
47+
for err in must_have_keys(BOARD_REQUIRED_KEYS, board_json):
48+
yield err
49+
for err in may_have_keys(BOARD_ALLOWED_KEYS, board_json):
50+
yield err
51+
52+
53+
def add_if(dict, key, val):
54+
if val:
55+
dict[key] = val
56+
57+
def _split_boards(resolution_order, tgt):
58+
mcus = []
59+
boards = []
60+
iterable = iter(resolution_order)
61+
for name in iterable:
62+
mcu_json = tgt.json_data[name]
63+
if (len(list(check_mcu(mcu_json, True))) >
64+
len(list(check_board(mcu_json, True)))):
65+
boards.append(name)
66+
else:
67+
mcus.append(name)
68+
break
69+
mcus.extend(iterable)
70+
mcus.reverse()
71+
boards.reverse()
72+
return mcus, boards
73+
74+
75+
MCU_FORMAT_STRING = {1: "MCU (%s) ->",
76+
2: "Family (%s) -> MCU (%s) ->",
77+
3: "Family (%s) -> SubFamily (%s) -> MCU (%s) ->"}
78+
BOARD_FORMAT_STRING = {1: "Board (%s)",
79+
2: "Module (%s) -> Board (%s)"}
80+
def _generate_hierarchy_string(mcus, boards):
81+
global_errors = []
82+
if len(mcus) < 1:
83+
global_errors.append("No MCUS found in heirarchy")
84+
mcus_string = "??? ->"
85+
elif len(mcus) > 3:
86+
global_errors.append("No name for targets: %s" % mcus[3:])
87+
mcus_string = MCU_FORMAT_STRING[3] % tuple(mcus[:3])
88+
for name in mcus[3:]:
89+
mcus_string += " ??? (%s) ->" % name
90+
else:
91+
mcus_string = MCU_FORMAT_STRING[len(mcus)] % tuple(mcus)
92+
93+
if len(boards) < 1:
94+
global_errors.append("no boards found in heirarchy")
95+
boards_string = "???"
96+
elif len(boards) > 2:
97+
global_errors.append("no name for targets: %s" % boards[2:])
98+
boards_string = BOARD_FORMAT_STRING[3] % tuple(boards[:2])
99+
for name in boards[2:]:
100+
boards_string += " ??? (%s)" % name
101+
else:
102+
boards_string = BOARD_FORMAT_STRING[len(boards)] % tuple(boards)
103+
return mcus_string + " " + boards_string, global_errors
104+
105+
106+
def check_hierarchy(tgt):
107+
"""Atempts to assign labels to the heirarchy"""
108+
resolution_order = copy(tgt.resolution_order_names[:-1])
109+
mcus, boards = _split_boards(resolution_order, tgt)
110+
111+
target_errors = {}
112+
hierachy_string, hierachy_errors = _generate_hierarchy_string(mcus, boards)
113+
to_ret = {"hierarchy": hierachy_string}
114+
add_if(to_ret, "hierachy errors", hierachy_errors)
115+
116+
for name in mcus[:-1]:
117+
add_if(target_errors, name, list(check_mcu(tgt.json_data[name])))
118+
if len(mcus) >= 1:
119+
add_if(target_errors, mcus[-1],
120+
list(check_mcu(tgt.json_data[mcus[-1]], True)))
121+
for name in boards:
122+
add_if(target_errors, name, list(check_board(tgt.json_data[name])))
123+
if len(boards) >= 1:
124+
add_if(target_errors, boards[-1],
125+
list(check_board(tgt.json_data[boards[-1]], True)))
126+
add_if(to_ret, "target errors", target_errors)
127+
return to_ret
128+
129+
130+
def main():
131+
import argparse
132+
parser = argparse.ArgumentParser()
133+
parser.add_argument("mcu", choices=TARGET_MAP.keys(), metavar="MCU")
134+
options = parser.parse_args()
135+
print dump(check_hierarchy(TARGET_MAP[options.mcu]), default_flow_style=False)
136+
return 0
137+
138+
if __name__ == "__main__":
139+
sys.exit(main())
140+

0 commit comments

Comments
 (0)