forked from ros/rosdistro
-
Notifications
You must be signed in to change notification settings - Fork 0
/
check_rosdistro.py
executable file
·176 lines (152 loc) · 5.03 KB
/
check_rosdistro.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/usr/bin/env python
import re
import yaml
import argparse
import sys
indent_atom = ' '
# pretty - A miniature library that provides a Python print and stdout
# wrapper that makes colored terminal text easier to use (eg. without
# having to mess around with ANSI escape sequences). This code is public
# domain - there is no license except that you must leave this header.
#
# Copyright (C) 2008 Brian Nez <thedude at bri1 dot com>
#
# With modifications
# (C) 2013 Paul M <[email protected]>
codeCodes = {
'black': '0;30', 'bright gray': '0;37',
'blue': '0;34', 'white': '1;37',
'green': '0;32', 'bright blue': '1;34',
'cyan': '0;36', 'bright green': '1;32',
'red': '0;31', 'bright cyan': '1;36',
'purple': '0;35', 'bright red': '1;31',
'yellow': '0;33', 'bright purple':'1;35',
'dark gray':'1;30', 'bright yellow':'1;33',
'normal': '0'
}
def printc(text, color):
"""Print in color."""
if sys.stdout.isatty():
print("\033["+codeCodes[color]+"m"+text+"\033[0m")
else:
print(text)
def print_test(msg):
printc(msg, 'yellow')
def print_err(msg):
printc(' ERR: ' + msg, 'red')
def no_trailing_spaces(buf):
clean = True
for i, l in enumerate(buf.split('\n')):
if re.search(r' $', l) is not None:
print_err("trailing space line %u" % (i+1))
clean = False
return clean
def generic_parser(buf, cb):
ilen = len(indent_atom)
stringblock = False
strlvl = 0
lvl = 0
clean = True
for i, l in enumerate(buf.split('\n')):
if l == '':
continue
if re.search(r'^\s*#', l) is not None:
continue
try:
s = re.search(r'(?!' + indent_atom + ')(\w|\?)', l).start()
except:
print_err("line %u: %s" % (i, l))
raise
if stringblock:
if int(s / ilen) > strlvl:
continue
stringblock = False
lvl = s / ilen
opts = {'lvl': lvl, 's': s}
if not cb(i, l, opts):
clean = False
if re.search(r'\|$|\?$|^\s*\?', l) is not None:
stringblock = True
strlvl = lvl
return clean
def correct_indent(buf):
ilen = len(indent_atom)
def fun(i, l, o):
s = o['s']
olvl = fun.lvl
lvl = o['lvl']
fun.lvl = lvl
if s % ilen > 0:
print_err("invalid indentation level line %u: %u" % (i+1, s))
return False
if lvl > olvl + 1:
print_err("too much indentation line %u" % (i+1))
return False
return True
fun.lvl = 0
return generic_parser(buf, fun)
def check_brackets(buf):
excepts = ['uri', 'md5sum']
def fun(i, l, o):
m = re.match(r'^(?:' + indent_atom + r')*([^:]*):\s*(\w.*)$', l)
if m is not None and m.groups()[0] not in excepts:
print_err("list not in square brackets line %u" % (i+1))
return False
return True
return generic_parser(buf, fun)
def check_order(buf):
def fun(i, l, o):
lvl = o['lvl']
st = fun.namestack
while len(st) > lvl + 1:
st.pop()
if len(st) < lvl + 1:
st.append('')
if re.search(r'^\s*\?', l) is not None:
return True
m = re.match(r'^(?:' + indent_atom + r')*([^:]*):.*$', l)
prev = st[lvl]
try:
item = m.groups()[0]
except:
print('woops line %d' % i)
raise
st[lvl] = item
if item < prev:
print_err("list out of alphabetical order line %u" % (i+1))
return False
return True
fun.namestack = ['']
return generic_parser(buf, fun)
def main(fname):
with open(fname) as f:
buf = f.read()
def my_assert(val):
if not val:
my_assert.clean = False
my_assert.clean = True
try:
ydict = yaml.safe_load(buf)
except Exception as e:
print_err("could not build the dict: %s" % (str(e)))
my_assert(False)
if 'release-name' not in ydict and isinstance(ydict, dict) and 'fuerte' not in ydict.keys():
print_err("The file does not contain a 'release-name'. (Only files for Fuerte and older are supported by this script)")
else:
print_test("checking for trailing spaces...")
my_assert(no_trailing_spaces(buf))
print_test("checking for incorrect indentation...")
my_assert(correct_indent(buf))
print_test("checking for item order...")
my_assert(check_order(buf))
print_test("building yaml dict...")
if not my_assert.clean:
printc("there were errors, please correct the file", 'bright red')
return False
return True
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Checks whether yaml syntax corresponds to ROS rules')
parser.add_argument('infile', help='input rosdep YAML file')
args = parser.parse_args()
if not main(args.infile):
sys.exit(1)