blob: 6f9f111b0040a74b4dd142b11be350820b669c11 [file] [log] [blame]
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +00001"""Create an applet from a Python script.
Guido van Rossum2d546921995-02-17 14:28:39 +00002
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +00003This puts up a dialog asking for a Python source file ('TEXT').
4The output is a file with the same name but its ".py" suffix dropped.
5It is created by copying an applet template and then adding a 'PYC '
6resource named __main__ containing the compiled, marshalled script.
Guido van Rossum2d546921995-02-17 14:28:39 +00007"""
8
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +00009import sys
Guido van Rossum57128fd1995-02-19 15:49:17 +000010sys.stdout = sys.stderr
11
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000012import string
13import os
Guido van Rossum2d546921995-02-17 14:28:39 +000014import marshal
15import imp
16import macfs
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000017import MacOS
Guido van Rossum2d546921995-02-17 14:28:39 +000018from Res import *
19
20# .pyc file (and 'PYC ' resource magic number)
21MAGIC = imp.get_magic()
22
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000023# Template file (searched on sys.path)
24TEMPLATE = "PythonApplet"
25
26# Specification of our resource
Guido van Rossum2d546921995-02-17 14:28:39 +000027RESTYPE = 'PYC '
Guido van Rossum2d546921995-02-17 14:28:39 +000028RESNAME = '__main__'
29
Guido van Rossum83c434b1995-02-26 10:19:42 +000030# A resource with this name sets the "owner" (creator) of the destination
31OWNERNAME = "owner resource"
32
Guido van Rossum2d546921995-02-17 14:28:39 +000033# OpenResFile mode parameters
34READ = 1
35WRITE = 2
36
37def main():
38
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000039 # Find the template
40 # (there's no point in proceeding if we can't find it)
41
42 for p in sys.path:
43 template = os.path.join(p, TEMPLATE)
44 try:
45 tmpl = open(template, "rb")
Guido van Rossum57128fd1995-02-19 15:49:17 +000046 tmpl.close()
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000047 break
48 except IOError:
49 continue
50 else:
Guido van Rossum42a69c81995-02-20 23:44:14 +000051 die("Template %s not found" % `template`)
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000052 return
53
Guido van Rossum57128fd1995-02-19 15:49:17 +000054 # Ask for source text if not specified in sys.argv[1:]
Guido van Rossum2d546921995-02-17 14:28:39 +000055
Guido van Rossum57128fd1995-02-19 15:49:17 +000056 if not sys.argv[1:]:
57 srcfss, ok = macfs.StandardGetFile('TEXT')
58 if not ok:
59 return
60 filename = srcfss.as_pathname()
61 if not sys.argv: sys.argv.append('')
62 sys.argv.append(filename)
63
64 # Loop over all files to be processed
65
66 for filename in sys.argv[1:]:
67 process(template, filename)
68
Jack Jansen397c3fb1995-02-24 22:46:51 +000069undefs = ('????', ' ', '\0\0\0\0', 'BINA')
Guido van Rossum57128fd1995-02-19 15:49:17 +000070
71def process(template, filename):
72
73 print "Processing", `filename`, "..."
Guido van Rossum2d546921995-02-17 14:28:39 +000074
75 # Read the source and compile it
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000076 # (there's no point overwriting the destination if it has a syntax error)
Guido van Rossum2d546921995-02-17 14:28:39 +000077
Guido van Rossum2d546921995-02-17 14:28:39 +000078 fp = open(filename)
79 text = fp.read()
80 fp.close()
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000081 try:
82 code = compile(text, filename, "exec")
83 except (SyntaxError, EOFError):
Guido van Rossum42a69c81995-02-20 23:44:14 +000084 die("Syntax error in script %s" % `filename`)
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000085 return
Guido van Rossum2d546921995-02-17 14:28:39 +000086
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000087 # Set the destination file name
Guido van Rossum2d546921995-02-17 14:28:39 +000088
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000089 if string.lower(filename[-3:]) == ".py":
90 destname = filename[:-3]
Guido van Rossum42a69c81995-02-20 23:44:14 +000091 rsrcname = destname + '.rsrc'
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000092 else:
93 destname = filename + ".applet"
Guido van Rossum42a69c81995-02-20 23:44:14 +000094 rsrcname = filename + '.rsrc'
Guido van Rossum2d546921995-02-17 14:28:39 +000095
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000096 # Copy the data from the template (creating the file as well)
Guido van Rossum2d546921995-02-17 14:28:39 +000097
Guido van Rossum57128fd1995-02-19 15:49:17 +000098 tmpl = open(template, "rb")
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +000099 dest = open(destname, "wb")
100 data = tmpl.read()
101 if data:
102 dest.write(data)
103 dest.close()
104 tmpl.close()
Guido van Rossum2d546921995-02-17 14:28:39 +0000105
Jack Jansen77b58281995-02-20 15:49:27 +0000106 # Copy the creator of the template to the destination
Guido van Rossum42a69c81995-02-20 23:44:14 +0000107 # unless it already got one. Set type to APPL
108
Guido van Rossum57128fd1995-02-19 15:49:17 +0000109 tctor, ttype = MacOS.GetCreatorAndType(template)
110 ctor, type = MacOS.GetCreatorAndType(destname)
Jack Jansen77b58281995-02-20 15:49:27 +0000111 if type in undefs: type = 'APPL'
Guido van Rossum57128fd1995-02-19 15:49:17 +0000112 if ctor in undefs: ctor = tctor
Guido van Rossum2d546921995-02-17 14:28:39 +0000113
Guido van Rossum42a69c81995-02-20 23:44:14 +0000114 # Open the output resource fork
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +0000115
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +0000116 try:
117 output = FSpOpenResFile(destname, WRITE)
118 except MacOS.Error:
119 print "Creating resource fork..."
120 CreateResFile(destname)
121 output = FSpOpenResFile(destname, WRITE)
122
Guido van Rossum42a69c81995-02-20 23:44:14 +0000123 # Copy the resources from the template
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +0000124
Guido van Rossum42a69c81995-02-20 23:44:14 +0000125 input = FSpOpenResFile(template, READ)
Guido van Rossum83c434b1995-02-26 10:19:42 +0000126 newctor = copyres(input, output)
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +0000127 CloseResFile(input)
Guido van Rossum83c434b1995-02-26 10:19:42 +0000128 if newctor: ctor = newctor
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +0000129
Guido van Rossum42a69c81995-02-20 23:44:14 +0000130 # Copy the resources from the target specific resource template, if any
131
132 try:
133 input = FSpOpenResFile(rsrcname, READ)
134 except MacOS.Error:
135 pass
136 else:
Guido van Rossum83c434b1995-02-26 10:19:42 +0000137 newctor = copyres(input, output)
Guido van Rossum42a69c81995-02-20 23:44:14 +0000138 CloseResFile(input)
Guido van Rossum83c434b1995-02-26 10:19:42 +0000139 if newctor: ctor = newctor
140
141 # Now set the creator and type of the destination
142
143 MacOS.SetCreatorAndType(destname, ctor, type)
Guido van Rossum42a69c81995-02-20 23:44:14 +0000144
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +0000145 # Make sure we're manipulating the output resource file now
146
147 UseResFile(output)
148
149 # Delete any existing 'PYC 'resource named __main__
Guido van Rossum2d546921995-02-17 14:28:39 +0000150
151 try:
152 res = Get1NamedResource(RESTYPE, RESNAME)
153 res.RmveResource()
154 except Error:
155 pass
156
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +0000157 # Create the raw data for the resource from the code object
158
159 data = marshal.dumps(code)
160 del code
161 data = (MAGIC + '\0\0\0\0') + data
Guido van Rossum2d546921995-02-17 14:28:39 +0000162
163 # Create the resource and write it
164
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +0000165 id = 0
166 while id < 128:
167 id = Unique1ID(RESTYPE)
Guido van Rossum2d546921995-02-17 14:28:39 +0000168 res = Resource(data)
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +0000169 res.AddResource(RESTYPE, id, RESNAME)
Guido van Rossum2d546921995-02-17 14:28:39 +0000170 res.WriteResource()
171 res.ReleaseResource()
172
Guido van Rossum42a69c81995-02-20 23:44:14 +0000173 # Close the output file
Guido van Rossum2d546921995-02-17 14:28:39 +0000174
Guido van Rossum6a0fb6e1995-02-18 15:05:39 +0000175 CloseResFile(output)
Guido van Rossum57128fd1995-02-19 15:49:17 +0000176
Guido van Rossum42a69c81995-02-20 23:44:14 +0000177 # Give positive feedback
178
179 message("Applet %s created." % `destname`)
180
181
Guido van Rossum83c434b1995-02-26 10:19:42 +0000182# Copy resources between two resource file descriptors.
183# Exception: don't copy a __main__ resource.
184# If a resource's name is "owner resource", its type is returned
185# (so the caller can use it to set the destination's creator)
Guido van Rossum42a69c81995-02-20 23:44:14 +0000186
187def copyres(input, output):
Guido van Rossum83c434b1995-02-26 10:19:42 +0000188 ctor = None
Guido van Rossum42a69c81995-02-20 23:44:14 +0000189 UseResFile(input)
190 ntypes = Count1Types()
191 for itype in range(1, 1+ntypes):
192 type = Get1IndType(itype)
193 nresources = Count1Resources(type)
194 for ires in range(1, 1+nresources):
195 res = Get1IndResource(type, ires)
196 id, type, name = res.GetResInfo()
Guido van Rossum83c434b1995-02-26 10:19:42 +0000197 lcname = string.lower(name)
198 if (type, lcname) == (RESTYPE, RESNAME):
Guido van Rossum42a69c81995-02-20 23:44:14 +0000199 continue # Don't copy __main__ from template
Guido van Rossum83c434b1995-02-26 10:19:42 +0000200 if lcname == OWNERNAME: ctor = type
Guido van Rossum42a69c81995-02-20 23:44:14 +0000201 size = res.SizeResource()
202 attrs = res.GetResAttrs()
203 print id, type, name, size, hex(attrs)
204 res.LoadResource()
205 res.DetachResource()
206 UseResFile(output)
207 try:
208 res2 = Get1Resource(type, id)
209 except MacOS.Error:
210 res2 = None
211 if res2:
212 print "Overwriting..."
213 res2.RmveResource()
214 res.AddResource(type, id, name)
Guido van Rossum42a69c81995-02-20 23:44:14 +0000215 res.WriteResource()
Guido van Rossum83c434b1995-02-26 10:19:42 +0000216 attrs = attrs | res.GetResAttrs()
217 print "New attrs =", hex(attrs)
218 res.SetResAttrs(attrs)
Guido van Rossum42a69c81995-02-20 23:44:14 +0000219 UseResFile(input)
Guido van Rossum83c434b1995-02-26 10:19:42 +0000220 return ctor
Guido van Rossum42a69c81995-02-20 23:44:14 +0000221
222
223# Show a message and exit
224
225def die(str):
226 message(str)
227 sys.exit(1)
228
229
230# Show a message
231
232def message(str, id = 256):
233 from Dlg import *
234 d = GetNewDialog(id, -1)
235 if not d:
236 print "Error:", `str`
237 print "DLOG id =", id, "not found."
238 return
239 tp, h, rect = d.GetDItem(2)
240 SetIText(h, str)
241 while 1:
242 n = ModalDialog(None)
243 if n == 1: break
244 del d
Guido van Rossum57128fd1995-02-19 15:49:17 +0000245
Guido van Rossum2d546921995-02-17 14:28:39 +0000246
247if __name__ == '__main__':
248 main()
Guido van Rossum83c434b1995-02-26 10:19:42 +0000249