mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			525 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			525 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""tools for BuildApplet and BuildApplication"""
 | 
						|
 | 
						|
import sys
 | 
						|
import os
 | 
						|
import string
 | 
						|
import imp
 | 
						|
import marshal
 | 
						|
from Carbon import Res
 | 
						|
import Carbon.Files
 | 
						|
import Carbon.File
 | 
						|
import MacOS
 | 
						|
import macostools
 | 
						|
import macresource
 | 
						|
import EasyDialogs
 | 
						|
import shutil
 | 
						|
 | 
						|
 | 
						|
BuildError = "BuildError"
 | 
						|
 | 
						|
# .pyc file (and 'PYC ' resource magic number)
 | 
						|
MAGIC = imp.get_magic()
 | 
						|
 | 
						|
# Template file (searched on sys.path)
 | 
						|
TEMPLATE = "PythonInterpreter"
 | 
						|
 | 
						|
# Specification of our resource
 | 
						|
RESTYPE = 'PYC '
 | 
						|
RESNAME = '__main__'
 | 
						|
 | 
						|
# A resource with this name sets the "owner" (creator) of the destination
 | 
						|
# It should also have ID=0. Either of these alone is not enough.
 | 
						|
OWNERNAME = "owner resource"
 | 
						|
 | 
						|
# Default applet creator code
 | 
						|
DEFAULT_APPLET_CREATOR="Pyta"
 | 
						|
 | 
						|
# OpenResFile mode parameters
 | 
						|
READ = 1
 | 
						|
WRITE = 2
 | 
						|
 | 
						|
# Parameter for FSOpenResourceFile
 | 
						|
RESOURCE_FORK_NAME=Carbon.File.FSGetResourceForkName()
 | 
						|
 | 
						|
def findtemplate(template=None):
 | 
						|
	"""Locate the applet template along sys.path"""
 | 
						|
	if MacOS.runtimemodel == 'macho':
 | 
						|
		if template:
 | 
						|
			return template
 | 
						|
		return findtemplate_macho()
 | 
						|
	if not template:
 | 
						|
		template=TEMPLATE
 | 
						|
	for p in sys.path:
 | 
						|
		file = os.path.join(p, template)
 | 
						|
		try:
 | 
						|
			file, d1, d2 = Carbon.File.FSResolveAliasFile(file, 1)
 | 
						|
			break
 | 
						|
		except (Carbon.File.Error, ValueError):
 | 
						|
			continue
 | 
						|
	else:
 | 
						|
		raise BuildError, "Template %s not found on sys.path" % `template`
 | 
						|
	file = file.as_pathname()
 | 
						|
	return file
 | 
						|
	
 | 
						|
def findtemplate_macho():
 | 
						|
	execpath = sys.executable.split('/')
 | 
						|
	if not 'Contents' in execpath:
 | 
						|
		raise BuildError, "Not running from a .app bundle: %s" % sys.executable
 | 
						|
	i = execpath.index('Contents')
 | 
						|
	return '/'.join(execpath[:i])
 | 
						|
 | 
						|
 | 
						|
def process(template, filename, destname, copy_codefragment, 
 | 
						|
		rsrcname=None, others=[], raw=0, progress="default"):
 | 
						|
	
 | 
						|
	if progress == "default":
 | 
						|
		progress = EasyDialogs.ProgressBar("Processing %s..."%os.path.split(filename)[1], 120)
 | 
						|
		progress.label("Compiling...")
 | 
						|
		progress.inc(0)
 | 
						|
	# check for the script name being longer than 32 chars. This may trigger a bug
 | 
						|
	# on OSX that can destroy your sourcefile.
 | 
						|
	if '#' in os.path.split(filename)[1]:
 | 
						|
		raise BuildError, "BuildApplet could destroy your sourcefile on OSX, please rename: %s" % filename
 | 
						|
	# Read the source and compile it
 | 
						|
	# (there's no point overwriting the destination if it has a syntax error)
 | 
						|
	
 | 
						|
	fp = open(filename, 'rU')
 | 
						|
	text = fp.read()
 | 
						|
	fp.close()
 | 
						|
	try:
 | 
						|
		code = compile(text + '\n', filename, "exec")
 | 
						|
	except SyntaxError, arg:
 | 
						|
		raise BuildError, "Syntax error in script %s: %s" % (filename, arg)
 | 
						|
	except EOFError:
 | 
						|
		raise BuildError, "End-of-file in script %s" % (filename,)
 | 
						|
	
 | 
						|
	# Set the destination file name. Note that basename
 | 
						|
	# does contain the whole filepath, only a .py is stripped.
 | 
						|
	
 | 
						|
	if string.lower(filename[-3:]) == ".py":
 | 
						|
		basename = filename[:-3]
 | 
						|
		if MacOS.runtimemodel != 'macho' and not destname:
 | 
						|
			destname = basename
 | 
						|
	else:
 | 
						|
		basename = filename
 | 
						|
		
 | 
						|
	if not destname:
 | 
						|
		if MacOS.runtimemodel == 'macho':
 | 
						|
			destname = basename + '.app'
 | 
						|
		else:
 | 
						|
			destname = basename + '.applet'
 | 
						|
	if not rsrcname:
 | 
						|
		rsrcname = basename + '.rsrc'
 | 
						|
		
 | 
						|
	# Try removing the output file. This fails in MachO, but it should
 | 
						|
	# do any harm.
 | 
						|
	try:
 | 
						|
		os.remove(destname)
 | 
						|
	except os.error:
 | 
						|
		pass
 | 
						|
	process_common(template, progress, code, rsrcname, destname, 0, 
 | 
						|
		copy_codefragment, raw, others)
 | 
						|
	
 | 
						|
 | 
						|
def update(template, filename, output):
 | 
						|
	if MacOS.runtimemodel == 'macho':
 | 
						|
		raise BuildError, "No updating yet for MachO applets"
 | 
						|
	if progress:
 | 
						|
		progress = EasyDialogs.ProgressBar("Updating %s..."%os.path.split(filename)[1], 120)
 | 
						|
	else:
 | 
						|
		progress = None
 | 
						|
	if not output:
 | 
						|
		output = filename + ' (updated)'
 | 
						|
	
 | 
						|
	# Try removing the output file
 | 
						|
	try:
 | 
						|
		os.remove(output)
 | 
						|
	except os.error:
 | 
						|
		pass
 | 
						|
	process_common(template, progress, None, filename, output, 1, 1)
 | 
						|
 | 
						|
 | 
						|
def process_common(template, progress, code, rsrcname, destname, is_update, 
 | 
						|
		copy_codefragment, raw=0, others=[]):
 | 
						|
	if MacOS.runtimemodel == 'macho':
 | 
						|
		return process_common_macho(template, progress, code, rsrcname, destname,
 | 
						|
			is_update, raw, others)
 | 
						|
	if others:
 | 
						|
		raise BuildError, "Extra files only allowed for MachoPython applets"
 | 
						|
	# Create FSSpecs for the various files
 | 
						|
	template_fsr, d1, d2 = Carbon.File.FSResolveAliasFile(template, 1)
 | 
						|
	template = template_fsr.as_pathname()
 | 
						|
	
 | 
						|
	# Copy data (not resources, yet) from the template
 | 
						|
	if progress:
 | 
						|
		progress.label("Copy data fork...")
 | 
						|
		progress.set(10)
 | 
						|
	
 | 
						|
	if copy_codefragment:
 | 
						|
		tmpl = open(template, "rb")
 | 
						|
		dest = open(destname, "wb")
 | 
						|
		data = tmpl.read()
 | 
						|
		if data:
 | 
						|
			dest.write(data)
 | 
						|
		dest.close()
 | 
						|
		tmpl.close()
 | 
						|
		del dest
 | 
						|
		del tmpl
 | 
						|
	
 | 
						|
	# Open the output resource fork
 | 
						|
	
 | 
						|
	if progress:
 | 
						|
		progress.label("Copy resources...")
 | 
						|
		progress.set(20)
 | 
						|
	try:
 | 
						|
		output = Res.FSOpenResourceFile(destname, RESOURCE_FORK_NAME, WRITE)
 | 
						|
	except MacOS.Error:
 | 
						|
		destdir, destfile = os.path.split(destname)
 | 
						|
		Res.FSCreateResourceFile(destdir, unicode(destfile), RESOURCE_FORK_NAME)
 | 
						|
		output = Res.FSOpenResourceFile(destname, RESOURCE_FORK_NAME, WRITE)
 | 
						|
	
 | 
						|
	# Copy the resources from the target specific resource template, if any
 | 
						|
	typesfound, ownertype = [], None
 | 
						|
	try:
 | 
						|
		input = Res.FSOpenResourceFile(rsrcname, RESOURCE_FORK_NAME, READ)
 | 
						|
	except (MacOS.Error, ValueError):
 | 
						|
		pass
 | 
						|
		if progress:
 | 
						|
			progress.inc(50)
 | 
						|
	else:
 | 
						|
		if is_update:
 | 
						|
			skip_oldfile = ['cfrg']
 | 
						|
		else:
 | 
						|
			skip_oldfile = []
 | 
						|
		typesfound, ownertype = copyres(input, output, skip_oldfile, 0, progress)
 | 
						|
		Res.CloseResFile(input)
 | 
						|
	
 | 
						|
	# Check which resource-types we should not copy from the template
 | 
						|
	skiptypes = []
 | 
						|
	if 'vers' in typesfound: skiptypes.append('vers')
 | 
						|
	if 'SIZE' in typesfound: skiptypes.append('SIZE')
 | 
						|
	if 'BNDL' in typesfound: skiptypes = skiptypes + ['BNDL', 'FREF', 'icl4', 
 | 
						|
			'icl8', 'ics4', 'ics8', 'ICN#', 'ics#']
 | 
						|
	if not copy_codefragment:
 | 
						|
		skiptypes.append('cfrg')
 | 
						|
##	skipowner = (ownertype <> None)
 | 
						|
	
 | 
						|
	# Copy the resources from the template
 | 
						|
	
 | 
						|
	input = Res.FSOpenResourceFile(template, RESOURCE_FORK_NAME, READ)
 | 
						|
	dummy, tmplowner = copyres(input, output, skiptypes, 1, progress)
 | 
						|
		
 | 
						|
	Res.CloseResFile(input)
 | 
						|
##	if ownertype == None:
 | 
						|
##		raise BuildError, "No owner resource found in either resource file or template"
 | 
						|
	# Make sure we're manipulating the output resource file now
 | 
						|
	
 | 
						|
	Res.UseResFile(output)
 | 
						|
 | 
						|
	if ownertype == None:
 | 
						|
		# No owner resource in the template. We have skipped the
 | 
						|
		# Python owner resource, so we have to add our own. The relevant
 | 
						|
		# bundle stuff is already included in the interpret/applet template.
 | 
						|
		newres = Res.Resource('\0')
 | 
						|
		newres.AddResource(DEFAULT_APPLET_CREATOR, 0, "Owner resource")
 | 
						|
		ownertype = DEFAULT_APPLET_CREATOR
 | 
						|
	
 | 
						|
	if code:
 | 
						|
		# Delete any existing 'PYC ' resource named __main__
 | 
						|
		
 | 
						|
		try:
 | 
						|
			res = Res.Get1NamedResource(RESTYPE, RESNAME)
 | 
						|
			res.RemoveResource()
 | 
						|
		except Res.Error:
 | 
						|
			pass
 | 
						|
		
 | 
						|
		# Create the raw data for the resource from the code object
 | 
						|
		if progress:
 | 
						|
			progress.label("Write PYC resource...")
 | 
						|
			progress.set(120)
 | 
						|
		
 | 
						|
		data = marshal.dumps(code)
 | 
						|
		del code
 | 
						|
		data = (MAGIC + '\0\0\0\0') + data
 | 
						|
		
 | 
						|
		# Create the resource and write it
 | 
						|
		
 | 
						|
		id = 0
 | 
						|
		while id < 128:
 | 
						|
			id = Res.Unique1ID(RESTYPE)
 | 
						|
		res = Res.Resource(data)
 | 
						|
		res.AddResource(RESTYPE, id, RESNAME)
 | 
						|
		attrs = res.GetResAttrs()
 | 
						|
		attrs = attrs | 0x04	# set preload
 | 
						|
		res.SetResAttrs(attrs)
 | 
						|
		res.WriteResource()
 | 
						|
		res.ReleaseResource()
 | 
						|
	
 | 
						|
	# Close the output file
 | 
						|
	
 | 
						|
	Res.CloseResFile(output)
 | 
						|
	
 | 
						|
	# Now set the creator, type and bundle bit of the destination.
 | 
						|
	# Done with FSSpec's, FSRef FInfo isn't good enough yet (2.3a1+)
 | 
						|
	dest_fss = Carbon.File.FSSpec(destname)
 | 
						|
	dest_finfo = dest_fss.FSpGetFInfo()
 | 
						|
	dest_finfo.Creator = ownertype
 | 
						|
	dest_finfo.Type = 'APPL'
 | 
						|
	dest_finfo.Flags = dest_finfo.Flags | Carbon.Files.kHasBundle | Carbon.Files.kIsShared
 | 
						|
	dest_finfo.Flags = dest_finfo.Flags & ~Carbon.Files.kHasBeenInited
 | 
						|
	dest_fss.FSpSetFInfo(dest_finfo)
 | 
						|
	
 | 
						|
	macostools.touched(destname)
 | 
						|
	if progress:
 | 
						|
		progress.label("Done.")
 | 
						|
		progress.inc(0)
 | 
						|
 | 
						|
def process_common_macho(template, progress, code, rsrcname, destname, is_update, raw=0, others=[]):
 | 
						|
	# First make sure the name ends in ".app"
 | 
						|
	if destname[-4:] != '.app':
 | 
						|
		destname = destname + '.app'
 | 
						|
	# Now deduce the short name
 | 
						|
	shortname = os.path.split(destname)[1]
 | 
						|
	if shortname[-4:] == '.app':
 | 
						|
		# Strip the .app suffix
 | 
						|
		shortname = shortname[:-4]
 | 
						|
	# And deduce the .plist and .icns names
 | 
						|
	plistname = None
 | 
						|
	icnsname = None
 | 
						|
	if rsrcname and rsrcname[-5:] == '.rsrc':
 | 
						|
		tmp = rsrcname[:-5]
 | 
						|
		plistname = tmp + '.plist'
 | 
						|
		if os.path.exists(plistname):
 | 
						|
			icnsname = tmp + '.icns'
 | 
						|
			if not os.path.exists(icnsname):
 | 
						|
				icnsname = None
 | 
						|
		else:
 | 
						|
			plistname = None
 | 
						|
	# Start with copying the .app framework
 | 
						|
	if not is_update:
 | 
						|
		exceptlist = ["Contents/Info.plist", 
 | 
						|
				"Contents/Resources/English.lproj/InfoPlist.strings", 
 | 
						|
				"Contents/Resources/English.lproj/Documentation", 
 | 
						|
				"Contents/Resources/python.rsrc",
 | 
						|
				]
 | 
						|
		copyapptree(template, destname, exceptlist, progress)
 | 
						|
		# SERIOUS HACK. If we've just copied a symlink as the
 | 
						|
		# executable we assume we're running from the MacPython addon
 | 
						|
		# to 10.2 python. We remove the symlink again and install
 | 
						|
		# the appletrunner script.
 | 
						|
		executable = os.path.join(destname, "Contents/MacOS/python")
 | 
						|
		if os.path.islink(executable):
 | 
						|
			os.remove(executable)
 | 
						|
			dummyfp, appletrunner, d2 = imp.find_module('appletrunner')
 | 
						|
			del dummyfp
 | 
						|
			shutil.copy2(appletrunner, executable)
 | 
						|
			os.chmod(executable, 0775)
 | 
						|
	# Now either use the .plist file or the default
 | 
						|
	if progress:
 | 
						|
		progress.label('Create info.plist')
 | 
						|
		progress.inc(0)
 | 
						|
	if plistname:
 | 
						|
		shutil.copy2(plistname, os.path.join(destname, 'Contents', 'Info.plist'))
 | 
						|
		if icnsname:
 | 
						|
			icnsdest = os.path.split(icnsname)[1]
 | 
						|
			icnsdest = os.path.join(destname, 
 | 
						|
				os.path.join('Contents', 'Resources', icnsdest))
 | 
						|
			shutil.copy2(icnsname, icnsdest)
 | 
						|
		# XXXX Wrong. This should be parsed from plist file. Also a big hack:-)
 | 
						|
		if shortname == 'PythonIDE':
 | 
						|
			ownertype = 'Pide'
 | 
						|
		else:
 | 
						|
			ownertype = 'PytA'
 | 
						|
		# XXXX Should copy .icns file
 | 
						|
	else:
 | 
						|
		cocoainfo = ''
 | 
						|
		for o in others:
 | 
						|
			if o[-4:] == '.nib':
 | 
						|
				nibname = os.path.split(o)[1][:-4]
 | 
						|
				cocoainfo = """
 | 
						|
        <key>NSMainNibFile</key>
 | 
						|
        <string>%s</string>
 | 
						|
        <key>NSPrincipalClass</key>
 | 
						|
        <string>NSApplication</string>""" % nibname
 | 
						|
			elif o[-6:] == '.lproj':
 | 
						|
				files = os.listdir(o)
 | 
						|
				for f in files:
 | 
						|
					if f[-4:] == '.nib':
 | 
						|
						nibname = os.path.split(f)[1][:-4]
 | 
						|
						cocoainfo = """
 | 
						|
        <key>NSMainNibFile</key>
 | 
						|
        <string>%s</string>
 | 
						|
        <key>NSPrincipalClass</key>
 | 
						|
        <string>NSApplication</string>""" % nibname
 | 
						|
 | 
						|
		plistname = os.path.join(template, 'Contents', 'Resources', 'Applet-Info.plist')
 | 
						|
		plistdata = open(plistname).read()
 | 
						|
		plistdata = plistdata % {'appletname':shortname, 'cocoainfo':cocoainfo}
 | 
						|
		ofp = open(os.path.join(destname, 'Contents', 'Info.plist'), 'w')
 | 
						|
		ofp.write(plistdata)
 | 
						|
		ofp.close()
 | 
						|
		ownertype = 'PytA'
 | 
						|
	# Create the PkgInfo file
 | 
						|
	if progress:
 | 
						|
		progress.label('Create PkgInfo')
 | 
						|
		progress.inc(0)
 | 
						|
	ofp = open(os.path.join(destname, 'Contents', 'PkgInfo'), 'wb')
 | 
						|
	ofp.write('APPL' + ownertype)
 | 
						|
	ofp.close()
 | 
						|
		
 | 
						|
	
 | 
						|
	# Copy the resources from the target specific resource template, if any
 | 
						|
	typesfound, ownertype = [], None
 | 
						|
	try:
 | 
						|
		input = macresource.open_pathname(rsrcname)
 | 
						|
	except (MacOS.Error, ValueError):
 | 
						|
		if progress:
 | 
						|
			progress.inc(50)
 | 
						|
	else:
 | 
						|
		if progress:
 | 
						|
			progress.label("Copy resources...")
 | 
						|
			progress.set(20)
 | 
						|
		resfilename = 'python.rsrc'  # XXXX later: '%s.rsrc' % shortname
 | 
						|
		try:
 | 
						|
			output = Res.FSOpenResourceFile(
 | 
						|
					os.path.join(destname, 'Contents', 'Resources', resfilename), 
 | 
						|
					u'', WRITE)
 | 
						|
		except MacOS.Error:
 | 
						|
			fsr, dummy = Res.FSCreateResourceFile(
 | 
						|
					os.path.join(destname, 'Contents', 'Resources'), 
 | 
						|
					unicode(resfilename), '')
 | 
						|
			output = Res.FSOpenResourceFile(fsr, u'', WRITE)
 | 
						|
		
 | 
						|
		typesfound, ownertype = copyres(input, output, [], 0, progress)
 | 
						|
		Res.CloseResFile(input)
 | 
						|
		Res.CloseResFile(output)
 | 
						|
 | 
						|
	if code:
 | 
						|
		if raw:
 | 
						|
			pycname = '__rawmain__.pyc'
 | 
						|
		else:
 | 
						|
			pycname = '__main__.pyc'
 | 
						|
			# And we also create __rawmain__.pyc
 | 
						|
			outputfilename = os.path.join(destname, 'Contents', 'Resources', '__rawmain__.pyc')
 | 
						|
			if progress:
 | 
						|
				progress.label('Creating __rawmain__.pyc')
 | 
						|
				progress.inc(0)
 | 
						|
			rawsourcefp, rawsourcefile, d2 = imp.find_module('appletrawmain')
 | 
						|
			rawsource = rawsourcefp.read()
 | 
						|
			rawcode = compile(rawsource, rawsourcefile, 'exec')
 | 
						|
			writepycfile(rawcode, outputfilename)
 | 
						|
			
 | 
						|
		outputfilename = os.path.join(destname, 'Contents', 'Resources', pycname)
 | 
						|
		if progress:
 | 
						|
			progress.label('Creating '+pycname)
 | 
						|
			progress.inc(0)
 | 
						|
		writepycfile(code, outputfilename)
 | 
						|
	# Copy other files the user asked for
 | 
						|
	for osrc in others:
 | 
						|
		oname = os.path.split(osrc)[1]
 | 
						|
		odst = os.path.join(destname, 'Contents', 'Resources', oname)
 | 
						|
		if progress: 
 | 
						|
			progress.label('Copy ' + oname)
 | 
						|
			progress.inc(0)
 | 
						|
		if os.path.isdir(osrc):
 | 
						|
			copyapptree(osrc, odst)
 | 
						|
		else:
 | 
						|
			shutil.copy2(osrc, odst)
 | 
						|
	if progress: 
 | 
						|
		progress.label('Done.')
 | 
						|
		progress.inc(0)
 | 
						|
	
 | 
						|
##	macostools.touched(dest_fss)
 | 
						|
 | 
						|
# Copy resources between two resource file descriptors.
 | 
						|
# skip a resource named '__main__' or (if skipowner is set) with ID zero.
 | 
						|
# Also skip resources with a type listed in skiptypes.
 | 
						|
#
 | 
						|
def copyres(input, output, skiptypes, skipowner, progress=None):
 | 
						|
	ctor = None
 | 
						|
	alltypes = []
 | 
						|
	Res.UseResFile(input)
 | 
						|
	ntypes = Res.Count1Types()
 | 
						|
	progress_type_inc = 50/ntypes
 | 
						|
	for itype in range(1, 1+ntypes):
 | 
						|
		type = Res.Get1IndType(itype)
 | 
						|
		if type in skiptypes:
 | 
						|
			continue
 | 
						|
		alltypes.append(type)
 | 
						|
		nresources = Res.Count1Resources(type)
 | 
						|
		progress_cur_inc = progress_type_inc/nresources
 | 
						|
		for ires in range(1, 1+nresources):
 | 
						|
			res = Res.Get1IndResource(type, ires)
 | 
						|
			id, type, name = res.GetResInfo()
 | 
						|
			lcname = string.lower(name)
 | 
						|
 | 
						|
			if lcname == OWNERNAME and id == 0:
 | 
						|
				if skipowner:
 | 
						|
					continue # Skip this one
 | 
						|
				else:
 | 
						|
					ctor = type
 | 
						|
			size = res.size
 | 
						|
			attrs = res.GetResAttrs()
 | 
						|
			if progress:
 | 
						|
				progress.label("Copy %s %d %s"%(type, id, name))
 | 
						|
				progress.inc(progress_cur_inc)
 | 
						|
			res.LoadResource()
 | 
						|
			res.DetachResource()
 | 
						|
			Res.UseResFile(output)
 | 
						|
			try:
 | 
						|
				res2 = Res.Get1Resource(type, id)
 | 
						|
			except MacOS.Error:
 | 
						|
				res2 = None
 | 
						|
			if res2:
 | 
						|
				if progress:
 | 
						|
					progress.label("Overwrite %s %d %s"%(type, id, name))
 | 
						|
					progress.inc(0)
 | 
						|
				res2.RemoveResource()
 | 
						|
			res.AddResource(type, id, name)
 | 
						|
			res.WriteResource()
 | 
						|
			attrs = attrs | res.GetResAttrs()
 | 
						|
			res.SetResAttrs(attrs)
 | 
						|
			Res.UseResFile(input)
 | 
						|
	return alltypes, ctor
 | 
						|
 | 
						|
def copyapptree(srctree, dsttree, exceptlist=[], progress=None):
 | 
						|
	names = []
 | 
						|
	if os.path.exists(dsttree):
 | 
						|
		shutil.rmtree(dsttree)
 | 
						|
	os.mkdir(dsttree)
 | 
						|
	todo = os.listdir(srctree)
 | 
						|
	while todo:
 | 
						|
		this, todo = todo[0], todo[1:]
 | 
						|
		if this in exceptlist:
 | 
						|
			continue
 | 
						|
		thispath = os.path.join(srctree, this)
 | 
						|
		if os.path.isdir(thispath):
 | 
						|
			thiscontent = os.listdir(thispath)
 | 
						|
			for t in thiscontent:
 | 
						|
				todo.append(os.path.join(this, t))
 | 
						|
		names.append(this)
 | 
						|
	for this in names:
 | 
						|
		srcpath = os.path.join(srctree, this)
 | 
						|
		dstpath = os.path.join(dsttree, this)
 | 
						|
		if os.path.isdir(srcpath):
 | 
						|
			os.mkdir(dstpath)
 | 
						|
		elif os.path.islink(srcpath):
 | 
						|
			endpoint = os.readlink(srcpath)
 | 
						|
			os.symlink(endpoint, dstpath)
 | 
						|
		else:
 | 
						|
			if progress:
 | 
						|
				progress.label('Copy '+this)
 | 
						|
				progress.inc(0)
 | 
						|
			shutil.copy2(srcpath, dstpath)
 | 
						|
			
 | 
						|
def writepycfile(codeobject, cfile):
 | 
						|
	import marshal
 | 
						|
	fc = open(cfile, 'wb')
 | 
						|
	fc.write('\0\0\0\0') # MAGIC placeholder, written later
 | 
						|
	fc.write('\0\0\0\0') # Timestap placeholder, not needed
 | 
						|
	marshal.dump(codeobject, fc)
 | 
						|
	fc.flush()
 | 
						|
	fc.seek(0, 0)
 | 
						|
	fc.write(MAGIC)
 | 
						|
	fc.close()
 | 
						|
 |