blob: 95d6a089f32db253ae19f9a557eab11680ec74df [file] [log] [blame]
Guido van Rossum63566e21998-01-19 04:01:26 +00001"""Routine to "compile" a .py file to a .pyc (or .pyo) file.
2
3This module has intimate knowledge of the format of .pyc files.
4"""
Guido van Rossum3bb54481994-08-29 10:52:58 +00005
Fred Drakea96f1a32002-08-21 20:23:22 +00006import __builtin__
Sjoerd Mullender2e5168c1995-07-19 11:21:47 +00007import imp
Fred Drakea96f1a32002-08-21 20:23:22 +00008import marshal
9import os
10import sys
11import traceback
12
Sjoerd Mullender2e5168c1995-07-19 11:21:47 +000013MAGIC = imp.get_magic()
Guido van Rossum3bb54481994-08-29 10:52:58 +000014
Martin v. Löwis0c6774d2003-01-15 11:51:06 +000015__all__ = ["compile", "main", "PyCompileError"]
16
17
18class 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
Skip Montanaroc62c81e2001-02-12 02:00:42 +000063
Fred Drakea96f1a32002-08-21 20:23:22 +000064# Define an internal helper according to the platform
65if os.name == "mac":
66 import macfs
67 def set_creator_type(file):
68 macfs.FSSpec(file).SetCreatorType('Pyth', 'PYC ')
69else:
70 def set_creator_type(file):
71 pass
72
Guido van Rossum3bb54481994-08-29 10:52:58 +000073def wr_long(f, x):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000074 """Internal; write a 32-bit int to a file in little-endian order."""
Guido van Rossum63566e21998-01-19 04:01:26 +000075 f.write(chr( x & 0xff))
76 f.write(chr((x >> 8) & 0xff))
77 f.write(chr((x >> 16) & 0xff))
78 f.write(chr((x >> 24) & 0xff))
Guido van Rossum3bb54481994-08-29 10:52:58 +000079
Martin v. Löwis0c6774d2003-01-15 11:51:06 +000080def compile(file, cfile=None, dfile=None, doraise=False):
Guido van Rossum63566e21998-01-19 04:01:26 +000081 """Byte-compile one Python source file to Python bytecode.
82
83 Arguments:
84
Martin v. Löwis0c6774d2003-01-15 11:51:06 +000085 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
Guido van Rossum63566e21998-01-19 04:01:26 +000098 Note that it isn't necessary to byte-compile Python modules for
99 execution efficiency -- Python itself byte-compiles a module when
100 it is loaded, and if it can, writes out the bytecode to the
101 corresponding .pyc (or .pyo) file.
102
103 However, if a Python installation is shared between users, it is a
104 good idea to byte-compile all modules upon installation, since
105 other users may not be able to write in the source directories,
106 and thus they won't be able to write the .pyc/.pyo file, and then
107 they would be byte-compiling every module each time it is loaded.
108 This can slow down program start-up considerably.
109
110 See compileall.py for a script/module that uses this module to
111 byte-compile all installed files (or all files in selected
112 directories).
113
114 """
Jack Jansen7b8c7542002-04-14 20:12:41 +0000115 f = open(file, 'U')
Guido van Rossum63566e21998-01-19 04:01:26 +0000116 try:
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000117 timestamp = long(os.fstat(f.fileno()).st_mtime)
Guido van Rossum63566e21998-01-19 04:01:26 +0000118 except AttributeError:
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000119 timestamp = long(os.stat(file).st_mtime)
Guido van Rossum63566e21998-01-19 04:01:26 +0000120 codestring = f.read()
121 f.close()
122 if codestring and codestring[-1] != '\n':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000123 codestring = codestring + '\n'
Guido van Rossumf984a651998-09-29 15:57:42 +0000124 try:
Martin v. Löwis0c6774d2003-01-15 11:51:06 +0000125 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
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000133 if cfile is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000134 cfile = file + (__debug__ and 'c' or 'o')
Guido van Rossum63566e21998-01-19 04:01:26 +0000135 fc = open(cfile, 'wb')
136 fc.write('\0\0\0\0')
137 wr_long(fc, timestamp)
138 marshal.dump(codeobject, fc)
139 fc.flush()
140 fc.seek(0, 0)
141 fc.write(MAGIC)
142 fc.close()
Fred Drakea96f1a32002-08-21 20:23:22 +0000143 set_creator_type(cfile)
Fred Drake61cf4402002-08-21 20:56:21 +0000144
145def main(args=None):
146 """Compile several source files.
147
148 The files named in 'args' (or on the command line, if 'args' is
149 not specified) are compiled and the resulting bytecode is cached
150 in the normal manner. This function does not search a directory
151 structure to locate source files; it only compiles files named
152 explicitly.
153
154 """
155 if args is None:
156 args = sys.argv[1:]
157 for filename in args:
Martin v. Löwis0c6774d2003-01-15 11:51:06 +0000158 try:
159 compile(filename, doraise=True)
160 except PyCompileError,err:
161 sys.stderr.write(err.msg)
162
Fred Drake61cf4402002-08-21 20:56:21 +0000163if __name__ == "__main__":
164 main()