Removing unstylish spaces
Alex
cut_me_out at hotmail.com
Sat Jul 8 21:13:02 EDT 2000
Reading Code Complete and The Pragmatic Programmer at the same time can
make you do some silly things. I learned recently that it's not stylish
to have a space between a function name and the opening parethesis of
its argument list, so I kludged something together to remove most of
them from my code. I thought I would make it available here, in case
anyone else is so frivolously minded. :)
Alex.
#!/usr/bin/env python
'''Finds all *.py files beneath the cwd, looks in them for opening
parentheses preceded by a space, and removes the space if it thinks
it\'s part of a function call.
If you use it without backing your files up, you\'re an idiot. That
said, it\'s pretty paranoid about trying not to stuff files up, and
will save a copy of file.py in file.py.bak, if it decides to modify
it.
You can do as you wish with this code, even attribute it to yourself,
if you\'re in a plagiaristic mood.'''
import os, string, re, shutil, sys
class File_getter:
def __init__ (self, paths):
self.filenames = []
for path in paths:
os.path.walk (os.path.expanduser (path), self.callback, None)
def callback (self, dummy, directory, filenames):
filenames = filter (re.compile ('\.py$').search, filenames)
filenames = map (os.path.join, len (filenames) * [directory],
filenames)
self.filenames.extend (filenames)
want_to_keep_the_space_p = re.compile (
'(([^%s](' % (string.letters + '_') + \
string.join (['if', 'and', 'or', 'else', 'assert',
'while', 'return', 'exec', 'del', 'for',
'not', 'raise', 'in', 'is',
'[-^<>=+*%~:]'],
'|') + \
'))|[-^<>=+*%~:]|\d)$').search
assert want_to_keep_the_space_p (')and')
assert want_to_keep_the_space_p ('5 %')
assert not want_to_keep_the_space_p ('"%s" % str(4)')
def clean_brackets(filename):
'''Find brackets proceeded by spaces in the python file filename,
and remove the spaces unless they are proceeded by a keyword or symbol.
'''
file = open(filename).read()
file_copied_p = None
# ...first, get rid of confusing carriage returns
file = string.replace (file, '\r\n', '\n')
# Check that we don't get any false positives from an existing
# syntax error.
try:
compile(file, 'test', 'exec')
except SyntaxError: # Ignore file if we do.
return None
start = 0
while 1:
candidate = string.find(file, ' (', start)
if candidate == -1: # No more found
break
# This could skip ahead two, if a space is removed.
start = candidate + 1
# Check that the bracket is in a coding region of the file
# by seeing if removing it induces a syntax error.
assert file[candidate: candidate + 2] == ' ('
mutated_file = file[:candidate] + file[candidate + 2:]
try:
compile(mutated_file, 'test', 'exec')
except SyntaxError:
# This is part of a coding region of the file, amend it.
# in the rest of the loop.
pass
else:
# Removal had no effect on syntactical correctness of the
# file, it must be irrelevant.
continue
# If this is the first amendment to the file, take a copy of
# it, in case this screws up.
if not file_copied_p:
shutil.copyfile(filename, filename + '.bak')
file_copied_p = 1
# Get the word/symbol prior to the bracket.
# ...get the start of the current line
line_start = string.rfind (file, '\n', 0, candidate)
if line_start == -1: # No prior newline, must be on first line.
line_start = 0
else: # Jump past the newline.
line_start = line_start + 1
# ...get the word
words = string.split (file[line_start: candidate])
if len (words) == 0: # Just whitespace prior to the bracket, ignore.
continue
prior_word = words[-1]
if not want_to_keep_the_space_p (prior_word):
assert file[candidate] == ' '
file = file[:candidate] + file[candidate + 1:]
if file_copied_p: # Must have been modified, too. Save it.
try:
compile(file, 'test', 'exec')
except SyntaxError:
raise 'Stuffed up the syntax of ' + filename
else:
open(filename, 'w').write(file)
if __name__ == '__main__':
agreement = 'Yes_I_want_to_run_this_poorly_understood_code_' \
'over_all_python_files_below_my_cwd.'
if (len(sys.argv) != 2) or (sys.argv[1] != agreement):
print 'Usage:'
print sys.argv[0], agreement
sys.exit (1)
for filename in File_getter([os.getcwd ()]).filenames:
print filename
clean_brackets(filename)
More information about the Python-list
mailing list