1 #!/usr/bin/env python 2 3 """List all those Python files that require a coding directive 4 5 Usage: nocoding.py dir1 [dir2...] 6 """ 7 8 __author__ = "Oleg Broytmann, Georg Brandl" 9 10 import sys, os, re, getopt 11 12 # our pysource module finds Python source files 13 try: 14 import pysource 15 except 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 35 decl_re = re.compile(r"coding[=:]\s*([-\w.]+)") 36 37 def get_declaration(line): 38 match = decl_re.search(line) 39 if match: 40 return match.group(1) 41 return '' 42 43 def has_correct_encoding(text, codec): 44 try: 45 unicode(text, codec) 46 except UnicodeDecodeError: 47 return False 48 else: 49 return True 50 51 def needs_declaration(fullpath): 52 try: 53 infile = open(fullpath, 'rU') 54 except IOError: # Oops, the file was removed - ignore it 55 return None 56 57 line1 = infile.readline() 58 line2 = infile.readline() 59 60 if get_declaration(line1) or get_declaration(line2): 61 # the file does have an encoding declaration, so trust it 62 infile.close() 63 return False 64 65 # check the whole file for non-ASCII characters 66 rest = infile.read() 67 infile.close() 68 69 if has_correct_encoding(line1+line2+rest, "ascii"): 70 return False 71 72 return True 73 74 75 usage = """Usage: %s [-cd] paths... 76 -c: recognize Python source files trying to compile them 77 -d: debug output""" % sys.argv[0] 78 79 try: 80 opts, args = getopt.getopt(sys.argv[1:], 'cd') 81 except getopt.error, msg: 82 print >>sys.stderr, msg 83 print >>sys.stderr, usage 84 sys.exit(1) 85 86 is_python = pysource.looks_like_python 87 debug = False 88 89 for o, a in opts: 90 if o == '-c': 91 is_python = pysource.can_be_compiled 92 elif o == '-d': 93 debug = True 94 95 if not args: 96 print >>sys.stderr, usage 97 sys.exit(1) 98 99 for fullpath in pysource.walk_python_files(args, is_python): 100 if debug: 101 print "Testing for coding: %s" % fullpath 102 result = needs_declaration(fullpath) 103 if result: 104 print fullpath 105