]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Lib/tabnanny.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / tabnanny.py
CommitLineData
4710c53d 1#! /usr/bin/env python\r
2\r
3"""The Tab Nanny despises ambiguous indentation. She knows no mercy.\r
4\r
5tabnanny -- Detection of ambiguous indentation\r
6\r
7For the time being this module is intended to be called as a script.\r
8However it is possible to import it into an IDE and use the function\r
9check() described below.\r
10\r
11Warning: The API provided by this module is likely to change in future\r
12releases; such changes may not be backward compatible.\r
13"""\r
14\r
15# Released to the public domain, by Tim Peters, 15 April 1998.\r
16\r
17# XXX Note: this is now a standard library module.\r
18# XXX The API needs to undergo changes however; the current code is too\r
19# XXX script-like. This will be addressed later.\r
20\r
21__version__ = "6"\r
22\r
23import os\r
24import sys\r
25import getopt\r
26import tokenize\r
27if not hasattr(tokenize, 'NL'):\r
28 raise ValueError("tokenize.NL doesn't exist -- tokenize module too old")\r
29\r
30__all__ = ["check", "NannyNag", "process_tokens"]\r
31\r
32verbose = 0\r
33filename_only = 0\r
34\r
35def errprint(*args):\r
36 sep = ""\r
37 for arg in args:\r
38 sys.stderr.write(sep + str(arg))\r
39 sep = " "\r
40 sys.stderr.write("\n")\r
41\r
42def main():\r
43 global verbose, filename_only\r
44 try:\r
45 opts, args = getopt.getopt(sys.argv[1:], "qv")\r
46 except getopt.error, msg:\r
47 errprint(msg)\r
48 return\r
49 for o, a in opts:\r
50 if o == '-q':\r
51 filename_only = filename_only + 1\r
52 if o == '-v':\r
53 verbose = verbose + 1\r
54 if not args:\r
55 errprint("Usage:", sys.argv[0], "[-v] file_or_directory ...")\r
56 return\r
57 for arg in args:\r
58 check(arg)\r
59\r
60class NannyNag(Exception):\r
61 """\r
62 Raised by tokeneater() if detecting an ambiguous indent.\r
63 Captured and handled in check().\r
64 """\r
65 def __init__(self, lineno, msg, line):\r
66 self.lineno, self.msg, self.line = lineno, msg, line\r
67 def get_lineno(self):\r
68 return self.lineno\r
69 def get_msg(self):\r
70 return self.msg\r
71 def get_line(self):\r
72 return self.line\r
73\r
74def check(file):\r
75 """check(file_or_dir)\r
76\r
77 If file_or_dir is a directory and not a symbolic link, then recursively\r
78 descend the directory tree named by file_or_dir, checking all .py files\r
79 along the way. If file_or_dir is an ordinary Python source file, it is\r
80 checked for whitespace related problems. The diagnostic messages are\r
81 written to standard output using the print statement.\r
82 """\r
83\r
84 if os.path.isdir(file) and not os.path.islink(file):\r
85 if verbose:\r
86 print "%r: listing directory" % (file,)\r
87 names = os.listdir(file)\r
88 for name in names:\r
89 fullname = os.path.join(file, name)\r
90 if (os.path.isdir(fullname) and\r
91 not os.path.islink(fullname) or\r
92 os.path.normcase(name[-3:]) == ".py"):\r
93 check(fullname)\r
94 return\r
95\r
96 try:\r
97 f = open(file)\r
98 except IOError, msg:\r
99 errprint("%r: I/O Error: %s" % (file, msg))\r
100 return\r
101\r
102 if verbose > 1:\r
103 print "checking %r ..." % file\r
104\r
105 try:\r
106 process_tokens(tokenize.generate_tokens(f.readline))\r
107\r
108 except tokenize.TokenError, msg:\r
109 errprint("%r: Token Error: %s" % (file, msg))\r
110 return\r
111\r
112 except IndentationError, msg:\r
113 errprint("%r: Indentation Error: %s" % (file, msg))\r
114 return\r
115\r
116 except NannyNag, nag:\r
117 badline = nag.get_lineno()\r
118 line = nag.get_line()\r
119 if verbose:\r
120 print "%r: *** Line %d: trouble in tab city! ***" % (file, badline)\r
121 print "offending line: %r" % (line,)\r
122 print nag.get_msg()\r
123 else:\r
124 if ' ' in file: file = '"' + file + '"'\r
125 if filename_only: print file\r
126 else: print file, badline, repr(line)\r
127 return\r
128\r
129 if verbose:\r
130 print "%r: Clean bill of health." % (file,)\r
131\r
132class Whitespace:\r
133 # the characters used for space and tab\r
134 S, T = ' \t'\r
135\r
136 # members:\r
137 # raw\r
138 # the original string\r
139 # n\r
140 # the number of leading whitespace characters in raw\r
141 # nt\r
142 # the number of tabs in raw[:n]\r
143 # norm\r
144 # the normal form as a pair (count, trailing), where:\r
145 # count\r
146 # a tuple such that raw[:n] contains count[i]\r
147 # instances of S * i + T\r
148 # trailing\r
149 # the number of trailing spaces in raw[:n]\r
150 # It's A Theorem that m.indent_level(t) ==\r
151 # n.indent_level(t) for all t >= 1 iff m.norm == n.norm.\r
152 # is_simple\r
153 # true iff raw[:n] is of the form (T*)(S*)\r
154\r
155 def __init__(self, ws):\r
156 self.raw = ws\r
157 S, T = Whitespace.S, Whitespace.T\r
158 count = []\r
159 b = n = nt = 0\r
160 for ch in self.raw:\r
161 if ch == S:\r
162 n = n + 1\r
163 b = b + 1\r
164 elif ch == T:\r
165 n = n + 1\r
166 nt = nt + 1\r
167 if b >= len(count):\r
168 count = count + [0] * (b - len(count) + 1)\r
169 count[b] = count[b] + 1\r
170 b = 0\r
171 else:\r
172 break\r
173 self.n = n\r
174 self.nt = nt\r
175 self.norm = tuple(count), b\r
176 self.is_simple = len(count) <= 1\r
177\r
178 # return length of longest contiguous run of spaces (whether or not\r
179 # preceding a tab)\r
180 def longest_run_of_spaces(self):\r
181 count, trailing = self.norm\r
182 return max(len(count)-1, trailing)\r
183\r
184 def indent_level(self, tabsize):\r
185 # count, il = self.norm\r
186 # for i in range(len(count)):\r
187 # if count[i]:\r
188 # il = il + (i/tabsize + 1)*tabsize * count[i]\r
189 # return il\r
190\r
191 # quicker:\r
192 # il = trailing + sum (i/ts + 1)*ts*count[i] =\r
193 # trailing + ts * sum (i/ts + 1)*count[i] =\r
194 # trailing + ts * sum i/ts*count[i] + count[i] =\r
195 # trailing + ts * [(sum i/ts*count[i]) + (sum count[i])] =\r
196 # trailing + ts * [(sum i/ts*count[i]) + num_tabs]\r
197 # and note that i/ts*count[i] is 0 when i < ts\r
198\r
199 count, trailing = self.norm\r
200 il = 0\r
201 for i in range(tabsize, len(count)):\r
202 il = il + i/tabsize * count[i]\r
203 return trailing + tabsize * (il + self.nt)\r
204\r
205 # return true iff self.indent_level(t) == other.indent_level(t)\r
206 # for all t >= 1\r
207 def equal(self, other):\r
208 return self.norm == other.norm\r
209\r
210 # return a list of tuples (ts, i1, i2) such that\r
211 # i1 == self.indent_level(ts) != other.indent_level(ts) == i2.\r
212 # Intended to be used after not self.equal(other) is known, in which\r
213 # case it will return at least one witnessing tab size.\r
214 def not_equal_witness(self, other):\r
215 n = max(self.longest_run_of_spaces(),\r
216 other.longest_run_of_spaces()) + 1\r
217 a = []\r
218 for ts in range(1, n+1):\r
219 if self.indent_level(ts) != other.indent_level(ts):\r
220 a.append( (ts,\r
221 self.indent_level(ts),\r
222 other.indent_level(ts)) )\r
223 return a\r
224\r
225 # Return True iff self.indent_level(t) < other.indent_level(t)\r
226 # for all t >= 1.\r
227 # The algorithm is due to Vincent Broman.\r
228 # Easy to prove it's correct.\r
229 # XXXpost that.\r
230 # Trivial to prove n is sharp (consider T vs ST).\r
231 # Unknown whether there's a faster general way. I suspected so at\r
232 # first, but no longer.\r
233 # For the special (but common!) case where M and N are both of the\r
234 # form (T*)(S*), M.less(N) iff M.len() < N.len() and\r
235 # M.num_tabs() <= N.num_tabs(). Proof is easy but kinda long-winded.\r
236 # XXXwrite that up.\r
237 # Note that M is of the form (T*)(S*) iff len(M.norm[0]) <= 1.\r
238 def less(self, other):\r
239 if self.n >= other.n:\r
240 return False\r
241 if self.is_simple and other.is_simple:\r
242 return self.nt <= other.nt\r
243 n = max(self.longest_run_of_spaces(),\r
244 other.longest_run_of_spaces()) + 1\r
245 # the self.n >= other.n test already did it for ts=1\r
246 for ts in range(2, n+1):\r
247 if self.indent_level(ts) >= other.indent_level(ts):\r
248 return False\r
249 return True\r
250\r
251 # return a list of tuples (ts, i1, i2) such that\r
252 # i1 == self.indent_level(ts) >= other.indent_level(ts) == i2.\r
253 # Intended to be used after not self.less(other) is known, in which\r
254 # case it will return at least one witnessing tab size.\r
255 def not_less_witness(self, other):\r
256 n = max(self.longest_run_of_spaces(),\r
257 other.longest_run_of_spaces()) + 1\r
258 a = []\r
259 for ts in range(1, n+1):\r
260 if self.indent_level(ts) >= other.indent_level(ts):\r
261 a.append( (ts,\r
262 self.indent_level(ts),\r
263 other.indent_level(ts)) )\r
264 return a\r
265\r
266def format_witnesses(w):\r
267 firsts = map(lambda tup: str(tup[0]), w)\r
268 prefix = "at tab size"\r
269 if len(w) > 1:\r
270 prefix = prefix + "s"\r
271 return prefix + " " + ', '.join(firsts)\r
272\r
273def process_tokens(tokens):\r
274 INDENT = tokenize.INDENT\r
275 DEDENT = tokenize.DEDENT\r
276 NEWLINE = tokenize.NEWLINE\r
277 JUNK = tokenize.COMMENT, tokenize.NL\r
278 indents = [Whitespace("")]\r
279 check_equal = 0\r
280\r
281 for (type, token, start, end, line) in tokens:\r
282 if type == NEWLINE:\r
283 # a program statement, or ENDMARKER, will eventually follow,\r
284 # after some (possibly empty) run of tokens of the form\r
285 # (NL | COMMENT)* (INDENT | DEDENT+)?\r
286 # If an INDENT appears, setting check_equal is wrong, and will\r
287 # be undone when we see the INDENT.\r
288 check_equal = 1\r
289\r
290 elif type == INDENT:\r
291 check_equal = 0\r
292 thisguy = Whitespace(token)\r
293 if not indents[-1].less(thisguy):\r
294 witness = indents[-1].not_less_witness(thisguy)\r
295 msg = "indent not greater e.g. " + format_witnesses(witness)\r
296 raise NannyNag(start[0], msg, line)\r
297 indents.append(thisguy)\r
298\r
299 elif type == DEDENT:\r
300 # there's nothing we need to check here! what's important is\r
301 # that when the run of DEDENTs ends, the indentation of the\r
302 # program statement (or ENDMARKER) that triggered the run is\r
303 # equal to what's left at the top of the indents stack\r
304\r
305 # Ouch! This assert triggers if the last line of the source\r
306 # is indented *and* lacks a newline -- then DEDENTs pop out\r
307 # of thin air.\r
308 # assert check_equal # else no earlier NEWLINE, or an earlier INDENT\r
309 check_equal = 1\r
310\r
311 del indents[-1]\r
312\r
313 elif check_equal and type not in JUNK:\r
314 # this is the first "real token" following a NEWLINE, so it\r
315 # must be the first token of the next program statement, or an\r
316 # ENDMARKER; the "line" argument exposes the leading whitespace\r
317 # for this statement; in the case of ENDMARKER, line is an empty\r
318 # string, so will properly match the empty string with which the\r
319 # "indents" stack was seeded\r
320 check_equal = 0\r
321 thisguy = Whitespace(line)\r
322 if not indents[-1].equal(thisguy):\r
323 witness = indents[-1].not_equal_witness(thisguy)\r
324 msg = "indent not equal e.g. " + format_witnesses(witness)\r
325 raise NannyNag(start[0], msg, line)\r
326\r
327\r
328if __name__ == '__main__':\r
329 main()\r