blob: 982570855b65fe45a544b39754f977c9c4847b78 [file] [log] [blame]
Jack Jansen813c9971998-07-31 09:42:35 +00001"""tools for BuildApplet and BuildApplication"""
2
3import sys
4import os
5import string
6import imp
7import marshal
8import macfs
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00009from Carbon import Res
Jack Jansen813c9971998-07-31 09:42:35 +000010import MACFS
11import MacOS
12import macostools
Jack Jansenb2e33fe2002-03-29 21:21:28 +000013import macresource
Jack Jansen813c9971998-07-31 09:42:35 +000014import EasyDialogs
Jack Jansenb2e33fe2002-03-29 21:21:28 +000015import shutil
Jack Jansen813c9971998-07-31 09:42:35 +000016
17
18BuildError = "BuildError"
19
Jack Jansen813c9971998-07-31 09:42:35 +000020# .pyc file (and 'PYC ' resource magic number)
21MAGIC = imp.get_magic()
22
23# Template file (searched on sys.path)
Jack Jansen3b805261999-02-14 23:12:06 +000024TEMPLATE = "PythonInterpreter"
Jack Jansen813c9971998-07-31 09:42:35 +000025
26# Specification of our resource
27RESTYPE = 'PYC '
28RESNAME = '__main__'
29
30# A resource with this name sets the "owner" (creator) of the destination
Jack Jansen81da9f11999-03-17 22:57:55 +000031# It should also have ID=0. Either of these alone is not enough.
Jack Jansen813c9971998-07-31 09:42:35 +000032OWNERNAME = "owner resource"
33
Jack Jansen81da9f11999-03-17 22:57:55 +000034# Default applet creator code
35DEFAULT_APPLET_CREATOR="Pyta"
36
Jack Jansen813c9971998-07-31 09:42:35 +000037# OpenResFile mode parameters
38READ = 1
39WRITE = 2
40
41
Jack Jansena4f8e582001-02-17 23:30:19 +000042def findtemplate(template=None):
Jack Jansen813c9971998-07-31 09:42:35 +000043 """Locate the applet template along sys.path"""
Jack Jansenb2e33fe2002-03-29 21:21:28 +000044 if MacOS.runtimemodel == 'macho':
45 if template:
46 return template
47 return findtemplate_macho()
Jack Jansena4f8e582001-02-17 23:30:19 +000048 if not template:
49 template=TEMPLATE
Jack Jansen813c9971998-07-31 09:42:35 +000050 for p in sys.path:
Jack Jansena4f8e582001-02-17 23:30:19 +000051 file = os.path.join(p, template)
Jack Jansen813c9971998-07-31 09:42:35 +000052 try:
Jack Jansena4f8e582001-02-17 23:30:19 +000053 file, d1, d2 = macfs.ResolveAliasFile(file)
Jack Jansen813c9971998-07-31 09:42:35 +000054 break
55 except (macfs.error, ValueError):
56 continue
57 else:
Jack Jansena4f8e582001-02-17 23:30:19 +000058 raise BuildError, "Template %s not found on sys.path" % `template`
59 file = file.as_pathname()
60 return file
Jack Jansenb2e33fe2002-03-29 21:21:28 +000061
62def findtemplate_macho():
63 execpath = sys.executable.split('/')
64 if not 'Contents' in execpath:
65 raise BuildError, "Not running from a .app bundle: %s" % sys.executable
66 i = execpath.index('Contents')
67 return '/'.join(execpath[:i])
Jack Jansen813c9971998-07-31 09:42:35 +000068
69
Jack Jansen388fbf32002-06-09 22:08:52 +000070def process(template, filename, destname, copy_codefragment,
71 rsrcname=None, others=[], raw=0, progress="default"):
Jack Jansen813c9971998-07-31 09:42:35 +000072
Jack Jansen388fbf32002-06-09 22:08:52 +000073 if progress == "default":
Jack Jansen813c9971998-07-31 09:42:35 +000074 progress = EasyDialogs.ProgressBar("Processing %s..."%os.path.split(filename)[1], 120)
75 progress.label("Compiling...")
Jack Jansen388fbf32002-06-09 22:08:52 +000076 progress.inc(0)
Jack Jansen813c9971998-07-31 09:42:35 +000077
78 # Read the source and compile it
79 # (there's no point overwriting the destination if it has a syntax error)
80
Jack Jansen5d099042002-06-20 20:42:07 +000081 fp = open(filename, 'rU')
Jack Jansen813c9971998-07-31 09:42:35 +000082 text = fp.read()
83 fp.close()
84 try:
85 code = compile(text, filename, "exec")
Jack Jansen2eb4b182002-08-02 14:04:15 +000086 except SyntaxError, arg:
87 raise BuildError, "Syntax error in script %s: %s" % (filename, arg)
88 except EOFError:
89 raise BuildError, "End-of-file in script %s" % (filename,)
Jack Jansen813c9971998-07-31 09:42:35 +000090
Jack Jansen388fbf32002-06-09 22:08:52 +000091 # Set the destination file name. Note that basename
92 # does contain the whole filepath, only a .py is stripped.
Jack Jansen813c9971998-07-31 09:42:35 +000093
94 if string.lower(filename[-3:]) == ".py":
Jack Jansen388fbf32002-06-09 22:08:52 +000095 basename = filename[:-3]
96 if MacOS.runtimemodel != 'macho' and not destname:
97 destname = basename
Jack Jansen813c9971998-07-31 09:42:35 +000098 else:
Jack Jansen388fbf32002-06-09 22:08:52 +000099 basename = filename
100
101 if not destname:
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000102 if MacOS.runtimemodel == 'macho':
Jack Jansen388fbf32002-06-09 22:08:52 +0000103 destname = basename + '.app'
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000104 else:
Jack Jansen388fbf32002-06-09 22:08:52 +0000105 destname = basename + '.applet'
106 if not rsrcname:
107 rsrcname = basename + '.rsrc'
108
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000109 # Try removing the output file. This fails in MachO, but it should
110 # do any harm.
Jack Jansen813c9971998-07-31 09:42:35 +0000111 try:
112 os.remove(destname)
113 except os.error:
114 pass
Jack Jansen388fbf32002-06-09 22:08:52 +0000115 process_common(template, progress, code, rsrcname, destname, 0,
116 copy_codefragment, raw, others)
Jack Jansen813c9971998-07-31 09:42:35 +0000117
118
119def update(template, filename, output):
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000120 if MacOS.runtimemodel == 'macho':
121 raise BuildError, "No updating yet for MachO applets"
Jack Jansen388fbf32002-06-09 22:08:52 +0000122 if progress:
Jack Jansen813c9971998-07-31 09:42:35 +0000123 progress = EasyDialogs.ProgressBar("Updating %s..."%os.path.split(filename)[1], 120)
124 else:
125 progress = None
126 if not output:
127 output = filename + ' (updated)'
128
129 # Try removing the output file
130 try:
131 os.remove(output)
132 except os.error:
133 pass
134 process_common(template, progress, None, filename, output, 1, 1)
135
136
Jack Jansen388fbf32002-06-09 22:08:52 +0000137def process_common(template, progress, code, rsrcname, destname, is_update,
138 copy_codefragment, raw=0, others=[]):
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000139 if MacOS.runtimemodel == 'macho':
Jack Jansen388fbf32002-06-09 22:08:52 +0000140 return process_common_macho(template, progress, code, rsrcname, destname,
141 is_update, raw, others)
142 if others:
143 raise BuildError, "Extra files only allowed for MachoPython applets"
Jack Jansen813c9971998-07-31 09:42:35 +0000144 # Create FSSpecs for the various files
145 template_fss = macfs.FSSpec(template)
146 template_fss, d1, d2 = macfs.ResolveAliasFile(template_fss)
147 dest_fss = macfs.FSSpec(destname)
148
149 # Copy data (not resources, yet) from the template
Jack Jansen388fbf32002-06-09 22:08:52 +0000150 if progress:
Jack Jansen813c9971998-07-31 09:42:35 +0000151 progress.label("Copy data fork...")
152 progress.set(10)
153
154 if copy_codefragment:
155 tmpl = open(template, "rb")
156 dest = open(destname, "wb")
157 data = tmpl.read()
158 if data:
159 dest.write(data)
160 dest.close()
161 tmpl.close()
162 del dest
163 del tmpl
164
165 # Open the output resource fork
166
Jack Jansen388fbf32002-06-09 22:08:52 +0000167 if progress:
Jack Jansen813c9971998-07-31 09:42:35 +0000168 progress.label("Copy resources...")
169 progress.set(20)
170 try:
171 output = Res.FSpOpenResFile(dest_fss, WRITE)
172 except MacOS.Error:
Jack Jansen01a2d9e2001-01-29 15:32:00 +0000173 Res.FSpCreateResFile(destname, '????', 'APPL', MACFS.smAllScripts)
Jack Jansen813c9971998-07-31 09:42:35 +0000174 output = Res.FSpOpenResFile(dest_fss, WRITE)
175
176 # Copy the resources from the target specific resource template, if any
177 typesfound, ownertype = [], None
178 try:
179 input = Res.FSpOpenResFile(rsrcname, READ)
180 except (MacOS.Error, ValueError):
181 pass
Jack Jansen388fbf32002-06-09 22:08:52 +0000182 if progress:
Jack Jansen813c9971998-07-31 09:42:35 +0000183 progress.inc(50)
184 else:
185 if is_update:
186 skip_oldfile = ['cfrg']
187 else:
188 skip_oldfile = []
189 typesfound, ownertype = copyres(input, output, skip_oldfile, 0, progress)
190 Res.CloseResFile(input)
191
192 # Check which resource-types we should not copy from the template
Jack Jansen81da9f11999-03-17 22:57:55 +0000193 skiptypes = []
194 if 'vers' in typesfound: skiptypes.append('vers')
Jack Jansen813c9971998-07-31 09:42:35 +0000195 if 'SIZE' in typesfound: skiptypes.append('SIZE')
196 if 'BNDL' in typesfound: skiptypes = skiptypes + ['BNDL', 'FREF', 'icl4',
197 'icl8', 'ics4', 'ics8', 'ICN#', 'ics#']
198 if not copy_codefragment:
199 skiptypes.append('cfrg')
Jack Jansen81da9f11999-03-17 22:57:55 +0000200## skipowner = (ownertype <> None)
Jack Jansen813c9971998-07-31 09:42:35 +0000201
202 # Copy the resources from the template
203
204 input = Res.FSpOpenResFile(template_fss, READ)
Jack Jansen81da9f11999-03-17 22:57:55 +0000205 dummy, tmplowner = copyres(input, output, skiptypes, 1, progress)
206
Jack Jansen813c9971998-07-31 09:42:35 +0000207 Res.CloseResFile(input)
Jack Jansen81da9f11999-03-17 22:57:55 +0000208## if ownertype == None:
209## raise BuildError, "No owner resource found in either resource file or template"
Jack Jansen813c9971998-07-31 09:42:35 +0000210 # Make sure we're manipulating the output resource file now
211
212 Res.UseResFile(output)
Jack Jansen81da9f11999-03-17 22:57:55 +0000213
214 if ownertype == None:
215 # No owner resource in the template. We have skipped the
216 # Python owner resource, so we have to add our own. The relevant
217 # bundle stuff is already included in the interpret/applet template.
218 newres = Res.Resource('\0')
219 newres.AddResource(DEFAULT_APPLET_CREATOR, 0, "Owner resource")
220 ownertype = DEFAULT_APPLET_CREATOR
Jack Jansen813c9971998-07-31 09:42:35 +0000221
222 if code:
223 # Delete any existing 'PYC ' resource named __main__
224
225 try:
226 res = Res.Get1NamedResource(RESTYPE, RESNAME)
227 res.RemoveResource()
228 except Res.Error:
229 pass
230
231 # Create the raw data for the resource from the code object
Jack Jansen388fbf32002-06-09 22:08:52 +0000232 if progress:
Jack Jansen813c9971998-07-31 09:42:35 +0000233 progress.label("Write PYC resource...")
234 progress.set(120)
235
236 data = marshal.dumps(code)
237 del code
238 data = (MAGIC + '\0\0\0\0') + data
239
240 # Create the resource and write it
241
242 id = 0
243 while id < 128:
244 id = Res.Unique1ID(RESTYPE)
245 res = Res.Resource(data)
246 res.AddResource(RESTYPE, id, RESNAME)
Just van Rossum874f87b1999-01-30 22:31:26 +0000247 attrs = res.GetResAttrs()
248 attrs = attrs | 0x04 # set preload
249 res.SetResAttrs(attrs)
Jack Jansen813c9971998-07-31 09:42:35 +0000250 res.WriteResource()
251 res.ReleaseResource()
252
253 # Close the output file
254
255 Res.CloseResFile(output)
256
257 # Now set the creator, type and bundle bit of the destination
258 dest_finfo = dest_fss.GetFInfo()
259 dest_finfo.Creator = ownertype
260 dest_finfo.Type = 'APPL'
Jack Jansenb70699b1999-12-03 23:38:05 +0000261 dest_finfo.Flags = dest_finfo.Flags | MACFS.kHasBundle | MACFS.kIsShared
Jack Jansen813c9971998-07-31 09:42:35 +0000262 dest_finfo.Flags = dest_finfo.Flags & ~MACFS.kHasBeenInited
263 dest_fss.SetFInfo(dest_finfo)
264
265 macostools.touched(dest_fss)
Jack Jansen388fbf32002-06-09 22:08:52 +0000266 if progress:
Jack Jansen813c9971998-07-31 09:42:35 +0000267 progress.label("Done.")
Jack Jansen388fbf32002-06-09 22:08:52 +0000268 progress.inc(0)
Jack Jansen813c9971998-07-31 09:42:35 +0000269
Jack Jansen388fbf32002-06-09 22:08:52 +0000270def process_common_macho(template, progress, code, rsrcname, destname, is_update, raw=0, others=[]):
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000271 # First make sure the name ends in ".app"
272 if destname[-4:] != '.app':
273 destname = destname + '.app'
274 # Now deduce the short name
275 shortname = os.path.split(destname)[1]
276 if shortname[-4:] == '.app':
277 # Strip the .app suffix
278 shortname = shortname[:-4]
Jack Jansen9aa8fd02002-03-29 23:44:37 +0000279 # And deduce the .plist and .icns names
280 plistname = None
281 icnsname = None
282 if rsrcname and rsrcname[-5:] == '.rsrc':
283 tmp = rsrcname[:-5]
284 plistname = tmp + '.plist'
285 if os.path.exists(plistname):
286 icnsname = tmp + '.icns'
287 if not os.path.exists(icnsname):
288 icnsname = None
289 else:
290 plistname = None
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000291 # Start with copying the .app framework
292 if not is_update:
293 exceptlist = ["Contents/Info.plist",
294 "Contents/Resources/English.lproj/InfoPlist.strings",
295 "Contents/Resources/python.rsrc",
296 ]
Jack Jansen388fbf32002-06-09 22:08:52 +0000297 copyapptree(template, destname, exceptlist, progress)
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000298 # Now either use the .plist file or the default
Jack Jansen388fbf32002-06-09 22:08:52 +0000299 if progress:
300 progress.label('Create info.plist')
301 progress.inc(0)
Jack Jansen9aa8fd02002-03-29 23:44:37 +0000302 if plistname:
Jack Jansen388fbf32002-06-09 22:08:52 +0000303 shutil.copy2(plistname, os.path.join(destname, 'Contents', 'Info.plist'))
Jack Jansen9aa8fd02002-03-29 23:44:37 +0000304 if icnsname:
305 icnsdest = os.path.split(icnsname)[1]
306 icnsdest = os.path.join(destname,
Jack Jansen388fbf32002-06-09 22:08:52 +0000307 os.path.join('Contents', 'Resources', icnsdest))
Jack Jansen9aa8fd02002-03-29 23:44:37 +0000308 shutil.copy2(icnsname, icnsdest)
309 # XXXX Wrong. This should be parsed from plist file. Also a big hack:-)
310 if shortname == 'PythonIDE':
311 ownertype = 'Pide'
312 else:
313 ownertype = 'PytA'
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000314 # XXXX Should copy .icns file
315 else:
Jack Jansen388fbf32002-06-09 22:08:52 +0000316 cocoainfo = ''
317 for o in others:
318 if o[-4:] == '.nib':
319 nibname = os.path.split(o)[1][:-4]
320 cocoainfo = """
321 <key>NSMainNibFile</key>
322 <string>%s</string>
323 <key>NSPrincipalClass</key>
324 <string>NSApplication</string>""" % nibname
325
326
327 plistname = os.path.join(template, 'Contents', 'Resources', 'Applet-Info.plist')
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000328 plistdata = open(plistname).read()
Jack Jansen388fbf32002-06-09 22:08:52 +0000329 plistdata = plistdata % {'appletname':shortname, 'cocoainfo':cocoainfo}
330 ofp = open(os.path.join(destname, 'Contents', 'Info.plist'), 'w')
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000331 ofp.write(plistdata)
332 ofp.close()
333 ownertype = 'PytA'
334 # Create the PkgInfo file
Jack Jansen388fbf32002-06-09 22:08:52 +0000335 if progress:
336 progress.label('Create PkgInfo')
337 progress.inc(0)
338 ofp = open(os.path.join(destname, 'Contents', 'PkgInfo'), 'wb')
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000339 ofp.write('APPL' + ownertype)
340 ofp.close()
341
342
Jack Jansen388fbf32002-06-09 22:08:52 +0000343 if progress:
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000344 progress.label("Copy resources...")
345 progress.set(20)
Jack Jansen2eb4b182002-08-02 14:04:15 +0000346 resfilename = 'python.rsrc' # XXXX later: '%s.rsrc' % shortname
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000347 try:
348 output = Res.FSOpenResourceFile(
Jack Jansen388fbf32002-06-09 22:08:52 +0000349 os.path.join(destname, 'Contents', 'Resources', resfilename),
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000350 u'', WRITE)
351 except MacOS.Error:
352 fsr, dummy = Res.FSCreateResourceFile(
Jack Jansen388fbf32002-06-09 22:08:52 +0000353 os.path.join(destname, 'Contents', 'Resources'),
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000354 unicode(resfilename), '')
355 output = Res.FSOpenResourceFile(fsr, u'', WRITE)
356
357 # Copy the resources from the target specific resource template, if any
358 typesfound, ownertype = [], None
359 try:
360 input = macresource.open_pathname(rsrcname)
361 except (MacOS.Error, ValueError):
362 pass
Jack Jansen388fbf32002-06-09 22:08:52 +0000363 if progress:
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000364 progress.inc(50)
365 else:
366 typesfound, ownertype = copyres(input, output, [], 0, progress)
367 Res.CloseResFile(input)
368
369 # Check which resource-types we should not copy from the template
370 skiptypes = []
371## if 'vers' in typesfound: skiptypes.append('vers')
372## if 'SIZE' in typesfound: skiptypes.append('SIZE')
373## if 'BNDL' in typesfound: skiptypes = skiptypes + ['BNDL', 'FREF', 'icl4',
374## 'icl8', 'ics4', 'ics8', 'ICN#', 'ics#']
375## if not copy_codefragment:
376## skiptypes.append('cfrg')
377## skipowner = (ownertype <> None)
378
379 # Copy the resources from the template
380
381 input = Res.FSOpenResourceFile(
Jack Jansen388fbf32002-06-09 22:08:52 +0000382 os.path.join(template, 'Contents', 'Resources', 'python.rsrc'), u'', READ)
383 if progress:
384 progress.label("Copy standard resources...")
385 progress.inc(0)
386## dummy, tmplowner = copyres(input, output, skiptypes, 1, progress)
387 dummy, tmplowner = copyres(input, output, skiptypes, 1, None)
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000388
389 Res.CloseResFile(input)
390## if ownertype == None:
391## raise BuildError, "No owner resource found in either resource file or template"
392 # Make sure we're manipulating the output resource file now
393
394 Res.CloseResFile(output)
395
396 if code:
Jack Jansen388fbf32002-06-09 22:08:52 +0000397 if raw:
398 pycname = '__rawmain__.pyc'
399 else:
400 pycname = '__main__.pyc'
401 outputfilename = os.path.join(destname, 'Contents', 'Resources', pycname)
402 if progress:
403 progress.label('Creating '+pycname)
404 progress.inc(0)
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000405 writepycfile(code, outputfilename)
Jack Jansen388fbf32002-06-09 22:08:52 +0000406 # Copy other files the user asked for
407 for osrc in others:
408 oname = os.path.split(osrc)[1]
409 odst = os.path.join(destname, 'Contents', 'Resources', oname)
410 if progress:
411 progress.label('Copy ' + oname)
412 progress.inc(0)
413 if os.path.isdir(osrc):
414 copyapptree(osrc, odst)
415 else:
416 shutil.copy2(osrc, odst)
417 if progress:
418 progress.label('Done.')
419 progress.inc(0)
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000420
421## macostools.touched(dest_fss)
Jack Jansen813c9971998-07-31 09:42:35 +0000422
423# Copy resources between two resource file descriptors.
Jack Jansen81da9f11999-03-17 22:57:55 +0000424# skip a resource named '__main__' or (if skipowner is set) with ID zero.
Jack Jansen813c9971998-07-31 09:42:35 +0000425# Also skip resources with a type listed in skiptypes.
426#
427def copyres(input, output, skiptypes, skipowner, progress=None):
428 ctor = None
429 alltypes = []
430 Res.UseResFile(input)
431 ntypes = Res.Count1Types()
432 progress_type_inc = 50/ntypes
433 for itype in range(1, 1+ntypes):
434 type = Res.Get1IndType(itype)
435 if type in skiptypes:
436 continue
437 alltypes.append(type)
438 nresources = Res.Count1Resources(type)
439 progress_cur_inc = progress_type_inc/nresources
440 for ires in range(1, 1+nresources):
441 res = Res.Get1IndResource(type, ires)
442 id, type, name = res.GetResInfo()
443 lcname = string.lower(name)
Jack Jansen81da9f11999-03-17 22:57:55 +0000444
445 if lcname == OWNERNAME and id == 0:
Jack Jansen813c9971998-07-31 09:42:35 +0000446 if skipowner:
447 continue # Skip this one
448 else:
449 ctor = type
450 size = res.size
451 attrs = res.GetResAttrs()
Jack Jansen388fbf32002-06-09 22:08:52 +0000452 if progress:
Jack Jansen813c9971998-07-31 09:42:35 +0000453 progress.label("Copy %s %d %s"%(type, id, name))
454 progress.inc(progress_cur_inc)
455 res.LoadResource()
456 res.DetachResource()
457 Res.UseResFile(output)
458 try:
459 res2 = Res.Get1Resource(type, id)
460 except MacOS.Error:
461 res2 = None
462 if res2:
Jack Jansen388fbf32002-06-09 22:08:52 +0000463 if progress:
Jack Jansen813c9971998-07-31 09:42:35 +0000464 progress.label("Overwrite %s %d %s"%(type, id, name))
Jack Jansen388fbf32002-06-09 22:08:52 +0000465 progress.inc(0)
Jack Jansen813c9971998-07-31 09:42:35 +0000466 res2.RemoveResource()
467 res.AddResource(type, id, name)
468 res.WriteResource()
469 attrs = attrs | res.GetResAttrs()
470 res.SetResAttrs(attrs)
471 Res.UseResFile(input)
472 return alltypes, ctor
473
Jack Jansen388fbf32002-06-09 22:08:52 +0000474def copyapptree(srctree, dsttree, exceptlist=[], progress=None):
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000475 names = []
476 if os.path.exists(dsttree):
477 shutil.rmtree(dsttree)
478 os.mkdir(dsttree)
479 todo = os.listdir(srctree)
480 while todo:
481 this, todo = todo[0], todo[1:]
482 if this in exceptlist:
483 continue
484 thispath = os.path.join(srctree, this)
485 if os.path.isdir(thispath):
486 thiscontent = os.listdir(thispath)
487 for t in thiscontent:
488 todo.append(os.path.join(this, t))
489 names.append(this)
490 for this in names:
491 srcpath = os.path.join(srctree, this)
492 dstpath = os.path.join(dsttree, this)
493 if os.path.isdir(srcpath):
494 os.mkdir(dstpath)
495 else:
Jack Jansen388fbf32002-06-09 22:08:52 +0000496 if progress:
497 progress.label('Copy '+this)
498 progress.inc(0)
Jack Jansenb2e33fe2002-03-29 21:21:28 +0000499 shutil.copy2(srcpath, dstpath)
500
501def writepycfile(codeobject, cfile):
502 import marshal
503 fc = open(cfile, 'wb')
504 fc.write('\0\0\0\0') # MAGIC placeholder, written later
505 fc.write('\0\0\0\0') # Timestap placeholder, not needed
506 marshal.dump(codeobject, fc)
507 fc.flush()
508 fc.seek(0, 0)
509 fc.write(MAGIC)
510 fc.close()
Jack Jansen813c9971998-07-31 09:42:35 +0000511