1212
1313"""
1414import os
15+ import errno
1516import sys
1617import py_compile
1718import struct
2021__all__ = ["compile_dir" ,"compile_file" ,"compile_path" ]
2122
2223def compile_dir (dir , maxlevels = 10 , ddir = None ,
23- force = 0 , rx = None , quiet = 0 ):
24+ force = False , rx = None , quiet = False , legacy = False ):
2425 """Byte-compile all modules in the given directory tree.
2526
2627 Arguments (only dir is required):
@@ -29,8 +30,9 @@ def compile_dir(dir, maxlevels=10, ddir=None,
2930 maxlevels: maximum recursion level (default 10)
3031 ddir: if given, purported directory name (this is the
3132 directory name that will show up in error messages)
32- force: if 1, force compilation, even if timestamps are up-to-date
33- quiet: if 1, be quiet during compilation
33+ force: if True, force compilation, even if timestamps are up-to-date
34+ quiet: if True, be quiet during compilation
35+ legacy: if True, produce legacy pyc paths instead of PEP 3147 paths
3436
3537 """
3638 if not quiet :
@@ -49,24 +51,26 @@ def compile_dir(dir, maxlevels=10, ddir=None,
4951 else :
5052 dfile = None
5153 if not os .path .isdir (fullname ):
52- if not compile_file (fullname , ddir , force , rx , quiet ):
54+ if not compile_file (fullname , ddir , force , rx , quiet , legacy ):
5355 success = 0
5456 elif maxlevels > 0 and \
5557 name != os .curdir and name != os .pardir and \
5658 os .path .isdir (fullname ) and \
5759 not os .path .islink (fullname ):
5860 if not compile_dir (fullname , maxlevels - 1 , dfile , force , rx ,
59- quiet ):
61+ quiet , legacy ):
6062 success = 0
6163 return success
6264
63- def compile_file (fullname , ddir = None , force = 0 , rx = None , quiet = 0 ):
65+ def compile_file (fullname , ddir = None , force = 0 , rx = None , quiet = False ,
66+ legacy = False ):
6467 """Byte-compile file.
65- file: the file to byte-compile
68+ fullname: the file to byte-compile
6669 ddir: if given, purported directory name (this is the
6770 directory name that will show up in error messages)
68- force: if 1, force compilation, even if timestamps are up-to-date
69- quiet: if 1, be quiet during compilation
71+ force: if True, force compilation, even if timestamps are up-to-date
72+ quiet: if True, be quiet during compilation
73+ legacy: if True, produce legacy pyc paths instead of PEP 3147 paths
7074
7175 """
7276 success = 1
@@ -80,13 +84,22 @@ def compile_file(fullname, ddir=None, force=0, rx=None, quiet=0):
8084 if mo :
8185 return success
8286 if os .path .isfile (fullname ):
87+ if legacy :
88+ cfile = fullname + ('c' if __debug__ else 'o' )
89+ else :
90+ cfile = imp .cache_from_source (fullname )
91+ cache_dir = os .path .dirname (cfile )
92+ try :
93+ os .mkdir (cache_dir )
94+ except OSError as error :
95+ if error .errno != errno .EEXIST :
96+ raise
8397 head , tail = name [:- 3 ], name [- 3 :]
8498 if tail == '.py' :
8599 if not force :
86100 try :
87101 mtime = int (os .stat (fullname ).st_mtime )
88102 expect = struct .pack ('<4sl' , imp .get_magic (), mtime )
89- cfile = fullname + (__debug__ and 'c' or 'o' )
90103 with open (cfile , 'rb' ) as chandle :
91104 actual = chandle .read (8 )
92105 if expect == actual :
@@ -96,14 +109,15 @@ def compile_file(fullname, ddir=None, force=0, rx=None, quiet=0):
96109 if not quiet :
97110 print ('Compiling' , fullname , '...' )
98111 try :
99- ok = py_compile .compile (fullname , None , dfile , True )
112+ ok = py_compile .compile (fullname , cfile , dfile , True )
100113 except py_compile .PyCompileError as err :
101114 if quiet :
102115 print ('*** Error compiling' , fullname , '...' )
103116 else :
104117 print ('*** ' , end = '' )
105118 # escape non-printable characters in msg
106- msg = err .msg .encode (sys .stdout .encoding , errors = 'backslashreplace' )
119+ msg = err .msg .encode (sys .stdout .encoding ,
120+ errors = 'backslashreplace' )
107121 msg = msg .decode (sys .stdout .encoding )
108122 print (msg )
109123 success = 0
@@ -119,15 +133,17 @@ def compile_file(fullname, ddir=None, force=0, rx=None, quiet=0):
119133 success = 0
120134 return success
121135
122- def compile_path (skip_curdir = 1 , maxlevels = 0 , force = 0 , quiet = 0 ):
136+ def compile_path (skip_curdir = 1 , maxlevels = 0 , force = False , quiet = False ,
137+ legacy = False ):
123138 """Byte-compile all module on sys.path.
124139
125140 Arguments (all optional):
126141
127142 skip_curdir: if true, skip current directory (default true)
128143 maxlevels: max recursion level (default 0)
129- force: as for compile_dir() (default 0)
130- quiet: as for compile_dir() (default 0)
144+ force: as for compile_dir() (default False)
145+ quiet: as for compile_dir() (default False)
146+ legacy: as for compile_dir() (default False)
131147
132148 """
133149 success = 1
@@ -136,7 +152,8 @@ def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0):
136152 print ('Skipping current directory' )
137153 else :
138154 success = success and compile_dir (dir , maxlevels , None ,
139- force , quiet = quiet )
155+ force , quiet = quiet ,
156+ legacy = legacy )
140157 return success
141158
142159def expand_args (args , flist ):
@@ -162,10 +179,10 @@ def main():
162179 """Script main program."""
163180 import getopt
164181 try :
165- opts , args = getopt .getopt (sys .argv [1 :], 'lfqd:x:i:' )
182+ opts , args = getopt .getopt (sys .argv [1 :], 'lfqd:x:i:b ' )
166183 except getopt .error as msg :
167184 print (msg )
168- print ("usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \
185+ print ("usage: python compileall.py [-l] [-f] [-q] [-d destdir] "
169186 "[-x regexp] [-i list] [directory|file ...]" )
170187 print ("-l: don't recurse down" )
171188 print ("-f: force rebuild even if timestamps are up-to-date" )
@@ -174,23 +191,27 @@ def main():
174191 print (" if no directory arguments, -l sys.path is assumed" )
175192 print ("-x regexp: skip files matching the regular expression regexp" )
176193 print (" the regexp is searched for in the full path of the file" )
177- print ("-i list: expand list with its content (file and directory names)" )
194+ print ("-i list: expand list with its content "
195+ "(file and directory names)" )
196+ print ("-b: Produce legacy byte-compile file paths" )
178197 sys .exit (2 )
179198 maxlevels = 10
180199 ddir = None
181- force = 0
182- quiet = 0
200+ force = False
201+ quiet = False
183202 rx = None
184203 flist = None
204+ legacy = False
185205 for o , a in opts :
186206 if o == '-l' : maxlevels = 0
187207 if o == '-d' : ddir = a
188- if o == '-f' : force = 1
189- if o == '-q' : quiet = 1
208+ if o == '-f' : force = True
209+ if o == '-q' : quiet = True
190210 if o == '-x' :
191211 import re
192212 rx = re .compile (a )
193213 if o == '-i' : flist = a
214+ if o == '-b' : legacy = True
194215 if ddir :
195216 if len (args ) != 1 and not os .path .isdir (args [0 ]):
196217 print ("-d destdir require exactly one directory argument" )
@@ -207,13 +228,14 @@ def main():
207228 for arg in args :
208229 if os .path .isdir (arg ):
209230 if not compile_dir (arg , maxlevels , ddir ,
210- force , rx , quiet ):
231+ force , rx , quiet , legacy ):
211232 success = 0
212233 else :
213- if not compile_file (arg , ddir , force , rx , quiet ):
234+ if not compile_file (arg , ddir , force , rx ,
235+ quiet , legacy ):
214236 success = 0
215237 else :
216- success = compile_path ()
238+ success = compile_path (legacy = legacy )
217239 except KeyboardInterrupt :
218240 print ("\n [interrupt]" )
219241 success = 0
0 commit comments