UtilitiesPython2/Tabnanny.py

changeset 945
8cd4d08fa9f6
parent 805
83ca4d1ff648
child 2965
d133c7edd88a
equal deleted inserted replaced
944:1b59c4ba121e 945:8cd4d08fa9f6
46 if not hasattr(tokenize, 'NL'): 46 if not hasattr(tokenize, 'NL'):
47 raise ValueError("tokenize.NL doesn't exist -- tokenize module too old") 47 raise ValueError("tokenize.NL doesn't exist -- tokenize module too old")
48 48
49 __all__ = ["check", "NannyNag", "process_tokens"] 49 __all__ = ["check", "NannyNag", "process_tokens"]
50 50
51
51 class NannyNag(Exception): 52 class NannyNag(Exception):
52 """ 53 """
53 Raised by tokeneater() if detecting an ambiguous indent. 54 Raised by tokeneater() if detecting an ambiguous indent.
54 Captured and handled in check(). 55 Captured and handled in check().
55 """ 56 """
84 Method to retrieve the offending line. 85 Method to retrieve the offending line.
85 86
86 @return The line of code (string) 87 @return The line of code (string)
87 """ 88 """
88 return self.line 89 return self.line
90
89 91
90 def check(filename, codestring): 92 def check(filename, codestring):
91 """ 93 """
92 Private function to check one Python source file for whitespace related problems. 94 Private function to check one Python source file for whitespace related problems.
93 95
119 121
120 except Exception, err: 122 except Exception, err:
121 return (True, filename, "1", "Unspecific Error: %s" % unicode(err)) 123 return (True, filename, "1", "Unspecific Error: %s" % unicode(err))
122 124
123 return (False, None, None, None) 125 return (False, None, None, None)
126
124 127
125 class Whitespace(object): 128 class Whitespace(object):
126 """ 129 """
127 Class implementing the whitespace checker. 130 Class implementing the whitespace checker.
128 """ 131 """
152 """ 155 """
153 Constructor 156 Constructor
154 157
155 @param ws The string to be checked. 158 @param ws The string to be checked.
156 """ 159 """
157 self.raw = ws 160 self.raw = ws
158 S, T = Whitespace.S, Whitespace.T 161 S, T = Whitespace.S, Whitespace.T
159 count = [] 162 count = []
160 b = n = nt = 0 163 b = n = nt = 0
161 for ch in self.raw: 164 for ch in self.raw:
162 if ch == S: 165 if ch == S:
169 count = count + [0] * (b - len(count) + 1) 172 count = count + [0] * (b - len(count) + 1)
170 count[b] = count[b] + 1 173 count[b] = count[b] + 1
171 b = 0 174 b = 0
172 else: 175 else:
173 break 176 break
174 self.n = n 177 self.n = n
175 self.nt = nt 178 self.nt = nt
176 self.norm = tuple(count), b 179 self.norm = tuple(count), b
177 self.is_simple = len(count) <= 1 180 self.is_simple = len(count) <= 1
178 181
179 # return length of longest contiguous run of spaces (whether or not 182 # return length of longest contiguous run of spaces (whether or not
180 # preceding a tab) 183 # preceding a tab)
184 187
185 @return The length of longest contiguous run of spaces (whether or not 188 @return The length of longest contiguous run of spaces (whether or not
186 preceding a tab) 189 preceding a tab)
187 """ 190 """
188 count, trailing = self.norm 191 count, trailing = self.norm
189 return max(len(count)-1, trailing) 192 return max(len(count) - 1, trailing)
190 193
191 def indent_level(self, tabsize): 194 def indent_level(self, tabsize):
192 """ 195 """
193 Method to determine the indentation level. 196 Method to determine the indentation level.
194 197
210 # and note that i/ts*count[i] is 0 when i < ts 213 # and note that i/ts*count[i] is 0 when i < ts
211 214
212 count, trailing = self.norm 215 count, trailing = self.norm
213 il = 0 216 il = 0
214 for i in range(tabsize, len(count)): 217 for i in range(tabsize, len(count)):
215 il = il + i/tabsize * count[i] 218 il = il + i / tabsize * count[i]
216 return trailing + tabsize * (il + self.nt) 219 return trailing + tabsize * (il + self.nt)
217 220
218 # return true iff self.indent_level(t) == other.indent_level(t) 221 # return true iff self.indent_level(t) == other.indent_level(t)
219 # for all t >= 1 222 # for all t >= 1
220 def equal(self, other): 223 def equal(self, other):
242 i1 == self.indent_level(ts) != other.indent_level(ts) == i2. 245 i1 == self.indent_level(ts) != other.indent_level(ts) == i2.
243 """ 246 """
244 n = max(self.longest_run_of_spaces(), 247 n = max(self.longest_run_of_spaces(),
245 other.longest_run_of_spaces()) + 1 248 other.longest_run_of_spaces()) + 1
246 a = [] 249 a = []
247 for ts in range(1, n+1): 250 for ts in range(1, n + 1):
248 if self.indent_level(ts) != other.indent_level(ts): 251 if self.indent_level(ts) != other.indent_level(ts):
249 a.append( (ts, 252 a.append((ts,
250 self.indent_level(ts), 253 self.indent_level(ts),
251 other.indent_level(ts)) ) 254 other.indent_level(ts)))
252 return a 255 return a
253 256
254 # Return True iff self.indent_level(t) < other.indent_level(t) 257 # Return True iff self.indent_level(t) < other.indent_level(t)
255 # for all t >= 1. 258 # for all t >= 1.
256 # The algorithm is due to Vincent Broman. 259 # The algorithm is due to Vincent Broman.
264 # M.num_tabs() <= N.num_tabs(). Proof is easy but kinda long-winded. 267 # M.num_tabs() <= N.num_tabs(). Proof is easy but kinda long-winded.
265 # XXXwrite that up. 268 # XXXwrite that up.
266 # Note that M is of the form (T*)(S*) iff len(M.norm[0]) <= 1. 269 # Note that M is of the form (T*)(S*) iff len(M.norm[0]) <= 1.
267 def less(self, other): 270 def less(self, other):
268 """ 271 """
269 Method to compare the indentation level against another Whitespace objects to 272 Method to compare the indentation level against another Whitespace objects to
270 be smaller. 273 be smaller.
271 274
272 @param other Whitespace object to compare against. 275 @param other Whitespace object to compare against.
273 @return True, if we compare less against the other Whitespace object. 276 @return True, if we compare less against the other Whitespace object.
274 """ 277 """
277 if self.is_simple and other.is_simple: 280 if self.is_simple and other.is_simple:
278 return self.nt <= other.nt 281 return self.nt <= other.nt
279 n = max(self.longest_run_of_spaces(), 282 n = max(self.longest_run_of_spaces(),
280 other.longest_run_of_spaces()) + 1 283 other.longest_run_of_spaces()) + 1
281 # the self.n >= other.n test already did it for ts=1 284 # the self.n >= other.n test already did it for ts=1
282 for ts in range(2, n+1): 285 for ts in range(2, n + 1):
283 if self.indent_level(ts) >= other.indent_level(ts): 286 if self.indent_level(ts) >= other.indent_level(ts):
284 return False 287 return False
285 return True 288 return True
286 289
287 # return a list of tuples (ts, i1, i2) such that 290 # return a list of tuples (ts, i1, i2) such that
300 i1 == self.indent_level(ts) >= other.indent_level(ts) == i2. 303 i1 == self.indent_level(ts) >= other.indent_level(ts) == i2.
301 """ 304 """
302 n = max(self.longest_run_of_spaces(), 305 n = max(self.longest_run_of_spaces(),
303 other.longest_run_of_spaces()) + 1 306 other.longest_run_of_spaces()) + 1
304 a = [] 307 a = []
305 for ts in range(1, n+1): 308 for ts in range(1, n + 1):
306 if self.indent_level(ts) >= other.indent_level(ts): 309 if self.indent_level(ts) >= other.indent_level(ts):
307 a.append( (ts, 310 a.append((ts,
308 self.indent_level(ts), 311 self.indent_level(ts),
309 other.indent_level(ts)) ) 312 other.indent_level(ts)))
310 return a 313 return a
314
311 315
312 def format_witnesses(w): 316 def format_witnesses(w):
313 """ 317 """
314 Function to format the witnesses as a readable string. 318 Function to format the witnesses as a readable string.
315 319
319 firsts = map(lambda tup: str(tup[0]), w) 323 firsts = map(lambda tup: str(tup[0]), w)
320 prefix = "at tab size" 324 prefix = "at tab size"
321 if len(w) > 1: 325 if len(w) > 1:
322 prefix = prefix + "s" 326 prefix = prefix + "s"
323 return prefix + " " + ', '.join(firsts) 327 return prefix + " " + ', '.join(firsts)
328
324 329
325 def process_tokens(tokens): 330 def process_tokens(tokens):
326 """ 331 """
327 Function processing all tokens generated by a tokenizer run. 332 Function processing all tokens generated by a tokenizer run.
328 333

eric ide

mercurial