#!/usr/bin/env python | |
"""List all those Python files that require a coding directive | |
Usage: nocoding.py dir1 [dir2...] | |
""" | |
__author__ = "Oleg Broytmann, Georg Brandl" | |
import sys, os, re, getopt | |
# our pysource module finds Python source files | |
try: | |
import pysource | |
except ImportError: | |
# emulate the module with a simple os.walk | |
class pysource: | |
has_python_ext = looks_like_python = can_be_compiled = None | |
def walk_python_files(self, paths, *args, **kwargs): | |
for path in paths: | |
if os.path.isfile(path): | |
yield path.endswith(".py") | |
elif os.path.isdir(path): | |
for root, dirs, files in os.walk(path): | |
for filename in files: | |
if filename.endswith(".py"): | |
yield os.path.join(root, filename) | |
pysource = pysource() | |
print >>sys.stderr, ("The pysource module is not available; " | |
"no sophisticated Python source file search will be done.") | |
decl_re = re.compile(r"coding[=:]\s*([-\w.]+)") | |
def get_declaration(line): | |
match = decl_re.search(line) | |
if match: | |
return match.group(1) | |
return '' | |
def has_correct_encoding(text, codec): | |
try: | |
unicode(text, codec) | |
except UnicodeDecodeError: | |
return False | |
else: | |
return True | |
def needs_declaration(fullpath): | |
try: | |
infile = open(fullpath, 'rU') | |
except IOError: # Oops, the file was removed - ignore it | |
return None | |
line1 = infile.readline() | |
line2 = infile.readline() | |
if get_declaration(line1) or get_declaration(line2): | |
# the file does have an encoding declaration, so trust it | |
infile.close() | |
return False | |
# check the whole file for non-ASCII characters | |
rest = infile.read() | |
infile.close() | |
if has_correct_encoding(line1+line2+rest, "ascii"): | |
return False | |
return True | |
usage = """Usage: %s [-cd] paths... | |
-c: recognize Python source files trying to compile them | |
-d: debug output""" % sys.argv[0] | |
try: | |
opts, args = getopt.getopt(sys.argv[1:], 'cd') | |
except getopt.error, msg: | |
print >>sys.stderr, msg | |
print >>sys.stderr, usage | |
sys.exit(1) | |
is_python = pysource.looks_like_python | |
debug = False | |
for o, a in opts: | |
if o == '-c': | |
is_python = pysource.can_be_compiled | |
elif o == '-d': | |
debug = True | |
if not args: | |
print >>sys.stderr, usage | |
sys.exit(1) | |
for fullpath in pysource.walk_python_files(args, is_python): | |
if debug: | |
print "Testing for coding: %s" % fullpath | |
result = needs_declaration(fullpath) | |
if result: | |
print fullpath |