From f59c6fa1256c4ddfcef95df8dd3f808c902fecc2 Mon Sep 17 00:00:00 2001 From: Jack Jansen Date: Wed, 12 Feb 2003 15:37:26 +0000 Subject: [PATCH] When in MacPython-OSX use bundlebuilder to create .app bundles. --- Lib/plat-mac/aepack.py | 4 + Lib/plat-mac/aetypes.py | 50 ++++------ Lib/plat-mac/bgenlocations.py | 4 +- Lib/plat-mac/buildtools.py | 174 ++++++---------------------------- 4 files changed, 52 insertions(+), 180 deletions(-) diff --git a/Lib/plat-mac/aepack.py b/Lib/plat-mac/aepack.py index bfe539a542a..17a7e7050de 100644 --- a/Lib/plat-mac/aepack.py +++ b/Lib/plat-mac/aepack.py @@ -88,6 +88,8 @@ def pack(x, forcetype = None): return x if isinstance(x, FSSType): return AE.AECreateDesc('fss ', x.data) + if isinstance(x, FSRefType): + return AE.AECreateDesc('fsrf', x.data) if isinstance(x, AliasType): return AE.AECreateDesc('alis', x.data) if isinstance(x, IntType): @@ -166,6 +168,8 @@ def unpack(desc, formodulename=""): return struct.unpack('d', data)[0] if t == typeFSS: return Carbon.File.FSSpec(rawdata=desc.data) + if t == typeFSRef: + return Carbon.File.FSRef(rawdata=desc.data) if t == typeInsertionLoc: record = desc.AECoerceDesc('reco') return mkinsertionloc(unpack(record, formodulename)) diff --git a/Lib/plat-mac/aetypes.py b/Lib/plat-mac/aetypes.py index ac339e72d04..b091a28ef04 100644 --- a/Lib/plat-mac/aetypes.py +++ b/Lib/plat-mac/aetypes.py @@ -11,24 +11,8 @@ import string # def pack(*args, **kwargs): from aepack import pack - return apply(pack, args, kwargs) + return pack( *args, **kwargs) -def IsSubclass(cls, base): - """Test whether CLASS1 is the same as or a subclass of CLASS2""" - # Loop to optimize for single inheritance - while 1: - if cls is base: return 1 - if len(cls.__bases__) <> 1: break - cls = cls.__bases__[0] - # Recurse to cope with multiple inheritance - for c in cls.__bases__: - if IsSubclass(c, base): return 1 - return 0 - -def IsInstance(x, cls): - """Test whether OBJECT is an instance of (a subclass of) CLASS""" - return type(x) is InstanceType and IsSubclass(x.__class__, cls) - def nice(s): """'nice' representation of an object""" if type(s) is StringType: return repr(s) @@ -63,7 +47,7 @@ class Enum: return pack(self.enum, typeEnumeration) def IsEnum(x): - return IsInstance(x, Enum) + return isinstance(x, Enum) def mkenum(enum): if IsEnum(enum): return enum @@ -108,7 +92,7 @@ class Boolean: return pack(struct.pack('b', self.bool), 'bool') def IsBoolean(x): - return IsInstance(x, Boolean) + return isinstance(x, Boolean) def mkboolean(bool): if IsBoolean(bool): return bool @@ -130,7 +114,7 @@ class Type: return pack(self.type, typeType) def IsType(x): - return IsInstance(x, Type) + return isinstance(x, Type) def mktype(type): if IsType(type): return type @@ -153,7 +137,7 @@ class Keyword: return pack(self.keyword, typeKeyword) def IsKeyword(x): - return IsInstance(x, Keyword) + return isinstance(x, Keyword) class Range: """An AE range object""" @@ -172,7 +156,7 @@ class Range: return pack({'star': self.start, 'stop': self.stop}, 'rang') def IsRange(x): - return IsInstance(x, Range) + return isinstance(x, Range) class Comparison: """An AE Comparison""" @@ -195,7 +179,7 @@ class Comparison: 'cmpd') def IsComparison(x): - return IsInstance(x, Comparison) + return isinstance(x, Comparison) class NComparison(Comparison): # The class attribute 'relo' must be set in a subclass @@ -220,7 +204,7 @@ class Ordinal: return pack(self.abso, 'abso') def IsOrdinal(x): - return IsInstance(x, Ordinal) + return isinstance(x, Ordinal) class NOrdinal(Ordinal): # The class attribute 'abso' must be set in a subclass @@ -250,7 +234,7 @@ class Logical: return pack({'logc': mkenum(self.logc), 'term': self.term}, 'logi') def IsLogical(x): - return IsInstance(x, Logical) + return isinstance(x, Logical) class StyledText: """An AE object respresenting text in a certain style""" @@ -269,7 +253,7 @@ class StyledText: return pack({'ksty': self.style, 'ktxt': self.text}, 'STXT') def IsStyledText(x): - return IsInstance(x, StyledText) + return isinstance(x, StyledText) class AEText: """An AE text object with style, script and language specified""" @@ -290,7 +274,7 @@ class AEText: keyAEText: self.text}, typeAEText) def IsAEText(x): - return IsInstance(x, AEText) + return isinstance(x, AEText) class IntlText: """A text object with script and language specified""" @@ -311,7 +295,7 @@ class IntlText: typeIntlText) def IsIntlText(x): - return IsInstance(x, IntlText) + return isinstance(x, IntlText) class IntlWritingCode: """An object representing script and language""" @@ -331,7 +315,7 @@ class IntlWritingCode: typeIntlWritingCode) def IsIntlWritingCode(x): - return IsInstance(x, IntlWritingCode) + return isinstance(x, IntlWritingCode) class QDPoint: """A point""" @@ -351,7 +335,7 @@ class QDPoint: typeQDPoint) def IsQDPoint(x): - return IsInstance(x, QDPoint) + return isinstance(x, QDPoint) class QDRectangle: """A rectangle""" @@ -374,7 +358,7 @@ class QDRectangle: typeQDRectangle) def IsQDRectangle(x): - return IsInstance(x, QDRectangle) + return isinstance(x, QDRectangle) class RGBColor: """An RGB color""" @@ -395,7 +379,7 @@ class RGBColor: typeRGBColor) def IsRGBColor(x): - return IsInstance(x, RGBColor) + return isinstance(x, RGBColor) class ObjectSpecifier: @@ -444,7 +428,7 @@ class ObjectSpecifier: 'obj ') def IsObjectSpecifier(x): - return IsInstance(x, ObjectSpecifier) + return isinstance(x, ObjectSpecifier) # Backwards compatability, sigh... diff --git a/Lib/plat-mac/bgenlocations.py b/Lib/plat-mac/bgenlocations.py index 87400e1c841..896861ebc70 100644 --- a/Lib/plat-mac/bgenlocations.py +++ b/Lib/plat-mac/bgenlocations.py @@ -26,9 +26,9 @@ else: # end of lines, so don't worry about that. # if sys.platform == 'mac': - _MWERKSDIR="Moes:Applications (Mac OS 9):Metrowerks CodeWarrior 7.0:Metrowerks CodeWarrior" + _MWERKSDIR="Sap:Applications (Mac OS 9):Metrowerks CodeWarrior 7.0:Metrowerks CodeWarrior" else: - _MWERKSDIR="/Volumes/Moes/Applications (Mac OS 9)/Metrowerks CodeWarrior 7.0/Metrowerks CodeWarrior/" + _MWERKSDIR="/Volumes/Sap/Applications (Mac OS 9)/Metrowerks CodeWarrior 7.0/Metrowerks CodeWarrior/" INCLUDEDIR=os.path.join(_MWERKSDIR, "MacOS Support", "Universal", "Interfaces", "CIncludes") # diff --git a/Lib/plat-mac/buildtools.py b/Lib/plat-mac/buildtools.py index 7cafce560f6..89d45103351 100644 --- a/Lib/plat-mac/buildtools.py +++ b/Lib/plat-mac/buildtools.py @@ -44,9 +44,7 @@ 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() + return None if not template: template=TEMPLATE for p in sys.path: @@ -61,15 +59,7 @@ def findtemplate(template=None): 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, +def process(template, filename, destname, copy_codefragment=0, rsrcname=None, others=[], raw=0, progress="default"): if progress == "default": @@ -118,7 +108,7 @@ def process(template, filename, destname, copy_codefragment, except os.error: pass process_common(template, progress, code, rsrcname, destname, 0, - copy_codefragment, raw, others) + copy_codefragment, raw, others, filename) def update(template, filename, output): @@ -140,10 +130,10 @@ def update(template, filename, output): def process_common(template, progress, code, rsrcname, destname, is_update, - copy_codefragment, raw=0, others=[]): + copy_codefragment, raw=0, others=[], filename=None): if MacOS.runtimemodel == 'macho': return process_common_macho(template, progress, code, rsrcname, destname, - is_update, raw, others) + is_update, raw, others, filename) if others: raise BuildError, "Extra files only allowed for MachoPython applets" # Create FSSpecs for the various files @@ -274,12 +264,16 @@ def process_common(template, progress, code, rsrcname, destname, is_update, progress.label("Done.") progress.inc(0) -def process_common_macho(template, progress, code, rsrcname, destname, is_update, raw=0, others=[]): +def process_common_macho(template, progress, code, rsrcname, destname, is_update, + raw=0, others=[], filename=None): + # Check that we have a filename + if filename is None: + raise BuildError, "Need source filename on MacOSX" # 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] + destdir, shortname = os.path.split(destname) if shortname[-4:] == '.app': # Strip the .app suffix shortname = shortname[:-4] @@ -295,136 +289,26 @@ def process_common_macho(template, progress, code, rsrcname, destname, is_update 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 not os.path.exists(rsrcname): + rsrcname = None if progress: - progress.label('Create info.plist') - progress.inc(0) + progress.label('Creating bundle...') + import bundlebuilder + builder = bundlebuilder.AppBuilder(verbosity=0) + builder.mainprogram = filename + builder.builddir = destdir + builder.name = shortname + if rsrcname: + builder.resources.append(rsrcname) + for o in others: + builder.resources.append(o) 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 = """ - NSMainNibFile - %s - NSPrincipalClass - NSApplication""" % 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 = """ - NSMainNibFile - %s - NSPrincipalClass - NSApplication""" % 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) + import Plist + builder.plist = Plist.fromFile(plistname) + if icnsname: + builder.iconfile = icnsname + builder.setup() + builder.build() if progress: progress.label('Done.') progress.inc(0)