import os
import sys
+
class Stats:
def __init__(self):
sys.stderr.write("Can't list %s: %s\n" % (dir, err))
self.addstats("<dir>", "unlistable", 1)
return
- names.sort()
- for name in names:
+ for name in sorted(names):
if name.startswith(".#"):
- continue # Skip CVS temp files
+ continue # Skip CVS temp files
if name.endswith("~"):
- continue# Skip Emacs backup files
+ continue # Skip Emacs backup files
full = os.path.join(dir, name)
if os.path.islink(full):
self.addstats("<lnk>", "links", 1)
head, ext = os.path.splitext(filename)
head, base = os.path.split(filename)
if ext == base:
- ext = "" # E.g. .cvsignore is deemed not to have an extension
+ ext = "" # E.g. .cvsignore is deemed not to have an extension
ext = os.path.normcase(ext)
if not ext:
ext = "<none>"
self.addstats(ext, "files", 1)
try:
- f = open(filename, "rb")
+ with open(filename, "rb") as f:
+ data = f.read()
except IOError as err:
sys.stderr.write("Can't open %s: %s\n" % (filename, err))
self.addstats(ext, "unopenable", 1)
return
- data = f.read()
- f.close()
self.addstats(ext, "bytes", len(data))
if b'\0' in data:
self.addstats(ext, "binary", 1)
return
if not data:
self.addstats(ext, "empty", 1)
- #self.addstats(ext, "chars", len(data))
+ # self.addstats(ext, "chars", len(data))
lines = str(data, "latin-1").splitlines()
self.addstats(ext, "lines", len(lines))
del lines
for ext in exts:
self.stats[ext]["ext"] = ext
cols.insert(0, "ext")
+
def printheader():
for col in cols:
print("%*s" % (colwidth[col], col), end=' ')
print()
+
printheader()
for ext in exts:
for col in cols:
value = self.stats[ext].get(col, "")
print("%*s" % (colwidth[col], value), end=' ')
print()
- printheader() # Another header at the bottom
+ printheader() # Another header at the bottom
+
def main():
args = sys.argv[1:]
s.statargs(args)
s.report()
+
if __name__ == "__main__":
main()
"""Return 'N file(s)' with the proper plurality on 'file'."""
return "{} file{}".format(count, "s" if count != 1 else "")
+
def status(message, modal=False, info=None):
"""Decorator to output status info to stdout."""
def decorated_fxn(fxn):
elif info:
print(info(result))
else:
- if result:
- print("yes")
- else:
- print("NO")
+ print("yes" if result else "NO")
return result
return call_fxn
return decorated_fxn
+
@status("Getting the list of files that have been added/changed",
info=lambda x: n_files_str(len(x)))
def changed_files():
"""Run ``svn status`` and return a set of files that have been
- changed/added."""
+ changed/added.
+ """
cmd = 'svn status --quiet --non-interactive --ignore-externals'
svn_st = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
svn_st.wait()
- output = [x.decode().rstrip() for x in svn_st.stdout.readlines()]
- files = set()
- for line in output:
- if not line[0] in ('A', 'M'):
- continue
- line_parts = line.split()
- path = line_parts[-1]
- if os.path.isfile(path):
- files.add(path)
- return files
+ output = (x.decode().rstrip().rsplit(None, 1)[-1]
+ for x in svn_st.stdout if x[0] in b'AM')
+ return set(path for path in output if os.path.isfile(path))
+
def report_modified_files(file_paths):
count = len(file_paths)
lines.append(" {}".format(path))
return "\n".join(lines)
+
@status("Fixing whitespace", info=report_modified_files)
def normalize_whitespace(file_paths):
"""Make sure that the whitespace for .py files have been normalized."""
fixed.append(path)
return fixed
+
@status("Docs modified", modal=True)
def docs_modified(file_paths):
"""Report if any file in the Doc directory has been changed."""
return bool(file_paths)
+
@status("Misc/ACKS updated", modal=True)
def credit_given(file_paths):
"""Check if Misc/ACKS has been changed."""
return 'Misc/ACKS' in file_paths
+
@status("Misc/NEWS updated", modal=True)
def reported_news(file_paths):
"""Check if Misc/NEWS has been changed."""
__version__ = "1"
import tokenize
-import os, shutil
+import os
+import shutil
import sys
-verbose = 0
-recurse = 0
-dryrun = 0
+verbose = False
+recurse = False
+dryrun = False
makebackup = True
+
def usage(msg=None):
- if msg is not None:
- print(msg, file=sys.stderr)
- print(__doc__, file=sys.stderr)
+ if msg is None:
+ msg = __doc__
+ print(msg, file=sys.stderr)
+
def errprint(*args):
- sep = ""
- for arg in args:
- sys.stderr.write(sep + str(arg))
- sep = " "
+ sys.stderr.write(" ".join(str(arg) for arg in args))
sys.stderr.write("\n")
+
def main():
import getopt
global verbose, recurse, dryrun, makebackup
return
for o, a in opts:
if o in ('-d', '--dryrun'):
- dryrun += 1
+ dryrun = True
elif o in ('-r', '--recurse'):
- recurse += 1
+ recurse = True
elif o in ('-n', '--nobackup'):
makebackup = False
elif o in ('-v', '--verbose'):
- verbose += 1
+ verbose = True
elif o in ('-h', '--help'):
usage()
return
for arg in args:
check(arg)
+
def check(file):
if os.path.isdir(file) and not os.path.islink(file):
if verbose:
if verbose:
print("checking", file, "...", end=' ')
try:
- f = open(file)
+ with open(file) as f:
+ r = Reindenter(f)
except IOError as msg:
errprint("%s: I/O Error: %s" % (file, str(msg)))
return
- r = Reindenter(f)
- f.close()
if r.run():
if verbose:
print("changed.")
shutil.copyfile(file, bak)
if verbose:
print("backed up", file, "to", bak)
- f = open(file, "w")
- r.write(f)
- f.close()
+ with open(file, "w") as f:
+ r.write(f)
if verbose:
print("wrote new", file)
return True
print("unchanged.")
return False
+
def _rstrip(line, JUNK='\n \t'):
"""Return line stripped of trailing spaces, tabs, newlines.
"""
i = len(line)
- while i > 0 and line[i-1] in JUNK:
+ while i > 0 and line[i - 1] in JUNK:
i -= 1
return line[:i]
+
class Reindenter:
def __init__(self, f):
# we see a line with *something* on it.
i = stats[0][0]
after.extend(lines[1:i])
- for i in range(len(stats)-1):
+ for i in range(len(stats) - 1):
thisstmt, thislevel = stats[i]
- nextstmt = stats[i+1][0]
+ nextstmt = stats[i + 1][0]
have = getlspace(lines[thisstmt])
want = thislevel * 4
if want < 0:
want = have2want.get(have, -1)
if want < 0:
# Then it probably belongs to the next real stmt.
- for j in range(i+1, len(stats)-1):
+ for j in range(i + 1, len(stats) - 1):
jline, jlevel = stats[j]
if jlevel >= 0:
if have == getlspace(lines[jline]):
# comment like this one,
# in which case we should shift it like its base
# line got shifted.
- for j in range(i-1, -1, -1):
+ for j in range(i - 1, -1, -1):
jline, jlevel = stats[j]
if jlevel >= 0:
- want = have + getlspace(after[jline-1]) - \
- getlspace(lines[jline])
+ want = have + (getlspace(after[jline - 1]) -
+ getlspace(lines[jline]))
break
if want < 0:
# Still no luck -- leave it alone.
if line: # not endmarker
self.stats.append((slinecol[0], self.level))
+
# Count number of leading blanks.
def getlspace(line):
i, n = 0, len(line)
i += 1
return i
+
if __name__ == '__main__':
main()
import re
import getopt
+
def main():
- bufsize = 64*1024
+ bufsize = 64 * 1024
reflags = 0
opts, args = getopt.getopt(sys.argv[1:], "i")
for o, a in opts:
try:
prog = re.compile(pattern, reflags)
except re.error as msg:
- usage("error in regular expression: %s" % str(msg))
+ usage("error in regular expression: %s" % msg)
try:
f = open(filename)
except IOError as msg:
- usage("can't open %s: %s" % (repr(filename), str(msg)), 1)
+ usage("can't open %r: %s" % (filename, msg), 1)
f.seek(0, 2)
pos = f.tell()
leftover = None
del lines[0]
else:
leftover = None
- lines.reverse()
- for line in lines:
+ for line in reversed(lines):
if prog.search(line):
print(line)
+
def usage(msg, code=2):
sys.stdout = sys.stderr
print(msg)
print(__doc__)
sys.exit(code)
+
if __name__ == '__main__':
main()
import sys
+
def main():
files = sys.argv[1:]
suffixes = {}
for filename in files:
suff = getsuffix(filename)
- if suff not in suffixes:
- suffixes[suff] = []
- suffixes[suff].append(filename)
- keys = sorted(suffixes.keys())
- for suff in keys:
- print(repr(suff), len(suffixes[suff]))
+ suffixes.setdefault(suff, []).append(filename)
+ for suff, filenames in sorted(suffixes.items()):
+ print(repr(suff), len(filenames))
+
def getsuffix(filename):
- suff = ''
- for i in range(len(filename)):
- if filename[i] == '.':
- suff = filename[i:]
- return suff
+ name, sep, suff = filename.rpartition('.')
+ return sep + suff if sep else ''
+
if __name__ == '__main__':
main()
import re
import os
+import sys
+import subprocess
+
def propfiles(root, fn):
- default = os.path.join(root, ".svn", "props", fn+".svn-work")
+ default = os.path.join(root, ".svn", "props", fn + ".svn-work")
try:
format = int(open(os.path.join(root, ".svn", "format")).read().strip())
except IOError:
if format in (8, 9):
# In version 8 and 9, committed props are stored in prop-base, local
# modifications in props
- return [os.path.join(root, ".svn", "prop-base", fn+".svn-base"),
- os.path.join(root, ".svn", "props", fn+".svn-work")]
- raise ValueError, "Unknown repository format"
+ return [os.path.join(root, ".svn", "prop-base", fn + ".svn-base"),
+ os.path.join(root, ".svn", "props", fn + ".svn-work")]
+ raise ValueError("Unknown repository format")
+
def proplist(root, fn):
- "Return a list of property names for file fn in directory root"
+ """Return a list of property names for file fn in directory root."""
result = []
for path in propfiles(root, fn):
try:
# no properties file: not under version control,
# or no properties set
continue
- while 1:
+ while True:
# key-value pairs, of the form
# K <length>
# <keyname>NL
f.close()
return result
+
+def set_eol_native(path):
+ cmd = 'svn propset svn:eol-style native "{}"'.format(path)
+ propset = subprocess.Popen(cmd, shell=True)
+ propset.wait()
+
+
possible_text_file = re.compile(r"\.([hc]|py|txt|sln|vcproj)$").search
-for root, dirs, files in os.walk('.'):
- if '.svn' in dirs:
- dirs.remove('.svn')
- for fn in files:
- if possible_text_file(fn):
+
+def main():
+ for arg in sys.argv[1:] or [os.curdir]:
+ if os.path.isfile(arg):
+ root, fn = os.path.split(arg)
if 'svn:eol-style' not in proplist(root, fn):
- path = os.path.join(root, fn)
- os.system('svn propset svn:eol-style native "%s"' % path)
+ set_eol_native(arg)
+ elif os.path.isdir(arg):
+ for root, dirs, files in os.walk(arg):
+ if '.svn' in dirs:
+ dirs.remove('.svn')
+ for fn in files:
+ if possible_text_file(fn):
+ if 'svn:eol-style' not in proplist(root, fn):
+ path = os.path.join(root, fn)
+ set_eol_native(path)
+
+
+if __name__ == '__main__':
+ main()
import sys
import getopt
+
def main():
tabsize = 8
try:
for filename in args:
process(filename, tabsize)
+
def process(filename, tabsize):
try:
- f = open(filename)
- text = f.read()
- f.close()
+ with open(filename) as f:
+ text = f.read()
except IOError as msg:
print("%r: I/O error: %s" % (filename, msg))
return
os.rename(filename, backup)
except os.error:
pass
- f = open(filename, "w")
- f.write(newtext)
- f.close()
+ with open(filename, "w") as f:
+ f.write(newtext)
print(filename)
+
if __name__ == '__main__':
main()