Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f4b44fa

Browse files
committed
Tim's latest version (supports old and new tokenize modules)
1 parent 5d97ebf commit f4b44fa

3 files changed

Lines changed: 384 additions & 231 deletions

File tree

Lib/tabnanny.py

Lines changed: 128 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,16 @@
1-
#! /home/guido/python/src/sparc/python
21
#! /usr/bin/env python
32

4-
"""The Tab Nanny despises ambiguous indentation. She knows no mercy.
3+
"""The Tab Nanny despises ambiguous indentation. She knows no mercy."""
54

6-
CAUTION: this version requires Guido's "NL" patch to lib/tokenize.py,
7-
posted 30-Mar-98. This version will not run at all with an unpatched
8-
tokenize (it will raise AttributeError while loading), while previous
9-
versions will run incorrectly with the patched tokenize.
10-
"""
5+
# Released to the public domain, by Tim Peters, 4 April 1998.
116

12-
# Released to the public domain, by Tim Peters, 30 March 1998.
13-
14-
__version__ = "2"
7+
__version__ = "3"
158

169
import os
1710
import sys
1811
import getopt
1912
import tokenize
2013

21-
try:
22-
tokenize.NL
23-
except AttributeError:
24-
raise AttributeError, "Sorry, I need a version of tokenize.py " \
25-
"that supports the NL pseudo-token."
26-
2714
verbose = 0
2815

2916
def main():
@@ -235,67 +222,131 @@ def format_witnesses(w):
235222
prefix = prefix + "s"
236223
return prefix + " " + string.join(firsts, ', ')
237224

238-
indents = []
239-
check_equal = 0
240-
241-
def reset_globals():
242-
global indents, check_equal
243-
check_equal = 0
244-
indents = [Whitespace("")]
245-
246-
def tokeneater(type, token, start, end, line,
247-
INDENT=tokenize.INDENT,
248-
DEDENT=tokenize.DEDENT,
249-
NEWLINE=tokenize.NEWLINE,
250-
COMMENT=tokenize.COMMENT,
251-
NL=tokenize.NL):
252-
global indents, check_equal
253-
254-
# test in decreasing order of frequency, although the check_equal
255-
# test *must* be last; INDENT and DEDENT appear equally often
256-
257-
if type in (COMMENT, NL):
258-
# the indentation of these guys is meaningless
259-
pass
260-
261-
elif type == NEWLINE:
262-
# a program statement, or ENDMARKER, will eventually follow,
263-
# after some (possibly empty) run of tokens of the form
264-
# (NL | COMMENT)* (INDENT | DEDENT+)?
265-
# If an INDENT appears, setting check_equal is wrong, and will
266-
# be undone when we see the INDENT.
267-
check_equal = 1
268-
269-
elif type == INDENT:
270-
check_equal = 0
271-
thisguy = Whitespace(token)
272-
if not indents[-1].less(thisguy):
273-
witness = indents[-1].not_less_witness(thisguy)
274-
msg = "indent not greater e.g. " + format_witnesses(witness)
275-
raise NannyNag(start[0], msg, line)
276-
indents.append(thisguy)
277-
278-
elif type == DEDENT:
279-
# there's nothing we need to check here! what's important is
280-
# that when the run of DEDENTs ends, the indentation of the
281-
# program statement (or ENDMARKER) that triggered the run is
282-
# equal to what's left at the top of the indents stack
283-
assert check_equal # else no earlier NEWLINE, or an earlier INDENT
284-
del indents[-1]
285-
286-
elif check_equal:
287-
# this is the first "real token" following a NEWLINE, so it
288-
# must be the first token of the next program statment, or an
289-
# ENDMARKER; the "line" argument exposes the leading whitespace
290-
# for this statement; in the case of ENDMARKER, line is an empty
291-
# string, so will properly match the empty string with which the
292-
# "indents" stack was seeded
293-
check_equal = 0
294-
thisguy = Whitespace(line)
295-
if not indents[-1].equal(thisguy):
296-
witness = indents[-1].not_equal_witness(thisguy)
297-
msg = "indent not equal e.g. " + format_witnesses(witness)
298-
raise NannyNag(start[0], msg, line)
225+
# The collection of globals, the reset_globals() function, and the
226+
# tokeneater() function, depend on which version of tokenize is
227+
# in use.
228+
229+
if hasattr(tokenize, 'NL'):
230+
# take advantage of Guido's patch!
231+
232+
indents = []
233+
check_equal = 0
234+
235+
def reset_globals():
236+
global indents, check_equal
237+
check_equal = 0
238+
indents = [Whitespace("")]
239+
240+
def tokeneater(type, token, start, end, line,
241+
INDENT=tokenize.INDENT,
242+
DEDENT=tokenize.DEDENT,
243+
NEWLINE=tokenize.NEWLINE,
244+
COMMENT=tokenize.COMMENT,
245+
NL=tokenize.NL):
246+
global indents, check_equal
247+
248+
# test in decreasing order of frequency, although the check_equal
249+
# test *must* be last; INDENT and DEDENT appear equally often
250+
251+
if type in (COMMENT, NL):
252+
# the indentation of these guys is meaningless
253+
pass
254+
255+
elif type == NEWLINE:
256+
# a program statement, or ENDMARKER, will eventually follow,
257+
# after some (possibly empty) run of tokens of the form
258+
# (NL | COMMENT)* (INDENT | DEDENT+)?
259+
# If an INDENT appears, setting check_equal is wrong, and will
260+
# be undone when we see the INDENT.
261+
check_equal = 1
262+
263+
elif type == INDENT:
264+
check_equal = 0
265+
thisguy = Whitespace(token)
266+
if not indents[-1].less(thisguy):
267+
witness = indents[-1].not_less_witness(thisguy)
268+
msg = "indent not greater e.g. " + format_witnesses(witness)
269+
raise NannyNag(start[0], msg, line)
270+
indents.append(thisguy)
271+
272+
elif type == DEDENT:
273+
# there's nothing we need to check here! what's important is
274+
# that when the run of DEDENTs ends, the indentation of the
275+
# program statement (or ENDMARKER) that triggered the run is
276+
# equal to what's left at the top of the indents stack
277+
assert check_equal # else no earlier NEWLINE, or an earlier INDENT
278+
del indents[-1]
279+
280+
elif check_equal:
281+
# this is the first "real token" following a NEWLINE, so it
282+
# must be the first token of the next program statement, or an
283+
# ENDMARKER; the "line" argument exposes the leading whitespace
284+
# for this statement; in the case of ENDMARKER, line is an empty
285+
# string, so will properly match the empty string with which the
286+
# "indents" stack was seeded
287+
check_equal = 0
288+
thisguy = Whitespace(line)
289+
if not indents[-1].equal(thisguy):
290+
witness = indents[-1].not_equal_witness(thisguy)
291+
msg = "indent not equal e.g. " + format_witnesses(witness)
292+
raise NannyNag(start[0], msg, line)
293+
294+
else:
295+
# unpatched version of tokenize
296+
297+
nesting_level = 0
298+
indents = []
299+
check_equal = 0
300+
301+
def reset_globals():
302+
global nesting_level, indents, check_equal
303+
nesting_level = check_equal = 0
304+
indents = [Whitespace("")]
305+
306+
def tokeneater(type, token, start, end, line,
307+
INDENT=tokenize.INDENT,
308+
DEDENT=tokenize.DEDENT,
309+
NEWLINE=tokenize.NEWLINE,
310+
COMMENT=tokenize.COMMENT,
311+
OP=tokenize.OP):
312+
global nesting_level, indents, check_equal
313+
314+
if type == INDENT:
315+
check_equal = 0
316+
thisguy = Whitespace(token)
317+
if not indents[-1].less(thisguy):
318+
witness = indents[-1].not_less_witness(thisguy)
319+
msg = "indent not greater e.g. " + format_witnesses(witness)
320+
raise NannyNag(start[0], msg, line)
321+
indents.append(thisguy)
322+
323+
elif type == DEDENT:
324+
del indents[-1]
325+
326+
elif type == NEWLINE:
327+
if nesting_level == 0:
328+
check_equal = 1
329+
330+
elif type == COMMENT:
331+
pass
332+
333+
elif check_equal:
334+
check_equal = 0
335+
thisguy = Whitespace(line)
336+
if not indents[-1].equal(thisguy):
337+
witness = indents[-1].not_equal_witness(thisguy)
338+
msg = "indent not equal e.g. " + format_witnesses(witness)
339+
raise NannyNag(start[0], msg, line)
340+
341+
if type == OP and token in ('{', '[', '('):
342+
nesting_level = nesting_level + 1
343+
344+
elif type == OP and token in ('}', ']', ')'):
345+
if nesting_level == 0:
346+
raise NannyNag(start[0],
347+
"unbalanced bracket '" + token + "'",
348+
line)
349+
nesting_level = nesting_level - 1
299350

300351
if __name__ == '__main__':
301352
main()

0 commit comments

Comments
 (0)