source: trunk/essentials/dev-lang/python/Tools/scripts/reindent.py@ 3393

Last change on this file since 3393 was 3225, checked in by bird, 19 years ago

Python 2.5

File size: 9.7 KB
Line 
1#! /usr/bin/env python
2
3# Released to the public domain, by Tim Peters, 03 October 2000.
4
5"""reindent [-d][-r][-v] [ path ... ]
6
7-d (--dryrun) Dry run. Analyze, but don't make any changes to, files.
8-r (--recurse) Recurse. Search for all .py files in subdirectories too.
9-v (--verbose) Verbose. Print informative msgs; else no output.
10-h (--help) Help. Print this usage information and exit.
11
12Change Python (.py) files to use 4-space indents and no hard tab characters.
13Also trim excess spaces and tabs from ends of lines, and remove empty lines
14at the end of files. Also ensure the last line ends with a newline.
15
16If no paths are given on the command line, reindent operates as a filter,
17reading a single source file from standard input and writing the transformed
18source to standard output. In this case, the -d, -r and -v flags are
19ignored.
20
21You can pass one or more file and/or directory paths. When a directory
22path, all .py files within the directory will be examined, and, if the -r
23option is given, likewise recursively for subdirectories.
24
25If output is not to standard output, reindent overwrites files in place,
26renaming the originals with a .bak extension. If it finds nothing to
27change, the file is left alone. If reindent does change a file, the changed
28file is a fixed-point for future runs (i.e., running reindent on the
29resulting .py file won't change it again).
30
31The hard part of reindenting is figuring out what to do with comment
32lines. So long as the input files get a clean bill of health from
33tabnanny.py, reindent should do a good job.
34"""
35
36__version__ = "1"
37
38import tokenize
39import os
40import sys
41
42verbose = 0
43recurse = 0
44dryrun = 0
45
46def usage(msg=None):
47 if msg is not None:
48 print >> sys.stderr, msg
49 print >> sys.stderr, __doc__
50
51def errprint(*args):
52 sep = ""
53 for arg in args:
54 sys.stderr.write(sep + str(arg))
55 sep = " "
56 sys.stderr.write("\n")
57
58def main():
59 import getopt
60 global verbose, recurse, dryrun
61 try:
62 opts, args = getopt.getopt(sys.argv[1:], "drvh",
63 ["dryrun", "recurse", "verbose", "help"])
64 except getopt.error, msg:
65 usage(msg)
66 return
67 for o, a in opts:
68 if o in ('-d', '--dryrun'):
69 dryrun += 1
70 elif o in ('-r', '--recurse'):
71 recurse += 1
72 elif o in ('-v', '--verbose'):
73 verbose += 1
74 elif o in ('-h', '--help'):
75 usage()
76 return
77 if not args:
78 r = Reindenter(sys.stdin)
79 r.run()
80 r.write(sys.stdout)
81 return
82 for arg in args:
83 check(arg)
84
85def check(file):
86 if os.path.isdir(file) and not os.path.islink(file):
87 if verbose:
88 print "listing directory", file
89 names = os.listdir(file)
90 for name in names:
91 fullname = os.path.join(file, name)
92 if ((recurse and os.path.isdir(fullname) and
93 not os.path.islink(fullname))
94 or name.lower().endswith(".py")):
95 check(fullname)
96 return
97
98 if verbose:
99 print "checking", file, "...",
100 try:
101 f = open(file)
102 except IOError, msg:
103 errprint("%s: I/O Error: %s" % (file, str(msg)))
104 return
105
106 r = Reindenter(f)
107 f.close()
108 if r.run():
109 if verbose:
110 print "changed."
111 if dryrun:
112 print "But this is a dry run, so leaving it alone."
113 if not dryrun:
114 bak = file + ".bak"
115 if os.path.exists(bak):