1 """Create an applet from a Python script.
3 This puts up a dialog asking for a Python source file ('TEXT').
4 The output is a file with the same name but its ".py" suffix dropped.
5 It is created by copying an applet template and then adding a 'PYC '
6 resource named __main__ containing the compiled, marshalled script.
10 sys
.stdout
= sys
.stderr
20 # .pyc file (and 'PYC ' resource magic number)
21 MAGIC
= imp
.get_magic()
23 # Template file (searched on sys.path)
24 TEMPLATE
= "PythonApplet"
26 # Specification of our resource
30 # A resource with this name sets the "owner" (creator) of the destination
31 OWNERNAME
= "owner resource"
33 # OpenResFile mode parameters
40 # (there's no point in proceeding if we can't find it)
43 template
= os
.path
.join(p
, TEMPLATE
)
45 tmpl
= open(template
, "rb")
51 die("Template %s not found" % `template`
)
54 # Convert to full pathname
55 template
= macfs
.FSSpec(template
).as_pathname()
57 # Ask for source text if not specified in sys.argv[1:]
60 srcfss
, ok
= macfs
.PromptGetFile('Select Python source file:', 'TEXT')
63 filename
= srcfss
.as_pathname()
64 tp
, tf
= os
.path
.split(filename
)
69 dstfss
, ok
= macfs
.StandardPutFile('Save application as:', tf
)
71 process(template
, filename
, dstfss
.as_pathname())
74 # Loop over all files to be processed
75 for filename
in sys
.argv
[1:]:
76 process(template
, filename
, '')
78 undefs
= ('Atmp', '????', ' ', '\0\0\0\0', 'BINA')
80 def process(template
, filename
, output
):
82 print "Processing", `filename`
, "..."
84 # Read the source and compile it
85 # (there's no point overwriting the destination if it has a syntax error)
91 code
= compile(text
, filename
, "exec")
92 except (SyntaxError, EOFError):
93 die("Syntax error in script %s" % `filename`
)
96 # Set the destination file name
98 if string
.lower(filename
[-3:]) == ".py":
99 destname
= filename
[:-3]
100 rsrcname
= destname
+ '.rsrc'
102 destname
= filename
+ ".applet"
103 rsrcname
= filename
+ '.rsrc'
107 # Copy the data from the template (creating the file as well)
109 tmpl
= open(template
, "rb")
110 dest
= open(destname
, "wb")
117 # Copy the creator of the template to the destination
118 # unless it already got one. Set type to APPL
120 tctor
, ttype
= MacOS
.GetCreatorAndType(template
)
121 ctor
, type = MacOS
.GetCreatorAndType(destname
)
122 if type in undefs
: type = 'APPL'
123 if ctor
in undefs
: ctor
= tctor
125 # Open the output resource fork
128 output
= FSpOpenResFile(destname
, WRITE
)
130 print "Creating resource fork..."
131 CreateResFile(destname
)
132 output
= FSpOpenResFile(destname
, WRITE
)
134 # Copy the resources from the template
136 input = FSpOpenResFile(template
, READ
)
137 newctor
= copyres(input, output
)
139 if newctor
: ctor
= newctor
141 # Copy the resources from the target specific resource template, if any
144 input = FSpOpenResFile(rsrcname
, READ
)
148 newctor
= copyres(input, output
)
150 if newctor
: ctor
= newctor
152 # Now set the creator and type of the destination
154 MacOS
.SetCreatorAndType(destname
, ctor
, type)
156 # Make sure we're manipulating the output resource file now
160 # Delete any existing 'PYC 'resource named __main__
163 res
= Get1NamedResource(RESTYPE
, RESNAME
)
168 # Create the raw data for the resource from the code object
170 data
= marshal
.dumps(code
)
172 data
= (MAGIC
+ '\0\0\0\0') + data
174 # Create the resource and write it
178 id = Unique1ID(RESTYPE
)
180 res
.AddResource(RESTYPE
, id, RESNAME
)
182 res
.ReleaseResource()
184 # Close the output file
188 # Give positive feedback
190 message("Applet %s created." % `destname`
)
193 # Copy resources between two resource file descriptors.
194 # Exception: don't copy a __main__ resource.
195 # If a resource's name is "owner resource", its type is returned
196 # (so the caller can use it to set the destination's creator)
198 def copyres(input, output
):
201 ntypes
= Count1Types()
202 for itype
in range(1, 1+ntypes
):
203 type = Get1IndType(itype
)
204 nresources
= Count1Resources(type)
205 for ires
in range(1, 1+nresources
):
206 res
= Get1IndResource(type, ires
)
207 id, type, name
= res
.GetResInfo()
208 lcname
= string
.lower(name
)
209 if (type, lcname
) == (RESTYPE
, RESNAME
):
210 continue # Don't copy __main__ from template
211 if lcname
== OWNERNAME
: ctor
= type
213 attrs
= res
.GetResAttrs()
214 print id, type, name
, size
, hex(attrs
)
219 res2
= Get1Resource(type, id)
223 print "Overwriting..."
224 res2
.RemoveResource()
225 res
.AddResource(type, id, name
)
227 attrs
= attrs | res
.GetResAttrs()
228 print "New attrs =", hex(attrs
)
229 res
.SetResAttrs(attrs
)
234 # Show a message and exit
243 def message(str, id = 256):
245 d
= GetNewDialog(id, -1)
247 print "Error:", `
str`
248 print "DLOG id =", id, "not found."
250 tp
, h
, rect
= d
.GetDialogItem(2)
251 SetDialogItemText(h
, str)
253 n
= ModalDialog(None)
258 if __name__
== '__main__':