1212
1313MAGIC = imp .get_magic ()
1414
15- __all__ = ["compile" , "main" ]
15+ __all__ = ["compile" , "main" , "PyCompileError" ]
16+
17+
18+ class PyCompileError (Exception ):
19+ """Exception raised when an error occurs while attempting to
20+ compile the file.
21+
22+ To raise this exception, use
23+
24+ raise PyCompileError(exc_type,exc_value,file[,msg])
25+
26+ where
27+
28+ exc_type: exception type to be used in error message
29+ type name can be accesses as class variable
30+ 'exc_type_name'
31+
32+ exc_value: exception value to be used in error message
33+ can be accesses as class variable 'exc_value'
34+
35+ file: name of file being compiled to be used in error message
36+ can be accesses as class variable 'file'
37+
38+ msg: string message to be written as error message
39+ If no value is given, a default exception message will be given,
40+ consistent with 'standard' py_compile output.
41+ message (or default) can be accesses as class variable 'msg'
42+
43+ """
44+
45+ def __init__ (self , exc_type , exc_value , file , msg = '' ):
46+ exc_type_name = exc_type .__name__
47+ if exc_type is SyntaxError :
48+ tbtext = '' .join (traceback .format_exception_only (exc_type , exc_value ))
49+ errmsg = tbtext .replace ('File "<string>"' , 'File "%s"' % file )
50+ else :
51+ errmsg = "Sorry: %s: %s" % (exc_type_name ,exc_value )
52+
53+ Exception .__init__ (self ,msg or errmsg ,exc_type_name ,exc_value ,file )
54+
55+ self .exc_type_name = exc_type_name
56+ self .exc_value = exc_value
57+ self .file = file
58+ self .msg = msg or errmsg
59+
60+ def __str__ (self ):
61+ return self .msg
62+
1663
1764# Define an internal helper according to the platform
1865if os .name == "mac" :
@@ -30,17 +77,24 @@ def wr_long(f, x):
3077 f .write (chr ((x >> 16 ) & 0xff ))
3178 f .write (chr ((x >> 24 ) & 0xff ))
3279
33- def compile (file , cfile = None , dfile = None ):
80+ def compile (file , cfile = None , dfile = None , doraise = False ):
3481 """Byte-compile one Python source file to Python bytecode.
3582
3683 Arguments:
3784
38- file: source filename
39- cfile: target filename; defaults to source with 'c' or 'o' appended
40- ('c' normally, 'o' in optimizing mode, giving .pyc or .pyo)
41- dfile: purported filename; defaults to source (this is the filename
42- that will show up in error messages)
43-
85+ file: source filename
86+ cfile: target filename; defaults to source with 'c' or 'o' appended
87+ ('c' normally, 'o' in optimizing mode, giving .pyc or .pyo)
88+ dfile: purported filename; defaults to source (this is the filename
89+ that will show up in error messages)
90+ doraise: flag indicating whether or not an exception should be
91+ raised when a compile error is found. If an exception
92+ occurs and this flag is set to False, a string
93+ indicating the nature of the exception will be printed,
94+ and the function will return to the caller. If an
95+ exception occurs and this flag is set to True, a
96+ PyCompileError exception will be raised.
97+
4498 Note that it isn't necessary to byte-compile Python modules for
4599 execution efficiency -- Python itself byte-compiles a module when
46100 it is loaded, and if it can, writes out the bytecode to the
@@ -68,13 +122,14 @@ def compile(file, cfile=None, dfile=None):
68122 if codestring and codestring [- 1 ] != '\n ' :
69123 codestring = codestring + '\n '
70124 try :
71- codeobject = __builtin__ .compile (codestring , dfile or file , 'exec' )
72- except SyntaxError , detail :
73- lines = traceback .format_exception_only (SyntaxError , detail )
74- for line in lines :
75- sys .stderr .write (line .replace ('File "<string>"' ,
76- 'File "%s"' % (dfile or file )))
77- return
125+ codeobject = __builtin__ .compile (codestring , dfile or file ,'exec' )
126+ except Exception ,err :
127+ py_exc = PyCompileError (err .__class__ ,err .args ,dfile or file )
128+ if doraise :
129+ raise py_exc
130+ else :
131+ sys .stderr .write (py_exc .msg )
132+ return
78133 if cfile is None :
79134 cfile = file + (__debug__ and 'c' or 'o' )
80135 fc = open (cfile , 'wb' )
@@ -100,7 +155,10 @@ def main(args=None):
100155 if args is None :
101156 args = sys .argv [1 :]
102157 for filename in args :
103- compile (filename )
104-
158+ try :
159+ compile (filename , doraise = True )
160+ except PyCompileError ,err :
161+ sys .stderr .write (err .msg )
162+
105163if __name__ == "__main__" :
106164 main ()
0 commit comments