Skip to content

Commit ca8ae5c

Browse files
committed
provided a scirpt for moving from device.h to target.json
use -h to find out how it works!
1 parent 986225d commit ca8ae5c

File tree

1 file changed

+204
-0
lines changed

1 file changed

+204
-0
lines changed

workspace_tools/remove-device-h.py

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
import json
2+
import os
3+
import stat
4+
import re
5+
from collections import OrderedDict
6+
from subprocess import Popen
7+
8+
git_processes = []
9+
10+
class MyJSONEncoder(json.JSONEncoder):
11+
def __init__(self, *args, **kwargs):
12+
super(MyJSONEncoder, self).__init__(*args, **kwargs)
13+
self.current_indent = 0
14+
self.current_indent_str = ""
15+
16+
17+
def encode(self, o):
18+
#Special Processing for lists
19+
if isinstance(o, (list, tuple)):
20+
primitives_only = True
21+
for item in o:
22+
if isinstance(item, (list, tuple, dict)):
23+
primitives_only = False
24+
break
25+
output = []
26+
if primitives_only:
27+
for item in o:
28+
output.append(json.dumps(item))
29+
return "[" + ", ".join(output) + "]"
30+
else:
31+
self.current_indent += self.indent
32+
self.current_indent_str = " " * self.current_indent
33+
for item in o:
34+
output.append(self.current_indent_str + self.encode(item))
35+
self.current_indent -= self.indent
36+
self.current_indent_str = " " * self.current_indent
37+
return "[\n" + ",\n".join(output) + "\n" + self.current_indent_str + "]"
38+
elif isinstance(o, dict):
39+
primitives_only = True
40+
for item in o.values():
41+
if isinstance(item, (list, tuple, dict)):
42+
primitives_only = False
43+
break
44+
output = []
45+
if primitives_only and len(o) < 3:
46+
for key, value in o.iteritems():
47+
output.append(json.dumps(key) + ": " + self.encode(value))
48+
return "{" + ", ".join(output) + "}"
49+
else:
50+
self.current_indent += self.indent
51+
self.current_indent_str = " " * self.current_indent
52+
for key, value in o.iteritems():
53+
output.append(self.current_indent_str + json.dumps(key) + ": " + self.encode(value))
54+
self.current_indent -= self.indent
55+
self.current_indent_str = " " * self.current_indent
56+
return "{\n" + ",\n".join(output) + "\n" + self.current_indent_str + "}"
57+
else:
58+
return json.dumps(o)
59+
60+
def load(path):
61+
with open(path, 'r') as f :
62+
return json.load(f, object_pairs_hook=OrderedDict)
63+
64+
def dump(path, obj):
65+
with os.fdopen(os.open(path, os.O_WRONLY | os.O_CREAT, stat.S_IRUSR | stat.S_IWUSR), 'w') as f :
66+
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
67+
f.write(MyJSONEncoder(indent=4).encode(obj))
68+
f.write(u'\n')
69+
f.truncate()
70+
71+
def find(stem, path) :
72+
for root, directories, files in os.walk(path, followlinks=True) :
73+
[dir for dir in directories if dir[0] != '.']
74+
if (stem_match(stem,os.path.basename(os.path.normpath(root))) and
75+
"device.h" in files) :
76+
return os.path.join(root, "device.h")
77+
78+
def find_all_devices(path, verbose=False) :
79+
for root, directories, files in os.walk(path, followlinks=True) :
80+
[dir for dir in directories if dir[0] != '.']
81+
if "device.h" in files :
82+
if verbose : print("[VERBOSE] found a device.h file in {}".format(root))
83+
yield os.path.join(root, "device.h")
84+
85+
mbed_matcher = re.compile('mbed', re.IGNORECASE)
86+
def stem_match(stem, thing) :
87+
return (stem in thing or
88+
re.sub(mbed_matcher, '', stem) in thing)
89+
90+
attr_matcher = re.compile('^#define\W+DEVICE_(\w+)\W+1.*$')
91+
def parse_attributes(path) :
92+
with open(path) as input :
93+
for line in input :
94+
m = re.match(attr_matcher, line)
95+
if m: yield m.group(1)
96+
97+
def user_select(things, message) :
98+
print(message)
99+
for thing, number in zip(things, range(len(things))):
100+
print("{} : {}".format(number, thing))
101+
selection = None
102+
while selection is None :
103+
print("please select an integer [0..{}] or specify all".format(len(things) - 1))
104+
try :
105+
i = raw_input()
106+
if i == "all" :
107+
selection = "all"
108+
else :
109+
selection = int(i)
110+
if (selection > len(things) or
111+
selection < 0) :
112+
print("selection {} out of range".format(selection))
113+
selection = None
114+
except (ValueError, SyntaxError) :
115+
print("selection not understood")
116+
if selection == "all" :
117+
return things
118+
else :
119+
return [things[selection]]
120+
121+
target_matcher = re.compile("TARGET_")
122+
def strip_target(str) :
123+
return re.sub(target_matcher, "", str)
124+
125+
def add_to_targets(targets, device_file, verbose=False, remove=False) :
126+
if verbose : print("[VERBOSE] trying target {}".format(device_file))
127+
device = strip_target(os.path.basename(os.path.normpath(os.path.dirname(device_file))))
128+
if not device :
129+
print("[WARNING] device {} did not have an associated device.h".format(device))
130+
else :
131+
possible_matches = set([key for key in targets.keys() if stem_match(device, key)])
132+
for key, value in targets.iteritems() :
133+
for alt in value['extra_labels'] if 'extra_labels' in value else [] :
134+
if stem_match(device, alt) : possible_matches.add(key)
135+
possible_matches = list(possible_matches)
136+
for match in possible_matches :
137+
if device == match : possible_matches = [match]
138+
if not possible_matches :
139+
print("[WARNING] device {} did not have an associated entry in targets.json".format(device))
140+
return None
141+
elif len(possible_matches) > 1 :
142+
message = ("possible matches for file {}".format(device_file))
143+
target = user_select(possible_matches, message)
144+
else :
145+
target = possible_matches
146+
attrs = list(parse_attributes(device_file))
147+
if attrs :
148+
for t in target :
149+
targets[t]["features"] = sorted(list(set(targets[t].setdefault("features",[]) + attrs)))
150+
if verbose : print("[VERBOSE] target {} now features {}".format(t, attrs))
151+
if remove :
152+
global git_processes
153+
git = Popen(['git', 'rm', device_file])
154+
git_processes.append(git)
155+
156+
if __name__ == '__main__' :
157+
import argparse
158+
parser = argparse.ArgumentParser(description='A helpful little script for converting' +
159+
' device.h files to parts of the targets.json file')
160+
parser.add_argument('-a', '--all', action='store_true',
161+
help='find and convert all available device.h files in the'+
162+
' directory tree starting at the current directory')
163+
parser.add_argument('-f', '--file', nargs='+', help='specify an individual file to '+
164+
'convert from device.h format to a piece of targets.json')
165+
parser.add_argument('-t', '--target', nargs='+', help='specify an individual target'+
166+
' to convert from device.h format to a piece of targets.json')
167+
parser.add_argument('-v', '--verbose', action='store_true',
168+
help="print out every target that is updated in the targets.json")
169+
parser.add_argument('-g', '--git-rm', action='store_true',
170+
help="call git rm on every device.h file")
171+
args = parser.parse_args()
172+
if not args.target and not args.file and not args.all :
173+
print("[WARNING] no action specified; auto-formatting targets.json")
174+
175+
targets_file_name = os.path.join(os.curdir, "hal", "targets.json")
176+
try :
177+
targets = load(targets_file_name)
178+
except OSError :
179+
print("[ERROR] did not find targets.json where I expected it {}".format(targets_file_name))
180+
exit(1)
181+
except ValueError :
182+
print("[ERROR] invalid json found in {}".format(targets_file_name))
183+
exit(2)
184+
185+
if args.target :
186+
for target in args.target :
187+
device_file = find(target, os.curdir)
188+
if device_file :
189+
add_to_targets(targets, device_file, verbose=args.verbose, remove=args.git_rm)
190+
else :
191+
print("[WARNING] could not locate a device file for target {}".format(target))
192+
193+
if args.file :
194+
for file in args.file :
195+
add_to_targets(targets, file, verbose=args.verbose, remove=args.git_rm)
196+
197+
if args.all :
198+
for file in find_all_devices(os.curdir, verbose=args.verbose) :
199+
add_to_targets(targets, file, verbose=args.verbose, remove=args.git_rm)
200+
201+
dump(targets_file_name, targets)
202+
203+
for process in git_processes :
204+
process.wait()

0 commit comments

Comments
 (0)