1 """tools for BuildApplet and BuildApplication"""
16 BuildError
= "BuildError"
21 # .pyc file (and 'PYC ' resource magic number)
22 MAGIC
= imp
.get_magic()
24 # Template file (searched on sys.path)
25 TEMPLATE
= "PythonInterpreter"
27 # Specification of our resource
31 # A resource with this name sets the "owner" (creator) of the destination
32 # It should also have ID=0. Either of these alone is not enough.
33 OWNERNAME
= "owner resource"
35 # Default applet creator code
36 DEFAULT_APPLET_CREATOR
="Pyta"
38 # OpenResFile mode parameters
44 """Locate the applet template along sys.path"""
46 template
= os
.path
.join(p
, TEMPLATE
)
48 template
, d1
, d2
= macfs
.ResolveAliasFile(template
)
50 except (macfs
.error
, ValueError):
53 raise BuildError
, "Template %s not found on sys.path" % `TEMPLATE`
54 template
= template
.as_pathname()
58 def process(template
, filename
, output
, copy_codefragment
):
61 progress
= EasyDialogs
.ProgressBar("Processing %s..."%os.path
.split(filename
)[1], 120)
62 progress
.label("Compiling...")
66 # Read the source and compile it
67 # (there's no point overwriting the destination if it has a syntax error)
73 code
= compile(text
, filename
, "exec")
74 except (SyntaxError, EOFError):
75 raise BuildError
, "Syntax error in script %s" % `filename`
77 # Set the destination file name
79 if string
.lower(filename
[-3:]) == ".py":
80 destname
= filename
[:-3]
81 rsrcname
= destname
+ '.rsrc'
83 destname
= filename
+ ".applet"
84 rsrcname
= filename
+ '.rsrc'
89 # Try removing the output file
94 process_common(template
, progress
, code
, rsrcname
, destname
, 0, copy_codefragment
)
97 def update(template
, filename
, output
):
99 progress
= EasyDialogs
.ProgressBar("Updating %s..."%os.path
.split(filename
)[1], 120)
103 output
= filename
+ ' (updated)'
105 # Try removing the output file
110 process_common(template
, progress
, None, filename
, output
, 1, 1)
113 def process_common(template
, progress
, code
, rsrcname
, destname
, is_update
, copy_codefragment
):
114 # Create FSSpecs for the various files
115 template_fss
= macfs
.FSSpec(template
)
116 template_fss
, d1
, d2
= macfs
.ResolveAliasFile(template_fss
)
117 dest_fss
= macfs
.FSSpec(destname
)
119 # Copy data (not resources, yet) from the template
121 progress
.label("Copy data fork...")
124 if copy_codefragment
:
125 tmpl
= open(template
, "rb")
126 dest
= open(destname
, "wb")
135 # Open the output resource fork
138 progress
.label("Copy resources...")
141 output
= Res
.FSpOpenResFile(dest_fss
, WRITE
)
143 Res
.CreateResFile(destname
)
144 output
= Res
.FSpOpenResFile(dest_fss
, WRITE
)
146 # Copy the resources from the target specific resource template, if any
147 typesfound
, ownertype
= [], None
149 input = Res
.FSpOpenResFile(rsrcname
, READ
)
150 except (MacOS
.Error
, ValueError):
156 skip_oldfile
= ['cfrg']
159 typesfound
, ownertype
= copyres(input, output
, skip_oldfile
, 0, progress
)
160 Res
.CloseResFile(input)
162 # Check which resource-types we should not copy from the template
164 if 'vers' in typesfound
: skiptypes
.append('vers')
165 if 'SIZE' in typesfound
: skiptypes
.append('SIZE')
166 if 'BNDL' in typesfound
: skiptypes
= skiptypes
+ ['BNDL', 'FREF', 'icl4',
167 'icl8', 'ics4', 'ics8', 'ICN#', 'ics#']
168 if not copy_codefragment
:
169 skiptypes
.append('cfrg')
170 ## skipowner = (ownertype <> None)
172 # Copy the resources from the template
174 input = Res
.FSpOpenResFile(template_fss
, READ
)
175 dummy
, tmplowner
= copyres(input, output
, skiptypes
, 1, progress
)
177 Res
.CloseResFile(input)
178 ## if ownertype == None:
179 ## raise BuildError, "No owner resource found in either resource file or template"
180 # Make sure we're manipulating the output resource file now
182 Res
.UseResFile(output
)
184 if ownertype
== None:
185 # No owner resource in the template. We have skipped the
186 # Python owner resource, so we have to add our own. The relevant
187 # bundle stuff is already included in the interpret/applet template.
188 newres
= Res
.Resource('\0')
189 newres
.AddResource(DEFAULT_APPLET_CREATOR
, 0, "Owner resource")
190 ownertype
= DEFAULT_APPLET_CREATOR
193 # Delete any existing 'PYC ' resource named __main__
196 res
= Res
.Get1NamedResource(RESTYPE
, RESNAME
)
201 # Create the raw data for the resource from the code object
203 progress
.label("Write PYC resource...")
206 data
= marshal
.dumps(code
)
208 data
= (MAGIC
+ '\0\0\0\0') + data
210 # Create the resource and write it
214 id = Res
.Unique1ID(RESTYPE
)
215 res
= Res
.Resource(data
)
216 res
.AddResource(RESTYPE
, id, RESNAME
)
217 attrs
= res
.GetResAttrs()
218 attrs
= attrs |
0x04 # set preload
219 res
.SetResAttrs(attrs
)
221 res
.ReleaseResource()
223 # Close the output file
225 Res
.CloseResFile(output
)
227 # Now set the creator, type and bundle bit of the destination
228 dest_finfo
= dest_fss
.GetFInfo()
229 dest_finfo
.Creator
= ownertype
230 dest_finfo
.Type
= 'APPL'
231 dest_finfo
.Flags
= dest_finfo
.Flags | MACFS
.kHasBundle | MACFS
.kIsShared
232 dest_finfo
.Flags
= dest_finfo
.Flags
& ~MACFS
.kHasBeenInited
233 dest_fss
.SetFInfo(dest_finfo
)
235 macostools
.touched(dest_fss
)
237 progress
.label("Done.")
240 # Copy resources between two resource file descriptors.
241 # skip a resource named '__main__' or (if skipowner is set) with ID zero.
242 # Also skip resources with a type listed in skiptypes.
244 def copyres(input, output
, skiptypes
, skipowner
, progress
=None):
247 Res
.UseResFile(input)
248 ntypes
= Res
.Count1Types()
249 progress_type_inc
= 50/ntypes
250 for itype
in range(1, 1+ntypes
):
251 type = Res
.Get1IndType(itype
)
252 if type in skiptypes
:
254 alltypes
.append(type)
255 nresources
= Res
.Count1Resources(type)
256 progress_cur_inc
= progress_type_inc
/nresources
257 for ires
in range(1, 1+nresources
):
258 res
= Res
.Get1IndResource(type, ires
)
259 id, type, name
= res
.GetResInfo()
260 lcname
= string
.lower(name
)
262 if lcname
== OWNERNAME
and id == 0:
264 continue # Skip this one
268 attrs
= res
.GetResAttrs()
269 if DEBUG
and progress
:
270 progress
.label("Copy %s %d %s"%(type, id, name
))
271 progress
.inc(progress_cur_inc
)
274 Res
.UseResFile(output
)
276 res2
= Res
.Get1Resource(type, id)
280 if DEBUG
and progress
:
281 progress
.label("Overwrite %s %d %s"%(type, id, name
))
282 res2
.RemoveResource()
283 res
.AddResource(type, id, name
)
285 attrs
= attrs | res
.GetResAttrs()
286 res
.SetResAttrs(attrs
)
287 Res
.UseResFile(input)
288 return alltypes
, ctor