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 # Ask for source text if not specified in sys.argv[1:]
57 srcfss
, ok
= macfs
.StandardGetFile('TEXT')
60 filename
= srcfss
.as_pathname()
61 tp
, tf
= os
.path
.split(filename
)
66 dstfss
, ok
= macfs
.StandardPutFile('Save application as:', tf
)
68 process(template
, filename
, dstfss
.as_pathname())
71 # Loop over all files to be processed
72 for filename
in sys
.argv
[1:]:
73 process(template
, filename
, '')
75 undefs
= ('????', ' ', '\0\0\0\0', 'BINA')
77 def process(template
, filename
, output
):
79 print "Processing", `filename`
, "..."
81 # Read the source and compile it
82 # (there's no point overwriting the destination if it has a syntax error)
88 code
= compile(text
, filename
, "exec")
89 except (SyntaxError, EOFError):
90 die("Syntax error in script %s" % `filename`
)
93 # Set the destination file name
95 if string
.lower(filename
[-3:]) == ".py":
96 destname
= filename
[:-3]
97 rsrcname
= destname
+ '.rsrc'
99 destname
= filename
+ ".applet"
100 rsrcname
= filename
+ '.rsrc'
104 # Copy the data from the template (creating the file as well)
106 tmpl
= open(template
, "rb")
107 dest
= open(destname
, "wb")
114 # Copy the creator of the template to the destination
115 # unless it already got one. Set type to APPL
117 tctor
, ttype
= MacOS
.GetCreatorAndType(template
)
118 ctor
, type = MacOS
.GetCreatorAndType(destname
)
119 if type in undefs
: type = 'APPL'
120 if ctor
in undefs
: ctor
= tctor
122 # Open the output resource fork
125 output
= FSpOpenResFile(destname
, WRITE
)
127 print "Creating resource fork..."
128 CreateResFile(destname
)
129 output
= FSpOpenResFile(destname
, WRITE
)
131 # Copy the resources from the template
133 input = FSpOpenResFile(template
, READ
)
134 newctor
= copyres(input, output
)
136 if newctor
: ctor
= newctor
138 # Copy the resources from the target specific resource template, if any
141 input = FSpOpenResFile(rsrcname
, READ
)
145 newctor
= copyres(input, output
)
147 if newctor
: ctor
= newctor
149 # Now set the creator and type of the destination
151 MacOS
.SetCreatorAndType(destname
, ctor
, type)
153 # Make sure we're manipulating the output resource file now
157 # Delete any existing 'PYC 'resource named __main__
160 res
= Get1NamedResource(RESTYPE
, RESNAME
)
165 # Create the raw data for the resource from the code object
167 data
= marshal
.dumps(code
)
169 data
= (MAGIC
+ '\0\0\0\0') + data
171 # Create the resource and write it
175 id = Unique1ID(RESTYPE
)
177 res
.AddResource(RESTYPE
, id, RESNAME
)
179 res
.ReleaseResource()
181 # Close the output file
185 # Give positive feedback
187 message("Applet %s created." % `destname`
)
190 # Copy resources between two resource file descriptors.
191 # Exception: don't copy a __main__ resource.
192 # If a resource's name is "owner resource", its type is returned
193 # (so the caller can use it to set the destination's creator)
195 def copyres(input, output
):
198 ntypes
= Count1Types()
199 for itype
in range(1, 1+ntypes
):
200 type = Get1IndType(itype
)
201 nresources
= Count1Resources(type)
202 for ires
in range(1, 1+nresources
):
203 res
= Get1IndResource(type, ires
)
204 id, type, name
= res
.GetResInfo()
205 lcname
= string
.lower(name
)
206 if (type, lcname
) == (RESTYPE
, RESNAME
):
207 continue # Don't copy __main__ from template
208 if lcname
== OWNERNAME
: ctor
= type
209 size
= res
.SizeResource()
210 attrs
= res
.GetResAttrs()
211 print id, type, name
, size
, hex(attrs
)
216 res2
= Get1Resource(type, id)
220 print "Overwriting..."
222 res
.AddResource(type, id, name
)
224 attrs
= attrs | res
.GetResAttrs()
225 print "New attrs =", hex(attrs
)
226 res
.SetResAttrs(attrs
)
231 # Show a message and exit
240 def message(str, id = 256):
242 d
= GetNewDialog(id, -1)
244 print "Error:", `
str`
245 print "DLOG id =", id, "not found."
247 tp
, h
, rect
= d
.GetDItem(2)
250 n
= ModalDialog(None)
255 if __name__
== '__main__':