| #!/usr/bin/env python3 |
| |
| """List all those Python files that require a coding directive |
| |
| Usage: findnocoding.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("The pysource module is not available; " |
| "no sophisticated Python source file search will be done.", file=sys.stderr) |
| |
| |
| decl_re = re.compile(rb'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)') |
| blank_re = re.compile(rb'^[ \t\f]*(?:[#\r\n]|$)') |
| |
| def get_declaration(line): |
| match = decl_re.match(line) |
| if match: |
| return match.group(1) |
| return b'' |
| |
| def has_correct_encoding(text, codec): |
| try: |
| str(text, codec) |
| except UnicodeDecodeError: |
| return False |
| else: |
| return True |
| |
| def needs_declaration(fullpath): |
| try: |
| infile = open(fullpath, 'rb') |
| except IOError: # Oops, the file was removed - ignore it |
| return None |
| |
| with infile: |
| line1 = infile.readline() |
| line2 = infile.readline() |
| |
| if (get_declaration(line1) or |
| blank_re.match(line1) and get_declaration(line2)): |
| # the file does have an encoding declaration, so trust it |
| return False |
| |
| # check the whole file for non utf-8 characters |
| rest = infile.read() |
| |
| if has_correct_encoding(line1+line2+rest, "utf-8"): |
| return False |
| |
| return True |
| |
| |
| usage = """Usage: %s [-cd] paths... |
| -c: recognize Python source files trying to compile them |
| -d: debug output""" % sys.argv[0] |
| |
| if __name__ == '__main__': |
| |
| try: |
| opts, args = getopt.getopt(sys.argv[1:], 'cd') |
| except getopt.error as msg: |
| print(msg, file=sys.stderr) |
| print(usage, file=sys.stderr) |
| 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(usage, file=sys.stderr) |
| 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) |