blob: 67d817e584f06f2be9f612f4fe7bd1169fec9483 [file] [log] [blame]
Behdad Esfahbod91540a72012-01-20 18:27:52 -05001#!/usr/bin/python
2
Behdad Esfahbod3a34e9e2012-01-21 19:15:41 -05003import sys, os, re, difflib, unicodedata, errno
Behdad Esfahbod91540a72012-01-20 18:27:52 -05004
5class Colors:
6 class Null:
7 red = ''
8 green = ''
9 end = ''
10 class ANSI:
11 red = '\033[41;37;1m'
12 green = '\033[42;37;1m'
13 end = '\033[m'
14 class HTML:
15 red = '<span style="color:red">'
16 green = '<span style="color:green">'
17 end = '</span>'
18
19 @staticmethod
20 def Auto (argv = [], out = sys.stdout):
21 if "--color" in argv or os.isatty (out.fileno ()):
22 if "--color" in sys.argv[1:]:
23 argv.remove ("--color")
Behdad Esfahbodf22089a2012-01-20 21:21:47 -050024 return Colors.ANSI, argv
Behdad Esfahbod91540a72012-01-20 18:27:52 -050025 else:
Behdad Esfahbodf22089a2012-01-20 21:21:47 -050026 return Colors.Null, argv
Behdad Esfahbod91540a72012-01-20 18:27:52 -050027
Behdad Esfahbodad34e392012-01-20 18:39:27 -050028 @staticmethod
29 def Default (argv = []):
30 return Colors.ANSI
31
Behdad Esfahbod91540a72012-01-20 18:27:52 -050032
33class FancyDiffer:
34
35 diff_regex = re.compile ('([a-za-z0-9_]*)([^a-za-z0-9_]?)')
36
37 @staticmethod
38 def diff_lines (l1, l2, colors=Colors.Null):
39
40 ss = [FancyDiffer.diff_regex.sub (r'\1\n\2\n', l).splitlines (True) for l in (l1, l2)]
41 oo = ["",""]
42 st = [False, False]
43 for l in difflib.Differ().compare (*ss):
44 if l[0] == '?':
45 continue
46 if l[0] == ' ':
47 for i in range(2):
48 if st[i]:
49 oo[i] += colors.end
50 st[i] = False
51 oo = [o + l[2:] for o in oo]
52 continue
53 if l[0] == '-':
54 if not st[0]:
55 oo[0] += colors.red
56 st[0] = True
57 oo[0] += l[2:]
58 continue
59 if l[0] == '+':
60 if not st[1]:
61 oo[1] += colors.green
62 st[1] = True
63 oo[1] += l[2:]
64 for i in range(2):
65 if st[i]:
66 oo[i] += colors.end
67 st[i] = 0
68 oo = [o.replace ('\n', '') for o in oo]
69 if oo[0] == oo[1]:
70 return [' ', oo[0], '\n']
71 return ['-', oo[0], '\n', '+', oo[1], '\n']
72
73 @staticmethod
74 def diff_files (f1, f2, colors=Colors.Null):
Behdad Esfahbod3a34e9e2012-01-21 19:15:41 -050075 try:
76 for (l1,l2) in zip (f1, f2):
77 if l1 == l2:
78 sys.stdout.writelines ([" ", l1])
79 continue
Behdad Esfahbod91540a72012-01-20 18:27:52 -050080
Behdad Esfahbod3a34e9e2012-01-21 19:15:41 -050081 sys.stdout.writelines (FancyDiffer.diff_lines (l1, l2, colors))
82 # print out residues
83 for l in f1:
84 sys.stdout.writelines (["-", colors.red, l1, colors.end])
85 for l in f1:
86 sys.stdout.writelines (["-", colors.green, l1, colors.end])
87 except IOError as e:
88 if e.errno != errno.EPIPE:
Behdad Esfahbod956d5522012-01-21 19:31:51 -050089 print >> sys.stderr, "%s: %s: %s" % (sys.argv[0], e.filename, e.strerror)
Behdad Esfahbod3a34e9e2012-01-21 19:15:41 -050090 sys.exit (1)
Behdad Esfahbod91540a72012-01-20 18:27:52 -050091
Behdad Esfahbodad34e392012-01-20 18:39:27 -050092
Behdad Esfahbod91540a72012-01-20 18:27:52 -050093class DiffFilters:
94
95 @staticmethod
96 def filter_failures (f):
97 for l in f:
98 if l[0] in '-+':
99 sys.stdout.writelines (l)
100
101
Behdad Esfahbodad34e392012-01-20 18:39:27 -0500102class ShapeFilters:
103
104 @staticmethod
105 def filter_failures (f):
106 for l in f:
107 if l[0] in '-+':
108 sys.stdout.writelines (l)
109
110
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500111class UtilMains:
112
113 @staticmethod
Behdad Esfahbod96968bf2012-01-20 21:16:34 -0500114 def process_multiple_files (callback, mnemonic = "FILE"):
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500115
116 if len (sys.argv) == 1:
Behdad Esfahbod96968bf2012-01-20 21:16:34 -0500117 print "Usage: %s %s..." % (sys.argv[0], mnemonic)
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500118 sys.exit (1)
119
Behdad Esfahbod3a34e9e2012-01-21 19:15:41 -0500120 try:
121 for s in sys.argv[1:]:
122 callback (FileHelpers.open_file_or_stdin (s))
123 except IOError as e:
124 if e.errno != errno.EPIPE:
Behdad Esfahbod956d5522012-01-21 19:31:51 -0500125 print >> sys.stderr, "%s: %s: %s" % (sys.argv[0], e.filename, e.strerror)
Behdad Esfahbod3a34e9e2012-01-21 19:15:41 -0500126 sys.exit (1)
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500127
128 @staticmethod
Behdad Esfahbod96968bf2012-01-20 21:16:34 -0500129 def process_multiple_args (callback, mnemonic):
130
131 if len (sys.argv) == 1:
132 print "Usage: %s %s..." % (sys.argv[0], mnemonic)
133 sys.exit (1)
134
Behdad Esfahbod3a34e9e2012-01-21 19:15:41 -0500135 try:
136 for s in sys.argv[1:]:
137 callback (s)
138 except IOError as e:
139 if e.errno != errno.EPIPE:
Behdad Esfahbod956d5522012-01-21 19:31:51 -0500140 print >> sys.stderr, "%s: %s: %s" % (sys.argv[0], e.filename, e.strerror)
Behdad Esfahbod3a34e9e2012-01-21 19:15:41 -0500141 sys.exit (1)
Behdad Esfahbod96968bf2012-01-20 21:16:34 -0500142
143 @staticmethod
144 def filter_multiple_strings_or_stdin (callback, mnemonic, \
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500145 separator = " ", \
146 concat_separator = False):
147
148 if len (sys.argv) == 1 or ('--stdin' in sys.argv and len (sys.argv) != 2):
149 print "Usage:\n %s %s...\nor:\n %s --stdin" \
Behdad Esfahbod96968bf2012-01-20 21:16:34 -0500150 % (sys.argv[0], mnemonic, sys.argv[0])
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500151 sys.exit (1)
152
Behdad Esfahbod3a34e9e2012-01-21 19:15:41 -0500153 try:
154 if '--stdin' in sys.argv:
155 sys.argv.remove ('--stdin')
156 while (1):
157 line = sys.stdin.readline ()
158 if not len (line):
159 break
160 print callback (line)
161 else:
162 args = sys.argv[1:]
163 if concat_separator != False:
164 args = [concat_separator.join (args)]
165 print separator.join (callback (x) for x in (args))
166 except IOError as e:
167 if e.errno != errno.EPIPE:
Behdad Esfahbod956d5522012-01-21 19:31:51 -0500168 print >> sys.stderr, "%s: %s: %s" % (sys.argv[0], e.filename, e.strerror)
Behdad Esfahbod3a34e9e2012-01-21 19:15:41 -0500169 sys.exit (1)
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500170
171
172class Unicode:
173
174 @staticmethod
175 def decode (s):
Behdad Esfahbod46ac4562012-01-20 19:32:17 -0500176 return '<' + u','.join ("U+%04X" % ord (u) for u in unicode (s, 'utf-8')).encode ('utf-8') + '>'
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500177
178 @staticmethod
179 def encode (s):
Behdad Esfahbod46ac4562012-01-20 19:32:17 -0500180 s = re.sub (r"[<+>,\\uU\n ]", " ", s)
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500181 s = re.sub (r"0[xX]", " ", s)
Behdad Esfahbod46ac4562012-01-20 19:32:17 -0500182 return u''.join (unichr (int (x, 16)) for x in s.split (' ') if len (x)).encode ('utf-8')
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500183
184 shorthands = {
185 "ZERO WIDTH NON-JOINER": "ZWNJ",
186 "ZERO WIDTH JOINER": "ZWJ",
187 "NARROW NO-BREAK SPACE": "NNBSP",
188 "COMBINING GRAPHEME JOINER": "CGJ",
189 "LEFT-TO-RIGHT MARK": "LRM",
190 "RIGHT-TO-LEFT MARK": "RLM",
191 "LEFT-TO-RIGHT EMBEDDING": "LRE",
192 "RIGHT-TO-LEFT EMBEDDING": "RLE",
193 "POP DIRECTIONAL FORMATTING": "PDF",
194 "LEFT-TO-RIGHT OVERRIDE": "LRO",
195 "RIGHT-TO-LEFT OVERRIDE": "RLO",
196 }
197
198 @staticmethod
199 def pretty_name (u):
200 try:
201 s = unicodedata.name (u)
202 except ValueError:
203 return "XXX"
204 s = re.sub (".* LETTER ", "", s)
205 s = re.sub (".* VOWEL SIGN (.*)", r"\1-MATRA", s)
206 s = re.sub (".* SIGN ", "", s)
207 s = re.sub (".* COMBINING ", "", s)
208 if re.match (".* VIRAMA", s):
209 s = "HALANT"
210 if s in Unicode.shorthands:
211 s = Unicode.shorthands[s]
212 return s
213
214 @staticmethod
215 def pretty_names (s):
216 s = re.sub (r"[<+>\\uU]", " ", s)
217 s = re.sub (r"0[xX]", " ", s)
218 s = [unichr (int (x, 16)) for x in re.split ('[, \n]', s) if len (x)]
Behdad Esfahbod46ac4562012-01-20 19:32:17 -0500219 return u' + '.join (Unicode.pretty_name (x) for x in s).encode ('utf-8')
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500220
Behdad Esfahbodad34e392012-01-20 18:39:27 -0500221
Behdad Esfahbod96968bf2012-01-20 21:16:34 -0500222class FileHelpers:
Behdad Esfahbodad34e392012-01-20 18:39:27 -0500223
224 @staticmethod
225 def open_file_or_stdin (f):
226 if f == '-':
227 return sys.stdin
228 return file (f)
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500229
Behdad Esfahbod96968bf2012-01-20 21:16:34 -0500230
231class Manifest:
232
233 @staticmethod
234 def print_to_stdout (s, strict = True):
235 if not os.path.exists (s):
236 if strict:
237 print >> sys.stderr, "%s: %s does not exist" (sys.argv[0], s)
238 sys.exit (1)
239 return
240
241 if os.path.isdir (s):
242
Behdad Esfahbod956d5522012-01-21 19:31:51 -0500243 if s[-1] in '/\\':
244 s = s[:-1]
Behdad Esfahbod96968bf2012-01-20 21:16:34 -0500245
246 try:
Behdad Esfahbod956d5522012-01-21 19:31:51 -0500247 m = file (os.path.join (s, "MANIFEST"))
Behdad Esfahbod96968bf2012-01-20 21:16:34 -0500248 items = [x.strip () for x in m.readlines ()]
249 for f in items:
250 Manifest.print_to_stdout (s + f)
251 except IOError:
252 if strict:
Behdad Esfahbod956d5522012-01-21 19:31:51 -0500253 print >> sys.stderr, "%s: %s does not exist" (sys.argv[0], os.path.join (s, "MANIFEST"))
Behdad Esfahbod96968bf2012-01-20 21:16:34 -0500254 sys.exit (1)
255 return
256 else:
257 print s
258
Behdad Esfahbod956d5522012-01-21 19:31:51 -0500259 @staticmethod
260 def update_recursive (s):
261
262 for dirpath, dirnames, filenames in os.walk (s, followlinks=True):
263
264 for f in ["MANIFEST", "README", "LICENSE", "COPYING", "AUTHORS", "SOURCES"]:
265 if f in dirnames:
266 dirnames.remove (f)
267 if f in filenames:
268 filenames.remove (f)
269 dirnames.sort ()
270 filenames.sort ()
271 ms = os.path.join (dirpath, "MANIFEST")
272 print " GEN %s" % ms
273 m = open (ms, "w")
274 for f in filenames:
275 print >> m, f
276 for f in dirnames:
277 print >> m, f
278 for f in dirnames:
279 Manifest.update_recursive (os.path.join (dirpath, f))
280
Behdad Esfahbod91540a72012-01-20 18:27:52 -0500281if __name__ == '__main__':
282 pass