Mailing List Archive

CVS: python/dist/src/Mac/Lib buildtools.py,1.9,1.10
Update of /cvsroot/python/python/dist/src/Mac/Lib
In directory usw-pr-cvs1:/tmp/cvs-serv29893

Modified Files:
buildtools.py
Log Message:
Implemented buildtools for MachoPython .app bundles. The API is compatible
enough that IDE and BuildApplet can create applets, yeah!


Index: buildtools.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Mac/Lib/buildtools.py,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** buildtools.py 25 Aug 2001 12:01:58 -0000 1.9
--- buildtools.py 29 Mar 2002 21:21:28 -0000 1.10
***************
*** 11,15 ****
--- 11,17 ----
import MacOS
import macostools
+ import macresource
import EasyDialogs
+ import shutil


***************
*** 43,46 ****
--- 45,52 ----
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
***************
*** 56,59 ****
--- 62,72 ----
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])


***************
*** 83,87 ****
rsrcname = destname + '.rsrc'
else:
! destname = filename + ".applet"
rsrcname = filename + '.rsrc'

--- 96,103 ----
rsrcname = destname + '.rsrc'
else:
! if MacOS.runtimemodel == 'macho':
! destname = filename + '.app'
! else:
! destname = filename + ".applet"
rsrcname = filename + '.rsrc'

***************
*** 89,93 ****
destname = output

try:
os.remove(destname)
--- 105,110 ----
destname = output

try:
os.remove(destname)
***************
*** 98,101 ****
--- 115,120 ----

def update(template, filename, output):
+ if MacOS.runtimemodel == 'macho':
+ raise BuildError, "No updating yet for MachO applets"
if DEBUG:
progress = EasyDialogs.ProgressBar("Updating %s..."%os.path.split(filename)[1], 120)
***************
*** 114,117 ****
--- 133,138 ----

def process_common(template, progress, code, rsrcname, destname, is_update, copy_codefragment):
+ if MacOS.runtimemodel == 'macho':
+ return process_common_macho(template, progress, code, rsrcname, destname, is_update)
# Create FSSpecs for the various files
template_fss = macfs.FSSpec(template)
***************
*** 239,242 ****
--- 260,356 ----
progress.label("Done.")

+ def process_common_macho(template, progress, code, rsrcname, destname, is_update):
+ # 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]
+ plistname = shortname + '.plist'
+ # Start with copying the .app framework
+ if not is_update:
+ exceptlist = ["Contents/Info.plist",
+ "Contents/Resources/English.lproj/InfoPlist.strings",
+ "Contents/Resources/python.rsrc",
+ ]
+ copyapptree(template, destname, exceptlist)
+ # Now either use the .plist file or the default
+ if plistname and os.path.exists(plistname):
+ shutil.copy2(plistname, os.path.join(destname, 'Contents/Info.plist'))
+ # XXXX Wrong. This should be parsed from plist file
+ # icnsname = 'PythonApplet.icns'
+ ownertype = 'PytA'
+ # XXXX Should copy .icns file
+ else:
+ plistname = os.path.join(template, 'Contents/Resources/Applet-Info.plist')
+ plistdata = open(plistname).read()
+ plistdata = plistdata % {'appletname':shortname}
+ ofp = open(os.path.join(destname, 'Contents/Info.plist'), 'w')
+ ofp.write(plistdata)
+ ofp.close()
+ ownertype = 'PytA'
+ # Create the PkgInfo file
+ ofp = open(os.path.join(destname, 'Contents/PkgInfo'), 'wb')
+ ofp.write('APPL' + ownertype)
+ ofp.close()
+
+
+ if DEBUG:
+ progress.label("Copy resources...")
+ progress.set(20)
+ resfilename = '%s.rsrc' % shortname
+ respartialpathname = 'Contents/Resources/%s' % resfilename
+ try:
+ output = Res.FSOpenResourceFile(
+ os.path.join(destname, respartialpathname),
+ u'', WRITE)
+ except MacOS.Error:
+ fsr, dummy = Res.FSCreateResourceFile(
+ os.path.join(destname, 'Contents/Resources'),
+ unicode(resfilename), '')
+ output = Res.FSOpenResourceFile(fsr, u'', WRITE)
+
+ # Copy the resources from the target specific resource template, if any
+ typesfound, ownertype = [], None
+ try:
+ input = macresource.open_pathname(rsrcname)
+ except (MacOS.Error, ValueError):
+ pass
+ if DEBUG:
+ progress.inc(50)
+ else:
+ typesfound, ownertype = copyres(input, output, [], 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(
+ os.path.join(template, 'Contents/Resources/python.rsrc'), u'', 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.CloseResFile(output)
+
+ if code:
+ outputfilename = os.path.join(destname, 'Contents/Resources/__main__.pyc')
+ writepycfile(code, outputfilename)
+
+ ## macostools.touched(dest_fss)

# Copy resources between two resource file descriptors.
***************
*** 290,292 ****
--- 404,440 ----
return alltypes, ctor

+ def copyapptree(srctree, dsttree, exceptlist=[]):
+ 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)
+ else:
+ 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()