1#!/usr/bin/env python 2 3"""List all those Python files that require a coding directive 4 5Usage: nocoding.py dir1 [dir2...] 6""" 7 8__author__ = "Oleg Broytmann, Georg Brandl" 9 10import sys, os, re, getopt 11 12# our pysource module finds Python source files 13try: 14 import pysource 15except ImportError: 16 # emulate the module with a simple os.walk 17 class pysource: 18 has_python_ext = looks_like_python = can_be_compiled = None 19 def walk_python_files(self, paths, *args, **kwargs): 20 for path in paths: 21 if os.path.isfile(path): 22 yield path.endswith(".py") 23 elif os.path.isdir(path): 24 for root, dirs, files in os.walk(path): 25 for filename in files: 26 if filename.endswith(".py"): 27 yield os.path.join(root, filename) 28 pysource = pysource() 29 30 31 print >>sys.stderr, ("The pysource module is not available; " 32 "no sophisticated Python source file search will be done.") 33 34 35decl_re = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)') 36blank_re = re.compile(r'^[ \t\f]*(?:[#\r\n]|$)') 37 38def get_declaration(line): 39 match = decl_re.match(line) 40 if match: 41 return match.group(1) 42 return b'' 43 44def has_correct_encoding(text, codec): 45 try: 46 unicode(text, codec) 47 except UnicodeDecodeError: 48 return False 49 else: 50 return True 51 52def needs_declaration(fullpath): 53 try: 54 infile = open(fullpath, 'rU') 55 except IOError: # Oops, the file was removed - ignore it 56 return None 57 58 line1 = infile.readline() 59 line2 = infile.readline() 60 61 if (get_declaration(line1) or 62 blank_re.match(line1) and get_declaration(line2)): 63 # the file does have an encoding declaration, so trust it 64 infile.close() 65 return False 66 67 # check the whole file for non-ASCII characters 68 rest = infile.read() 69 infile.close() 70 71 if has_correct_encoding(line1+line2+rest, "ascii"): 72 return False 73 74 return True 75 76 77usage = """Usage: %s [-cd] paths... 78 -c: recognize Python source files trying to compile them 79 -d: debug output""" % sys.argv[0] 80 81try: 82 opts, args = getopt.getopt(sys.argv[1:], 'cd') 83except getopt.error, msg: 84 print >>sys.stderr, msg 85 print >>sys.stderr, usage 86 sys.exit(1) 87 88is_python = pysource.looks_like_python 89debug = False 90 91for o, a in opts: 92 if o == '-c': 93 is_python = pysource.can_be_compiled 94 elif o == '-d': 95 debug = True 96 97if not args: 98 print >>sys.stderr, usage 99 sys.exit(1) 100 101for fullpath in pysource.walk_python_files(args, is_python): 102 if debug: 103 print "Testing for coding: %s" % fullpath 104 result = needs_declaration(fullpath) 105 if result: 106 print fullpath 107