12532f11321808b8af8c54d6a7171373b64a67748Éric Araujo"""Module/script to byte-compile all .py files to .pyc (or .pyo) files. 2c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum 3c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van RossumWhen called as a script with arguments, this compiles the directories 4c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossumgiven as arguments recursively; the -l option prevents it from 5c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossumrecursing into directories. 6c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum 7c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van RossumWithout arguments, if compiles all modules on sys.path, without 8c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossumrecursing into subdirectories. (Even though it should do so for 9c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossumpackages -- for now, you'll have to deal with packages separately.) 10c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum 11c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van RossumSee module py_compile for details of the actual byte-compilation. 12c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum""" 133bb54487675cd28166fc7271b5788b185bcc1b63Guido van Rossumimport os 143bb54487675cd28166fc7271b5788b185bcc1b63Guido van Rossumimport sys 153bb54487675cd28166fc7271b5788b185bcc1b63Guido van Rossumimport py_compile 1628d108893c5a6663c1747b1c79d0432ba7794e63Brett Cannonimport struct 1728d108893c5a6663c1747b1c79d0432ba7794e63Brett Cannonimport imp 183bb54487675cd28166fc7271b5788b185bcc1b63Guido van Rossum 19fae23dc9dc1b4e1b3138b1c933306869440408f2Matthias Klose__all__ = ["compile_dir","compile_file","compile_path"] 20e99d5ea25ba994491c773d9b5872332334ccd1c5Skip Montanaro 215c137c225113764faae183034e7a85175a699ae2Martin v. Löwisdef compile_dir(dir, maxlevels=10, ddir=None, 225c137c225113764faae183034e7a85175a699ae2Martin v. Löwis force=0, rx=None, quiet=0): 23c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum """Byte-compile all modules in the given directory tree. 24c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum 25c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum Arguments (only dir is required): 26c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum 27c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum dir: the directory to byte-compile 28c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum maxlevels: maximum recursion level (default 10) 292532f11321808b8af8c54d6a7171373b64a67748Éric Araujo ddir: the directory that will be prepended to the path to the 302532f11321808b8af8c54d6a7171373b64a67748Éric Araujo file as it is compiled into each byte-code file. 310b56a3e9a78f3e49a6c4c17842e18c59bcf75cb4Guido van Rossum force: if 1, force compilation, even if timestamps are up-to-date 325c137c225113764faae183034e7a85175a699ae2Martin v. Löwis quiet: if 1, be quiet during compilation 33c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum """ 345c137c225113764faae183034e7a85175a699ae2Martin v. Löwis if not quiet: 355c137c225113764faae183034e7a85175a699ae2Martin v. Löwis print 'Listing', dir, '...' 36c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum try: 3745e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum names = os.listdir(dir) 38c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum except os.error: 3945e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum print "Can't list", dir 4045e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum names = [] 41c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum names.sort() 429065ea36deb5812654c1959413a92cfb18ad3b5aFred Drake success = 1 43c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum for name in names: 4445e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum fullname = os.path.join(dir, name) 458989ea6ce1619890adc58778fb5516a36053cadbRaymond Hettinger if ddir is not None: 4645e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum dfile = os.path.join(ddir, name) 4745e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum else: 4845e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum dfile = None 49b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if not os.path.isdir(fullname): 50b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if not compile_file(fullname, ddir, force, rx, quiet): 51b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose success = 0 5245e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum elif maxlevels > 0 and \ 5345e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum name != os.curdir and name != os.pardir and \ 5445e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum os.path.isdir(fullname) and \ 5545e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum not os.path.islink(fullname): 5628d108893c5a6663c1747b1c79d0432ba7794e63Brett Cannon if not compile_dir(fullname, maxlevels - 1, dfile, force, rx, 5728d108893c5a6663c1747b1c79d0432ba7794e63Brett Cannon quiet): 5812b6457e24924ff60cf89fd19a584185a5d6c256Jeremy Hylton success = 0 599065ea36deb5812654c1959413a92cfb18ad3b5aFred Drake return success 60c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum 61b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klosedef compile_file(fullname, ddir=None, force=0, rx=None, quiet=0): 62c11ba768da100a7d7eb64cf457910a7f1655d559Éric Araujo """Byte-compile one file. 63c11ba768da100a7d7eb64cf457910a7f1655d559Éric Araujo 64c11ba768da100a7d7eb64cf457910a7f1655d559Éric Araujo Arguments (only fullname is required): 65c11ba768da100a7d7eb64cf457910a7f1655d559Éric Araujo 66c11ba768da100a7d7eb64cf457910a7f1655d559Éric Araujo fullname: the file to byte-compile 672532f11321808b8af8c54d6a7171373b64a67748Éric Araujo ddir: if given, the directory name compiled in to the 682532f11321808b8af8c54d6a7171373b64a67748Éric Araujo byte-code file. 69b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose force: if 1, force compilation, even if timestamps are up-to-date 70b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose quiet: if 1, be quiet during compilation 71b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose """ 72b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose success = 1 73b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose name = os.path.basename(fullname) 74b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if ddir is not None: 75b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose dfile = os.path.join(ddir, name) 76b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose else: 77b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose dfile = None 78b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if rx is not None: 79b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose mo = rx.search(fullname) 80b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if mo: 81b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose return success 82b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if os.path.isfile(fullname): 83b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose head, tail = name[:-3], name[-3:] 84b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if tail == '.py': 85b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if not force: 86b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose try: 87b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose mtime = int(os.stat(fullname).st_mtime) 88b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose expect = struct.pack('<4sl', imp.get_magic(), mtime) 89b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose cfile = fullname + (__debug__ and 'c' or 'o') 90b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose with open(cfile, 'rb') as chandle: 91b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose actual = chandle.read(8) 92b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if expect == actual: 93b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose return success 94b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose except IOError: 95b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose pass 96b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if not quiet: 97b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose print 'Compiling', fullname, '...' 98b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose try: 99b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose ok = py_compile.compile(fullname, None, dfile, True) 100b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose except py_compile.PyCompileError,err: 101b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if quiet: 102b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose print 'Compiling', fullname, '...' 103b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose print err.msg 104b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose success = 0 105b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose except IOError, e: 106b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose print "Sorry", e 107b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose success = 0 108b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose else: 109b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if ok == 0: 110b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose success = 0 111b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose return success 112b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose 1135c137c225113764faae183034e7a85175a699ae2Martin v. Löwisdef compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0): 114c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum """Byte-compile all module on sys.path. 115c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum 116c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum Arguments (all optional): 117c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum 118c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum skip_curdir: if true, skip current directory (default true) 119c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum maxlevels: max recursion level (default 0) 1200b56a3e9a78f3e49a6c4c17842e18c59bcf75cb4Guido van Rossum force: as for compile_dir() (default 0) 1215c137c225113764faae183034e7a85175a699ae2Martin v. Löwis quiet: as for compile_dir() (default 0) 122c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum """ 1239065ea36deb5812654c1959413a92cfb18ad3b5aFred Drake success = 1 124c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum for dir in sys.path: 12545e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum if (not dir or dir == os.curdir) and skip_curdir: 12645e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum print 'Skipping current directory' 12745e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum else: 1285c137c225113764faae183034e7a85175a699ae2Martin v. Löwis success = success and compile_dir(dir, maxlevels, None, 1295c137c225113764faae183034e7a85175a699ae2Martin v. Löwis force, quiet=quiet) 1309065ea36deb5812654c1959413a92cfb18ad3b5aFred Drake return success 1313bb54487675cd28166fc7271b5788b185bcc1b63Guido van Rossum 132b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klosedef expand_args(args, flist): 133b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose """read names in flist and append to args""" 134b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose expanded = args[:] 135b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if flist: 136b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose try: 137b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if flist == '-': 138b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose fd = sys.stdin 139b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose else: 140b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose fd = open(flist) 141b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose while 1: 142b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose line = fd.readline() 143b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if not line: 144b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose break 145b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose expanded.append(line[:-1]) 146b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose except IOError: 147b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose print "Error reading file list %s" % flist 148b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose raise 149b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose return expanded 150b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose 1513bb54487675cd28166fc7271b5788b185bcc1b63Guido van Rossumdef main(): 152c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum """Script main program.""" 153c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum import getopt 154c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum try: 155b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:i:') 156c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum except getopt.error, msg: 15745e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum print msg 1585c137c225113764faae183034e7a85175a699ae2Martin v. Löwis print "usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \ 159b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose "[-x regexp] [-i list] [directory|file ...]" 1602532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print 1612532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print "arguments: zero or more file and directory names to compile; " \ 1622532f11321808b8af8c54d6a7171373b64a67748Éric Araujo "if no arguments given, " 1632532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print " defaults to the equivalent of -l sys.path" 1642532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print 1652532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print "options:" 1662532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print "-l: don't recurse into subdirectories" 1670b56a3e9a78f3e49a6c4c17842e18c59bcf75cb4Guido van Rossum print "-f: force rebuild even if timestamps are up-to-date" 1682532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print "-q: output only error messages" 1692532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print "-d destdir: directory to prepend to file paths for use in " \ 1702532f11321808b8af8c54d6a7171373b64a67748Éric Araujo "compile-time tracebacks and in" 1712532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print " runtime tracebacks in cases where the source " \ 1722532f11321808b8af8c54d6a7171373b64a67748Éric Araujo "file is unavailable" 1732532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print "-x regexp: skip files matching the regular expression regexp; " \ 1742532f11321808b8af8c54d6a7171373b64a67748Éric Araujo "the regexp is searched for" 1752532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print " in the full path of each file considered for " \ 1762532f11321808b8af8c54d6a7171373b64a67748Éric Araujo "compilation" 1772532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print "-i file: add all the files and directories listed in file to " \ 1782532f11321808b8af8c54d6a7171373b64a67748Éric Araujo "the list considered for" 1792532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print ' compilation; if "-", names are read from stdin' 1802532f11321808b8af8c54d6a7171373b64a67748Éric Araujo 18145e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum sys.exit(2) 182c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum maxlevels = 10 183c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum ddir = None 1840b56a3e9a78f3e49a6c4c17842e18c59bcf75cb4Guido van Rossum force = 0 1855c137c225113764faae183034e7a85175a699ae2Martin v. Löwis quiet = 0 18612b6457e24924ff60cf89fd19a584185a5d6c256Jeremy Hylton rx = None 187b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose flist = None 188c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum for o, a in opts: 18945e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum if o == '-l': maxlevels = 0 19045e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum if o == '-d': ddir = a 1910b56a3e9a78f3e49a6c4c17842e18c59bcf75cb4Guido van Rossum if o == '-f': force = 1 1925c137c225113764faae183034e7a85175a699ae2Martin v. Löwis if o == '-q': quiet = 1 19312b6457e24924ff60cf89fd19a584185a5d6c256Jeremy Hylton if o == '-x': 19412b6457e24924ff60cf89fd19a584185a5d6c256Jeremy Hylton import re 19512b6457e24924ff60cf89fd19a584185a5d6c256Jeremy Hylton rx = re.compile(a) 196b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if o == '-i': flist = a 197c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum if ddir: 198b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if len(args) != 1 and not os.path.isdir(args[0]): 19945e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum print "-d destdir require exactly one directory argument" 20045e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum sys.exit(2) 2019065ea36deb5812654c1959413a92cfb18ad3b5aFred Drake success = 1 202c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum try: 203b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if args or flist: 204b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose try: 205b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if flist: 206b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose args = expand_args(args, flist) 207b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose except IOError: 208b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose success = 0 209b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if success: 210b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose for arg in args: 211b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if os.path.isdir(arg): 212b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if not compile_dir(arg, maxlevels, ddir, 213b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose force, rx, quiet): 214b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose success = 0 215b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose else: 216b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose if not compile_file(arg, ddir, force, rx, quiet): 217b13d04c99143ea326d1c74ba537ff43cbd04175bMatthias Klose success = 0 21845e2fbc2e70ef28b1f0327207f33dab3a4e825c5Guido van Rossum else: 2199065ea36deb5812654c1959413a92cfb18ad3b5aFred Drake success = compile_path() 220c567b8176a51a9ebd8bdeaa4d8f0771cf05f7c7aGuido van Rossum except KeyboardInterrupt: 2212532f11321808b8af8c54d6a7171373b64a67748Éric Araujo print "\n[interrupted]" 2229065ea36deb5812654c1959413a92cfb18ad3b5aFred Drake success = 0 2239065ea36deb5812654c1959413a92cfb18ad3b5aFred Drake return success 2243bb54487675cd28166fc7271b5788b185bcc1b63Guido van Rossum 2253bb54487675cd28166fc7271b5788b185bcc1b63Guido van Rossumif __name__ == '__main__': 2267b4b788eaadb36f65b08a4a84e7096bb03dcc12bRaymond Hettinger exit_status = int(not main()) 22712b6457e24924ff60cf89fd19a584185a5d6c256Jeremy Hylton sys.exit(exit_status) 228