]> git.saurik.com Git - wxWidgets.git/commitdiff
Updated Installer builder scripts and such for OS X
authorRobin Dunn <robin@alldunn.com>
Sat, 17 Jan 2004 23:20:49 +0000 (23:20 +0000)
committerRobin Dunn <robin@alldunn.com>
Sat, 17 Jan 2004 23:20:49 +0000 (23:20 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@25219 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

13 files changed:
wxPython/distrib/mac/MacPython/.cvsignore [deleted file]
wxPython/distrib/mac/MacPython/README.txt [deleted file]
wxPython/distrib/mac/MacPython/build [deleted file]
wxPython/distrib/mac/MacPython/resources/Welcome.txt [deleted file]
wxPython/distrib/mac/MacPython/resources/postflight [deleted file]
wxPython/distrib/mac/buildpkg.py
wxPython/distrib/mac/bundlebuilder.py
wxPython/distrib/mac/wxPythonOSX/build
wxPython/distrib/mac/wxPythonOSX/resources/.cvsignore [new file with mode: 0644]
wxPython/distrib/mac/wxPythonOSX/resources/ReadMe.rtf [deleted file]
wxPython/distrib/mac/wxPythonOSX/resources/preflight [deleted file]
wxPython/distrib/mac/zappycfiles.py
wxPython/scripts/CreateMacScripts.py

diff --git a/wxPython/distrib/mac/MacPython/.cvsignore b/wxPython/distrib/mac/MacPython/.cvsignore
deleted file mode 100644 (file)
index e43b0f9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.DS_Store
diff --git a/wxPython/distrib/mac/MacPython/README.txt b/wxPython/distrib/mac/MacPython/README.txt
deleted file mode 100644 (file)
index 89ecd2b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-This is a set of build scripts and such for MacPython-OSX 2.3 that I
-will use until there are standard distributions from Jack.
-
diff --git a/wxPython/distrib/mac/MacPython/build b/wxPython/distrib/mac/MacPython/build
deleted file mode 100755 (executable)
index f684d43..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/bin/sh -e
-#----------------------------------------------------------------------
-# Build MacPython 2.3 and make an Installer package of it
-
-# TODO:  Parameterize the versions, builddirs, etc...
-
-# Script configs
-PYVERSION=2.3a2
-PYVER=2.3
-BUILDNUM=3
-DOCLEANUP=no
-
-PROGDIR="`dirname \"$0\"`"
-TMPDIR=/tmp/_py
-#TMPDIR=/projects/_py
-
-BUILDROOT=$TMPDIR/build
-INSTALLROOT=$TMPDIR/install
-DMGDIR=$TMPDIR/dmg
-RESOURCEDIR=$PROGDIR/resources
-DESTDIR=/projects/wx/wxPython/dist
-PYTHONSRC=/projects/Python-$PYVERSION
-WASTEDIR=/projects/waste
-
-# Setup
-mkdir -p $BUILDROOT
-mkdir -p $INSTALLROOT
-rm -rf $DMGDIR
-mkdir -p $DMGDIR/root
-
-
-# Configure and build Python
-pushd $BUILDROOT
-
-# Check if we should build and install the docs, but only if it
-# doesn't appear to be done already.  TODO: fix this path to be version independent
-if [ ! -e "build/temp.darwin-6.3-Power Macintosh-2.3/build-html/build-html idx" ]; then
-    read -p "Build the Python docs? (y/N)? " builddocs
-fi
-
-# If the filesystem is case-sensitive then "python" will be built, but
-# some parts of the install expect "python.exe which is what is built
-# on a case-insensitive filesystem.  Make a link just in case it is
-# needed.
-if [ ! -e python.exe ]; then
-    ln -s python python.exe
-fi
-
-# Make a link to the waste dir so that lib can be found.  This allows
-# the PythonIDE to be built
-if [ ! -e waste ]; then
-    ln -s $WASTEDIR waste
-fi
-
-$PYTHONSRC/configure --enable-framework=$INSTALLROOT/Library/Frameworks LDFLAGS=-Wl,-x
-make
-make frameworkinstall
-
-if [ "$builddocs" = "y" -o "$builddocs" = "Y" ]; then
-    ./python.exe $PYTHONSRC/Mac/OSX/setupDocs.py build
-    echo ""
-    read -p "When the help indexer is done press Enter..." ans
-    ./python.exe $PYTHONSRC/Mac/OSX/setupDocs.py install \
-       --prefix=$INSTALLROOT/Library/Frameworks/Python.framework/Versions/$PYVER
-fi
-
-popd
-
-
-
-# Make the Installer package:
-# First, remove the unix tools as their paths will be wrong.  We'll recreate
-# them in the postinstall.
-rm -r $INSTALLROOT/usr
-
-# Next, remove the .pyc/.pyo files
-python $PROGDIR/../zappycfiles.py $INSTALLROOT/Library/Frameworks/Python.framework/Versions/$PYVER/lib/python$PYVER
-
-# Make the welcome message
-cat > $RESOURCEDIR/Welcome.txt <<EOF
-Welcome!
-
-This program will install Python $PYVERSION for Mac OS X as a Framework.
-
-Build number: $BUILDNUM
-Build date:   `date`
-EOF
-
-
-# fix a bug in the IDLE install
-IDLERES=$INSTALLROOT/Applications/MacPython-2.3/IDLE.app/Contents/Resources
-mv $IDLERES/idlelib/idle $IDLERES
-
-
-# Finally, build the package...
-rm -rf MacPython-OSX.pkg
-python $PROGDIR/../buildpkg.py \
-    --Title=MacPython-OSX \
-    --Version=$PYVERSION-$BUILDNUM \
-    --Description="Python $PYVERSION for Mac OS X, framework based" \
-    --NeedsAuthorization="YES" \
-    --Relocatable="NO" \
-    --InstallOnly="YES" \
-    $INSTALLROOT \
-    $RESOURCEDIR
-
-##    --RootVolumeOnly="YES" \
-
-# ...and then make a disk image containing the package.
-mv MacPython-OSX.pkg $DMGDIR/root
-$PROGDIR/../makedmg $DMGDIR/root $DMGDIR MacPython-OSX-$PYVERSION-$BUILDNUM
-
-echo Moving $DMGDIR/MacPython-OSX-$PYVERSION-$BUILDNUM to $DESTDIR
-mv $DMGDIR/MacPython-OSX-$PYVERSION-$BUILDNUM.dmg $DESTDIR
-
-
-# Cleanup build/install dirs
-if [ $DOCLEANUP = yes ]; then
-    echo "Cleaning up..."
-    rm -rf $BUILDROOT
-    rm -rf $INSTALLROOT
-    rm -rf $DMGDIR
-else
-    echo "Cleanup is disabled.  You should remove these dirs when done:"
-    echo "          $BUILDROOT"
-    echo "          $INSTALLROOT"
-    echo "          $DMGDIR"
-fi
-
diff --git a/wxPython/distrib/mac/MacPython/resources/Welcome.txt b/wxPython/distrib/mac/MacPython/resources/Welcome.txt
deleted file mode 100644 (file)
index 9ecb080..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-Welcome!
-
-This program will install Python 2.3a2 for Mac OS X as a Framework.
-
-Build number: 3
-Build date:   Thu Mar 20 18:54:52 PST 2003
diff --git a/wxPython/distrib/mac/MacPython/resources/postflight b/wxPython/distrib/mac/MacPython/resources/postflight
deleted file mode 100755 (executable)
index 25c12c1..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/sh
-#----------------------------------------------------------------------
-# Create the unix tools and compile the .py files after Python has been
-# installed.
-#----------------------------------------------------------------------
-
-PYVER=2.3
-
-PKG=$1
-DEST=$2
-
-
-# if destination is / then use usr/local/bin, otherwise just bin
-if [ "$DEST" = "/" ]; then
-    TOOLDIR=/usr/local/bin
-    DEST=
-else
-    TOOLDIR=$DEST/bin
-fi
-
-# Make sure the dir exists
-mkdir -p $TOOLDIR
-
-# Make some links to the python executable
-if [ -e $TOOLDIR/python$PYVER ]; then
-    rm $TOOLDIR/python$PYVER
-fi
-ln -fs $DEST/Library/Frameworks/Python.framework/Versions/$PYVER/bin/python $TOOLDIR/python$PYVER
-
-if [ -e $TOOLDIR/python ]; then
-    rm $TOOLDIR/python
-fi
-ln -fs python$PYVER $TOOLDIR/python
-
-
-# make the pythonw script
-cat > $TOOLDIR/pythonw <<EOF
-#!/bin/sh
-exec "$DEST/Library/Frameworks/Python.framework/Versions/$PYVER/Resources/Python.app/Contents/MacOS/python" "\$@"
-EOF
-chmod +x $TOOLDIR/pythonw
-
-
-# Compile the .py files in the Python library to .pyc's and then .pyo's
-$TOOLDIR/python -Wi -tt \
-    $DEST/Library/Frameworks/Python.framework/Versions/$PYVER/lib/python$PYVER/compileall.py \
-    -x badsyntax -x site-packages $DEST/Library/Frameworks/Python.framework/Versions/$PYVER/lib/python$PYVER
-
-$TOOLDIR/python -Wi -tt -O \
-    $DEST/Library/Frameworks/Python.framework/Versions/$PYVER/lib/python$PYVER/compileall.py \
-    -x badsyntax -x site-packages  $DEST/Library/Frameworks/Python.framework/Versions/$PYVER/lib/python$PYVER
-
-
-# Make the site-packages and other dirs writable by the admin.
-for d in $DEST/Library/Frameworks/Python.framework/Versions/$PYVER/lib/python$PYVER/site-packages \
-         $DEST/Library/Frameworks/Python.framework/Versions/$PYVER/bin \
-         $DEST/Applications/MacPython-$PYVER; do
-    chgrp -R admin $d
-    chmod -R g+w   $d
-done
-
-
-# The link in the app bundles needs updated.
-for app in BuildApplet IDLE PackageManager PythonIDE; do
-    ln -s $DEST/Library/Frameworks/Python.framework/Versions/$PYVER/Resources/Python.app/Contents/MacOS/python \
-          $DEST/Applications/MacPython-$PYVER/$app.app/Contents/MacOS
-done
index 5aade1ac8e6332290aa01ef7d90924a1e88651eb..a9c70c111caf8cee9b23a69c2b2d56a061b07767 100644 (file)
@@ -3,34 +3,34 @@
 """buildpkg.py -- Build OS X packages for Apple's Installer.app.
 
 This is an experimental command-line tool for building packages to be
-installed with the Mac OS X Installer.app application.
+installed with the Mac OS X Installer.app application. 
 
-It is much inspired by Apple's GUI tool called PackageMaker.app, that
-seems to be part of the OS X developer tools installed in the folder
-/Developer/Applications. But apparently there are other free tools to
-do the same thing which are also named PackageMaker like Brian Hill's
-one:
+It is much inspired by Apple's GUI tool called PackageMaker.app, that 
+seems to be part of the OS X developer tools installed in the folder 
+/Developer/Applications. But apparently there are other free tools to 
+do the same thing which are also named PackageMaker like Brian Hill's 
+one: 
 
   http://personalpages.tds.net/~brian_hill/packagemaker.html
 
-Beware of the multi-package features of Installer.app (which are not
-yet supported here) that can potentially screw-up your installation
+Beware of the multi-package features of Installer.app (which are not 
+yet supported here) that can potentially screw-up your installation 
 and are discussed in these articles on Stepwise:
 
   http://www.stepwise.com/Articles/Technical/Packages/InstallerWoes.html
   http://www.stepwise.com/Articles/Technical/Packages/InstallerOnX.html
 
-Beside using the PackageMaker class directly, by importing it inside
+Beside using the PackageMaker class directly, by importing it inside 
 another module, say, there are additional ways of using this module:
-the top-level buildPackage() function provides a shortcut to the same
+the top-level buildPackage() function provides a shortcut to the same 
 feature and is also called when using this module from the command-
 line.
 
     ****************************************************************
-    NOTE: For now you should be able to run this even on a non-OS X
+    NOTE: For now you should be able to run this even on a non-OS X 
           system and get something similar to a package, but without
-          the real archive (needs pax) and bom files (needs mkbom)
-          inside! This is only for providing a chance for testing to
+          the real archive (needs pax) and bom files (needs mkbom) 
+          inside! This is only for providing a chance for testing to 
           folks without OS X.
     ****************************************************************
 
@@ -39,7 +39,7 @@ TODO:
   - handle multi-volume packages (?)
   - integrate into distutils (?)
 
-Dinu C. Gherman,
+Dinu C. Gherman, 
 gherman@europemail.com
 November 2001
 
@@ -60,7 +60,6 @@ Title
 Version
 Description
 DefaultLocation
-Diskname
 DeleteWarning
 NeedsAuthorization
 DisableStop
@@ -71,6 +70,10 @@ Required
 InstallOnly
 RequiresReboot
 RootVolumeOnly
+LongFilenames
+LibrarySubdirectory
+AllowBackRev
+OverwritePermissions
 InstallFat\
 """
 
@@ -117,14 +120,14 @@ class PackageMaker:
     """A class to generate packages for Mac OS X.
 
     This is intended to create OS X packages (with extension .pkg)
-    containing archives of arbitrary files that the Installer.app
+    containing archives of arbitrary files that the Installer.app 
     will be able to handle.
 
-    As of now, PackageMaker instances need to be created with the
-    title, version and description of the package to be built.
-    The package is built after calling the instance method
-    build(root, **options). It has the same name as the constructor's
-    title argument plus a '.pkg' extension and is located in the same
+    As of now, PackageMaker instances need to be created with the 
+    title, version and description of the package to be built. 
+    The package is built after calling the instance method 
+    build(root, **options). It has the same name as the constructor's 
+    title argument plus a '.pkg' extension and is located in the same 
     parent folder that contains the root folder.
 
     E.g. this will create a package folder /my/space/distutils.pkg/:
@@ -138,7 +141,6 @@ class PackageMaker:
         'Version': None,
         'Description': '',
         'DefaultLocation': '/',
-        'Diskname': '(null)',
         'DeleteWarning': '',
         'NeedsAuthorization': 'NO',
         'DisableStop': 'NO',
@@ -149,7 +151,12 @@ class PackageMaker:
         'InstallOnly': 'NO',
         'RequiresReboot': 'NO',
         'RootVolumeOnly' : 'NO',
-        'InstallFat': 'NO'}
+        'InstallFat': 'NO',
+        'LongFilenames': 'YES',
+        'LibrarySubdirectory': 'Standard',
+        'AllowBackRev': 'YES',
+        'OverwritePermissions': 'NO',
+        }
 
 
     def __init__(self, title, version, desc):
@@ -158,7 +165,7 @@ class PackageMaker:
         info = {"Title": title, "Version": version, "Description": desc}
         self.packageInfo = copy.deepcopy(self.packageInfoDefaults)
         self.packageInfo.update(info)
-
+        
         # variables set later
         self.packageRootFolder = None
         self.packageResourceFolder = None
@@ -169,8 +176,8 @@ class PackageMaker:
     def build(self, root, resources=None, **options):
         """Create a package for some given root folder.
 
-        With no 'resources' argument set it is assumed to be the same
-        as the root directory. Option items replace the default ones
+        With no 'resources' argument set it is assumed to be the same 
+        as the root directory. Option items replace the default ones 
         in the package info.
         """
 
@@ -188,12 +195,12 @@ class PackageMaker:
                 self.packageInfo[k] = v
             elif not k in ["OutputDir"]:
                 raise Error, "Unknown package option: %s" % k
-
+        
         # Check where we should leave the output. Default is current directory
         outputdir = options.get("OutputDir", os.getcwd())
         packageName = self.packageInfo["Title"]
         self.PackageRootFolder = os.path.join(outputdir, packageName + ".pkg")
-
         # do what needs to be done
         self._makeFolders()
         self._addInfo()
@@ -201,13 +208,14 @@ class PackageMaker:
         self._addArchive()
         self._addResources()
         self._addSizes()
+        self._addLoc()
 
 
     def _makeFolders(self):
         "Create package folder structure."
 
         # Not sure if the package name should contain the version or not...
-        # packageName = "%s-%s" % (self.packageInfo["Title"],
+        # packageName = "%s-%s" % (self.packageInfo["Title"], 
         #                          self.packageInfo["Version"]) # ??
 
         contFolder = join(self.PackageRootFolder, "Contents")
@@ -223,7 +231,8 @@ class PackageMaker:
 
         info = ""
         for f in string.split(PKG_INFO_FIELDS, "\n"):
-            info = info + "%s %%(%s)s\n" % (f, f)
+            if self.packageInfo.has_key(f):
+                info = info + "%s %%(%s)s\n" % (f, f)
         info = info % self.packageInfo
         base = self.packageInfo["Title"] + ".info"
         path = join(self.packageResourceFolder, base)
@@ -258,7 +267,7 @@ class PackageMaker:
         self.archPath = join(self.packageResourceFolder, base)
         cmd = "pax -w -f %s %s" % (self.archPath, ".")
         res = os.system(cmd)
-
+        
         # compress archive
         cmd = "gzip %s" % self.archPath
         res = os.system(cmd)
@@ -268,8 +277,8 @@ class PackageMaker:
     def _addResources(self):
         "Add Welcome/ReadMe/License files, .lproj folders and scripts."
 
-        # Currently we just copy everything that matches the allowed
-        # filenames. So, it's left to Installer.app to deal with the
+        # Currently we just copy everything that matches the allowed 
+        # filenames. So, it's left to Installer.app to deal with the 
         # same file available in multiple formats...
 
         if not self.resourceFolder:
@@ -328,9 +337,9 @@ class PackageMaker:
     def _addSizes(self):
         "Write .sizes file with info about number and size of files."
 
-        # Not sure if this is correct, but 'installedSize' and
-        # 'zippedSize' are now in Bytes. Maybe blocks are needed?
-        # Well, Installer.app doesn't seem to care anyway, saying
+        # Not sure if this is correct, but 'installedSize' and 
+        # 'zippedSize' are now in Bytes. Maybe blocks are needed? 
+        # Well, Installer.app doesn't seem to care anyway, saying 
         # the installation needs 100+ MB...
 
         numFiles = 0
@@ -344,19 +353,24 @@ class PackageMaker:
 
         try:
             zippedSize = os.stat(self.archPath+ ".gz")[6]
-        except OSError: # ignore error
+        except OSError: # ignore error 
             pass
         base = self.packageInfo["Title"] + ".sizes"
         f = open(join(self.packageResourceFolder, base), "w")
         format = "NumFiles %d\nInstalledSize %d\nCompressedSize %d\n"
         f.write(format % (numFiles, installedSize, zippedSize))
 
+    def _addLoc(self):
+        "Write .loc file."
+        base = self.packageInfo["Title"] + ".loc"
+        f = open(join(self.packageResourceFolder, base), "w")
+        f.write('/')
 
 # Shortcut function interface
 
 def buildPackage(*args, **options):
     "A Shortcut function for building a package."
-
+    
     o = options
     title, version, desc = o["Title"], o["Version"], o["Description"]
     pm = PackageMaker(title, version, desc)
@@ -377,9 +391,9 @@ def test0():
 def test1():
     "Test for the reportlab distribution with modified options."
 
-    pm = PackageMaker("reportlab", "1.10",
+    pm = PackageMaker("reportlab", "1.10", 
                       "ReportLab's Open Source PDF toolkit.")
-    pm.build(root="/Users/dinu/Desktop/reportlab",
+    pm.build(root="/Users/dinu/Desktop/reportlab", 
              DefaultLocation="/Applications/ReportLab",
              Relocatable="YES")
 
@@ -387,9 +401,9 @@ def test2():
     "Shortcut test for the reportlab distribution with modified options."
 
     buildPackage(
-        "/Users/dinu/Desktop/reportlab",
-        Title="reportlab",
-        Version="1.10",
+        "/Users/dinu/Desktop/reportlab", 
+        Title="reportlab", 
+        Version="1.10", 
         Description="ReportLab's Open Source PDF toolkit.",
         DefaultLocation="/Applications/ReportLab",
         Relocatable="YES")
index ac810440b5f611d60ac68dea673ec9524e8138db..09b9deae4a5a6aab1302dabb36b908d542b67a85 100644 (file)
@@ -42,173 +42,178 @@ class BundleBuilderError(Exception): pass
 
 class Defaults:
 
-       """Class attributes that don't start with an underscore and are
-       not functions or classmethods are (deep)copied to self.__dict__.
-       This allows for mutable default values.
-       """
-
-       def __init__(self, **kwargs):
-               defaults = self._getDefaults()
-               defaults.update(kwargs)
-               self.__dict__.update(defaults)
-
-       def _getDefaults(cls):
-               defaults = {}
-               for name, value in cls.__dict__.items():
-                       if name[0] != "_" and not isinstance(value,
-                                       (function, classmethod)):
-                               defaults[name] = deepcopy(value)
-               for base in cls.__bases__:
-                       if hasattr(base, "_getDefaults"):
-                               defaults.update(base._getDefaults())
-               return defaults
-       _getDefaults = classmethod(_getDefaults)
+    """Class attributes that don't start with an underscore and are
+    not functions or classmethods are (deep)copied to self.__dict__.
+    This allows for mutable default values.
+    """
+
+    def __init__(self, **kwargs):
+        defaults = self._getDefaults()
+        defaults.update(kwargs)
+        self.__dict__.update(defaults)
+
+    def _getDefaults(cls):
+        defaults = {}
+        for base in cls.__bases__:
+            if hasattr(base, "_getDefaults"):
+                defaults.update(base._getDefaults())
+        for name, value in cls.__dict__.items():
+            if name[0] != "_" and not isinstance(value,
+                    (function, classmethod)):
+                defaults[name] = deepcopy(value)
+        return defaults
+    _getDefaults = classmethod(_getDefaults)
 
 
 class BundleBuilder(Defaults):
 
-       """BundleBuilder is a barebones class for assembling bundles. It
-       knows nothing about executables or icons, it only copies files
-       and creates the PkgInfo and Info.plist files.
-       """
-
-       # (Note that Defaults.__init__ (deep)copies these values to
-       # instance variables. Mutable defaults are therefore safe.)
-
-       # Name of the bundle, with or without extension.
-       name = None
-
-       # The property list ("plist")
-       plist = Plist(CFBundleDevelopmentRegion = "English",
-                     CFBundleInfoDictionaryVersion = "6.0")
-
-       # The type of the bundle.
-       type = "BNDL"
-       # The creator code of the bundle.
-       creator = None
-
-       # List of files that have to be copied to <bundle>/Contents/Resources.
-       resources = []
-
-       # List of (src, dest) tuples; dest should be a path relative to the bundle
-       # (eg. "Contents/Resources/MyStuff/SomeFile.ext).
-       files = []
-
-       # List of shared libraries (dylibs, Frameworks) to bundle with the app
-       # will be placed in Contents/Frameworks
-       libs = []
-
-       # Directory where the bundle will be assembled.
-       builddir = "build"
-
-       # Make symlinks instead copying files. This is handy during debugging, but
-       # makes the bundle non-distributable.
-       symlink = 0
-
-       # Verbosity level.
-       verbosity = 1
-
-       def setup(self):
-               # XXX rethink self.name munging, this is brittle.
-               self.name, ext = os.path.splitext(self.name)
-               if not ext:
-                       ext = ".bundle"
-               bundleextension = ext
-               # misc (derived) attributes
-               self.bundlepath = pathjoin(self.builddir, self.name + bundleextension)
-
-               plist = self.plist
-               plist.CFBundleName = self.name
-               plist.CFBundlePackageType = self.type
-               if self.creator is None:
-                       if hasattr(plist, "CFBundleSignature"):
-                               self.creator = plist.CFBundleSignature
-                       else:
-                               self.creator = "????"
-               plist.CFBundleSignature = self.creator
-               if not hasattr(plist, "CFBundleIdentifier"):
-                       plist.CFBundleIdentifier = self.name
-
-       def build(self):
-               """Build the bundle."""
-               builddir = self.builddir
-               if builddir and not os.path.exists(builddir):
-                       os.mkdir(builddir)
-               self.message("Building %s" % repr(self.bundlepath), 1)
-               if os.path.exists(self.bundlepath):
-                       shutil.rmtree(self.bundlepath)
-               os.mkdir(self.bundlepath)
-               self.preProcess()
-               self._copyFiles()
-               self._addMetaFiles()
-               self.postProcess()
-               self.message("Done.", 1)
-
-       def preProcess(self):
-               """Hook for subclasses."""
-               pass
-       def postProcess(self):
-               """Hook for subclasses."""
-               pass
-
-       def _addMetaFiles(self):
-               contents = pathjoin(self.bundlepath, "Contents")
-               makedirs(contents)
-               #
-               # Write Contents/PkgInfo
-               assert len(self.type) == len(self.creator) == 4, \
-                               "type and creator must be 4-byte strings."
-               pkginfo = pathjoin(contents, "PkgInfo")
-               f = open(pkginfo, "wb")
-               f.write(self.type + self.creator)
-               f.close()
-               #
-               # Write Contents/Info.plist
-               infoplist = pathjoin(contents, "Info.plist")
-               self.plist.write(infoplist)
-
-       def _copyFiles(self):
-               files = self.files[:]
-               for path in self.resources:
-                       files.append((path, pathjoin("Contents", "Resources",
-                               os.path.basename(path))))
-               for path in self.libs:
-                       files.append((path, pathjoin("Contents", "Frameworks",
-                               os.path.basename(path))))
-               if self.symlink:
-                       self.message("Making symbolic links", 1)
-                       msg = "Making symlink from"
-               else:
-                       self.message("Copying files", 1)
-                       msg = "Copying"
-               files.sort()
-               for src, dst in files:
-                       if os.path.isdir(src):
-                               self.message("%s %s/ to %s/" % (msg, src, dst), 2)
-                       else:
-                               self.message("%s %s to %s" % (msg, src, dst), 2)
-                       dst = pathjoin(self.bundlepath, dst)
-                       if self.symlink:
-                               symlink(src, dst, mkdirs=1)
-                       else:
-                               copy(src, dst, mkdirs=1)
-
-       def message(self, msg, level=0):
-               if level <= self.verbosity:
-                       indent = ""
-                       if level > 1:
-                               indent = (level - 1) * "  "
-                       sys.stderr.write(indent + msg + "\n")
-
-       def report(self):
-               # XXX something decent
-               pass
+    """BundleBuilder is a barebones class for assembling bundles. It
+    knows nothing about executables or icons, it only copies files
+    and creates the PkgInfo and Info.plist files.
+    """
+
+    # (Note that Defaults.__init__ (deep)copies these values to
+    # instance variables. Mutable defaults are therefore safe.)
+
+    # Name of the bundle, with or without extension.
+    name = None
+
+    # The property list ("plist")
+    plist = Plist(CFBundleDevelopmentRegion = "English",
+                  CFBundleInfoDictionaryVersion = "6.0")
+
+    # The type of the bundle.
+    type = "BNDL"
+    # The creator code of the bundle.
+    creator = None
+
+    # the CFBundleIdentifier (this is used for the preferences file name)
+    bundle_id = None
+
+    # List of files that have to be copied to <bundle>/Contents/Resources.
+    resources = []
+
+    # List of (src, dest) tuples; dest should be a path relative to the bundle
+    # (eg. "Contents/Resources/MyStuff/SomeFile.ext).
+    files = []
+
+    # List of shared libraries (dylibs, Frameworks) to bundle with the app
+    # will be placed in Contents/Frameworks
+    libs = []
+
+    # Directory where the bundle will be assembled.
+    builddir = "build"
+
+    # Make symlinks instead copying files. This is handy during debugging, but
+    # makes the bundle non-distributable.
+    symlink = 0
+
+    # Verbosity level.
+    verbosity = 1
+
+    def setup(self):
+        # XXX rethink self.name munging, this is brittle.
+        self.name, ext = os.path.splitext(self.name)
+        if not ext:
+            ext = ".bundle"
+        bundleextension = ext
+        # misc (derived) attributes
+        self.bundlepath = pathjoin(self.builddir, self.name + bundleextension)
+
+        plist = self.plist
+        plist.CFBundleName = self.name
+        plist.CFBundlePackageType = self.type
+        if self.creator is None:
+            if hasattr(plist, "CFBundleSignature"):
+                self.creator = plist.CFBundleSignature
+            else:
+                self.creator = "????"
+        plist.CFBundleSignature = self.creator
+        if self.bundle_id:
+            plist.CFBundleIdentifier = self.bundle_id
+        elif not hasattr(plist, "CFBundleIdentifier"):
+            plist.CFBundleIdentifier = self.name
+
+    def build(self):
+        """Build the bundle."""
+        builddir = self.builddir
+        if builddir and not os.path.exists(builddir):
+            os.mkdir(builddir)
+        self.message("Building %s" % repr(self.bundlepath), 1)
+        if os.path.exists(self.bundlepath):
+            shutil.rmtree(self.bundlepath)
+        os.mkdir(self.bundlepath)
+        self.preProcess()
+        self._copyFiles()
+        self._addMetaFiles()
+        self.postProcess()
+        self.message("Done.", 1)
+
+    def preProcess(self):
+        """Hook for subclasses."""
+        pass
+    def postProcess(self):
+        """Hook for subclasses."""
+        pass
+
+    def _addMetaFiles(self):
+        contents = pathjoin(self.bundlepath, "Contents")
+        makedirs(contents)
+        #
+        # Write Contents/PkgInfo
+        assert len(self.type) == len(self.creator) == 4, \
+                "type and creator must be 4-byte strings."
+        pkginfo = pathjoin(contents, "PkgInfo")
+        f = open(pkginfo, "wb")
+        f.write(self.type + self.creator)
+        f.close()
+        #
+        # Write Contents/Info.plist
+        infoplist = pathjoin(contents, "Info.plist")
+        self.plist.write(infoplist)
+
+    def _copyFiles(self):
+        files = self.files[:]
+        for path in self.resources:
+            files.append((path, pathjoin("Contents", "Resources",
+                os.path.basename(path))))
+        for path in self.libs:
+            files.append((path, pathjoin("Contents", "Frameworks",
+                os.path.basename(path))))
+        if self.symlink:
+            self.message("Making symbolic links", 1)
+            msg = "Making symlink from"
+        else:
+            self.message("Copying files", 1)
+            msg = "Copying"
+        files.sort()
+        for src, dst in files:
+            if os.path.isdir(src):
+                self.message("%s %s/ to %s/" % (msg, src, dst), 2)
+            else:
+                self.message("%s %s to %s" % (msg, src, dst), 2)
+            dst = pathjoin(self.bundlepath, dst)
+            if self.symlink:
+                symlink(src, dst, mkdirs=1)
+            else:
+                copy(src, dst, mkdirs=1)
+
+    def message(self, msg, level=0):
+        if level <= self.verbosity:
+            indent = ""
+            if level > 1:
+                indent = (level - 1) * "  "
+            sys.stderr.write(indent + msg + "\n")
+
+    def report(self):
+        # XXX something decent
+        pass
 
 
 if __debug__:
-       PYC_EXT = ".pyc"
+    PYC_EXT = ".pyc"
 else:
-       PYC_EXT = ".pyo"
+    PYC_EXT = ".pyo"
 
 MAGIC = imp.get_magic()
 USE_ZIPIMPORT = "zipimport" in sys.builtin_module_names
@@ -217,19 +222,18 @@ USE_ZIPIMPORT = "zipimport" in sys.builtin_module_names
 # all the cruft of the real site.py.
 SITE_PY = """\
 import sys
-del sys.path[1:]  # sys.path[0] is Contents/Resources/
+if not %(semi_standalone)s:
+    del sys.path[1:]  # sys.path[0] is Contents/Resources/
 """
 
 if USE_ZIPIMPORT:
-       ZIP_ARCHIVE = "Modules.zip"
-       SITE_PY += "sys.path.append(sys.path[0] + '/%s')\n" % ZIP_ARCHIVE
-       def getPycData(fullname, code, ispkg):
-               if ispkg:
-                       fullname += ".__init__"
-               path = fullname.replace(".", os.sep) + PYC_EXT
-               return path, MAGIC + '\0\0\0\0' + marshal.dumps(code)
-
-SITE_CO = compile(SITE_PY, "<-bundlebuilder.py->", "exec")
+    ZIP_ARCHIVE = "Modules.zip"
+    SITE_PY += "sys.path.append(sys.path[0] + '/%s')\n" % ZIP_ARCHIVE
+    def getPycData(fullname, code, ispkg):
+        if ispkg:
+            fullname += ".__init__"
+        path = fullname.replace(".", os.sep) + PYC_EXT
+        return path, MAGIC + '\0\0\0\0' + marshal.dumps(code)
 
 #
 # Extension modules can't be in the modules zip archive, so a placeholder
@@ -237,22 +241,22 @@ SITE_CO = compile(SITE_PY, "<-bundlebuilder.py->", "exec")
 #
 EXT_LOADER = """\
 def __load():
-       import imp, sys, os
-       for p in sys.path:
-               path = os.path.join(p, "%(filename)s")
-               if os.path.exists(path):
-                       break
-       else:
-               assert 0, "file not found: %(filename)s"
-       mod = imp.load_dynamic("%(name)s", path)
+    import imp, sys, os
+    for p in sys.path:
+        path = os.path.join(p, "%(filename)s")
+        if os.path.exists(path):
+            break
+    else:
+        assert 0, "file not found: %(filename)s"
+    mod = imp.load_dynamic("%(name)s", path)
 
 __load()
 del __load
 """
 
 MAYMISS_MODULES = ['mac', 'os2', 'nt', 'ntpath', 'dos', 'dospath',
-       'win32api', 'ce', '_winreg', 'nturl2path', 'sitecustomize',
-       'org.python.core', 'riscos', 'riscosenviron', 'riscospath'
+    'win32api', 'ce', '_winreg', 'nturl2path', 'sitecustomize',
+    'org.python.core', 'riscos', 'riscosenviron', 'riscospath'
 ]
 
 STRIP_EXEC = "/usr/bin/strip"
@@ -279,10 +283,18 @@ libdir = os.path.join(os.path.dirname(execdir), "Frameworks")
 mainprogram = os.path.join(resdir, "%(mainprogram)s")
 
 sys.argv.insert(1, mainprogram)
-os.environ["PYTHONPATH"] = resdir
-%(pythonhome)s
+if %(standalone)s or %(semi_standalone)s:
+    os.environ["PYTHONPATH"] = resdir
+    if %(standalone)s:
+        os.environ["PYTHONHOME"] = resdir
+else:
+    pypath = os.getenv("PYTHONPATH", "")
+    if pypath:
+        pypath = ":" + pypath
+    os.environ["PYTHONPATH"] = resdir + pypath
 os.environ["PYTHONEXECUTABLE"] = executable
 os.environ["DYLD_LIBRARY_PATH"] = libdir
+os.environ["DYLD_FRAMEWORK_PATH"] = libdir
 os.execve(executable, sys.argv, os.environ)
 """
 
@@ -297,318 +309,393 @@ argvemulator.ArgvCollector().mainloop()
 execfile(os.path.join(os.path.split(__file__)[0], "%(realmainprogram)s"))
 """
 
+#
+# When building a standalone app with Python.framework, we need to copy
+# a subset from Python.framework to the bundle. The following list
+# specifies exactly what items we'll copy.
+#
+PYTHONFRAMEWORKGOODIES = [
+    "Python",  # the Python core library
+    "Resources/English.lproj",
+    "Resources/Info.plist",
+    "Resources/version.plist",
+]
+
+def isFramework():
+    return sys.exec_prefix.find("Python.framework") > 0
+
+
+LIB = os.path.join(sys.prefix, "lib", "python" + sys.version[:3])
+SITE_PACKAGES = os.path.join(LIB, "site-packages")
+
 
 class AppBuilder(BundleBuilder):
 
-       # Override type of the bundle.
-       type = "APPL"
+    # Override type of the bundle.
+    type = "APPL"
+
+    # platform, name of the subfolder of Contents that contains the executable.
+    platform = "MacOS"
+
+    # A Python main program. If this argument is given, the main
+    # executable in the bundle will be a small wrapper that invokes
+    # the main program. (XXX Discuss why.)
+    mainprogram = None
 
-       # platform, name of the subfolder of Contents that contains the executable.
-       platform = "MacOS"
+    # The main executable. If a Python main program is specified
+    # the executable will be copied to Resources and be invoked
+    # by the wrapper program mentioned above. Otherwise it will
+    # simply be used as the main executable.
+    executable = None
 
-       # A Python main program. If this argument is given, the main
-       # executable in the bundle will be a small wrapper that invokes
-       # the main program. (XXX Discuss why.)
-       mainprogram = None
-
-       # The main executable. If a Python main program is specified
-       # the executable will be copied to Resources and be invoked
-       # by the wrapper program mentioned above. Otherwise it will
-       # simply be used as the main executable.
-       executable = None
-
-       # The name of the main nib, for Cocoa apps. *Must* be specified
-       # when building a Cocoa app.
-       nibname = None
-
-       # The name of the icon file to be copied to Resources and used for
-       # the Finder icon.
-       iconfile = None
-
-       # Symlink the executable instead of copying it.
-       symlink_exec = 0
-
-       # If True, build standalone app.
-       standalone = 0
-
-       # If True, add a real main program that emulates sys.argv before calling
-       # mainprogram
-       argv_emulation = 0
-
-       # The following attributes are only used when building a standalone app.
-
-       # Exclude these modules.
-       excludeModules = []
-
-       # Include these modules.
-       includeModules = []
-
-       # Include these packages.
-       includePackages = []
-
-       # Strip binaries.
-       strip = 0
-
-       # Found Python modules: [(name, codeobject, ispkg), ...]
-       pymodules = []
-
-       # Modules that modulefinder couldn't find:
-       missingModules = []
-       maybeMissingModules = []
-
-       # List of all binaries (executables or shared libs), for stripping purposes
-       binaries = []
-
-       def setup(self):
-               if self.standalone and self.mainprogram is None:
-                       raise BundleBuilderError, ("must specify 'mainprogram' when "
-                                       "building a standalone application.")
-               if self.mainprogram is None and self.executable is None:
-                       raise BundleBuilderError, ("must specify either or both of "
-                                       "'executable' and 'mainprogram'")
-
-               self.execdir = pathjoin("Contents", self.platform)
-
-               if self.name is not None:
-                       pass
-               elif self.mainprogram is not None:
-                       self.name = os.path.splitext(os.path.basename(self.mainprogram))[0]
-               elif executable is not None:
-                       self.name = os.path.splitext(os.path.basename(self.executable))[0]
-               if self.name[-4:] != ".app":
-                       self.name += ".app"
-
-               if self.executable is None:
-                       if not self.standalone:
-                               self.symlink_exec = 1
-                       self.executable = sys.executable
-
-               if self.nibname:
-                       self.plist.NSMainNibFile = self.nibname
-                       if not hasattr(self.plist, "NSPrincipalClass"):
-                               self.plist.NSPrincipalClass = "NSApplication"
-
-               BundleBuilder.setup(self)
-
-               self.plist.CFBundleExecutable = self.name
-
-               if self.standalone:
-                       self.findDependencies()
-
-       def preProcess(self):
-               resdir = "Contents/Resources"
-               if self.executable is not None:
-                       if self.mainprogram is None:
-                               execname = self.name
-                       else:
-                               execname = os.path.basename(self.executable)
-                       execpath = pathjoin(self.execdir, execname)
-                       if not self.symlink_exec:
-                               self.files.append((self.executable, execpath))
-                               self.binaries.append(execpath)
-                       self.execpath = execpath
-
-               if self.mainprogram is not None:
-                       mainprogram = os.path.basename(self.mainprogram)
-                       self.files.append((self.mainprogram, pathjoin(resdir, mainprogram)))
-                       if self.argv_emulation:
-                               # Change the main program, and create the helper main program (which
-                               # does argv collection and then calls the real main).
-                               # Also update the included modules (if we're creating a standalone
-                               # program) and the plist
-                               realmainprogram = mainprogram
-                               mainprogram = '__argvemulator_' + mainprogram
-                               resdirpath = pathjoin(self.bundlepath, resdir)
-                               mainprogrampath = pathjoin(resdirpath, mainprogram)
-                               makedirs(resdirpath)
-                               open(mainprogrampath, "w").write(ARGV_EMULATOR % locals())
-                               if self.standalone:
-                                       self.includeModules.append("argvemulator")
-                                       self.includeModules.append("os")
-                               if not self.plist.has_key("CFBundleDocumentTypes"):
-                                       self.plist["CFBundleDocumentTypes"] = [
-                                               { "CFBundleTypeOSTypes" : [
-                                                       "****",
-                                                       "fold",
-                                                       "disk"],
-                                                 "CFBundleTypeRole": "Viewer"}]
-                       # Write bootstrap script
-                       executable = os.path.basename(self.executable)
-                       execdir = pathjoin(self.bundlepath, self.execdir)
-                       bootstrappath = pathjoin(execdir, self.name)
-                       makedirs(execdir)
-                       if self.standalone:
-                               # XXX we're screwed when the end user has deleted
-                               # /usr/bin/python
-                               hashbang = "/usr/bin/python"
-                                pythonhome = 'os.environ["PYTHONHOME"] = resdir'
-                       else:
-                               hashbang = sys.executable
-                               while os.path.islink(hashbang):
-                                       hashbang = os.readlink(hashbang)
-                                pythonhome = ''
-                       open(bootstrappath, "w").write(BOOTSTRAP_SCRIPT % locals())
-                       os.chmod(bootstrappath, 0775)
-
-               if self.iconfile is not None:
-                       iconbase = os.path.basename(self.iconfile)
-                       self.plist.CFBundleIconFile = iconbase
-                       self.files.append((self.iconfile, pathjoin(resdir, iconbase)))
-
-       def postProcess(self):
-               if self.standalone:
-                       self.addPythonModules()
-               if self.strip and not self.symlink:
-                       self.stripBinaries()
-
-               if self.symlink_exec and self.executable:
-                       self.message("Symlinking executable %s to %s" % (self.executable,
-                                       self.execpath), 2)
-                       dst = pathjoin(self.bundlepath, self.execpath)
-                       makedirs(os.path.dirname(dst))
-                       os.symlink(os.path.abspath(self.executable), dst)
-
-               if self.missingModules or self.maybeMissingModules:
-                       self.reportMissing()
-
-       def addPythonModules(self):
-               self.message("Adding Python modules", 1)
-
-               if USE_ZIPIMPORT:
-                       # Create a zip file containing all modules as pyc.
-                       import zipfile
-                       relpath = pathjoin("Contents", "Resources", ZIP_ARCHIVE)
-                       abspath = pathjoin(self.bundlepath, relpath)
-                       zf = zipfile.ZipFile(abspath, "w", zipfile.ZIP_DEFLATED)
-                       for name, code, ispkg in self.pymodules:
-                               self.message("Adding Python module %s" % name, 2)
-                               path, pyc = getPycData(name, code, ispkg)
-                               zf.writestr(path, pyc)
-                       zf.close()
-                       # add site.pyc
-                       sitepath = pathjoin(self.bundlepath, "Contents", "Resources",
-                                       "site" + PYC_EXT)
-                       writePyc(SITE_CO, sitepath)
-               else:
-                       # Create individual .pyc files.
-                       for name, code, ispkg in self.pymodules:
-                               if ispkg:
-                                       name += ".__init__"
-                               path = name.split(".")
-                               path = pathjoin("Contents", "Resources", *path) + PYC_EXT
-
-                               if ispkg:
-                                       self.message("Adding Python package %s" % path, 2)
-                               else:
-                                       self.message("Adding Python module %s" % path, 2)
-
-                               abspath = pathjoin(self.bundlepath, path)
-                               makedirs(os.path.dirname(abspath))
-                               writePyc(code, abspath)
-
-       def stripBinaries(self):
-               if not os.path.exists(STRIP_EXEC):
-                       self.message("Error: can't strip binaries: no strip program at "
-                               "%s" % STRIP_EXEC, 0)
-               else:
-                       self.message("Stripping binaries", 1)
-                       for relpath in self.binaries:
-                               self.message("Stripping %s" % relpath, 2)
-                               abspath = pathjoin(self.bundlepath, relpath)
-                               assert not os.path.islink(abspath)
-                               rv = os.system("%s -S \"%s\"" % (STRIP_EXEC, abspath))
-
-       def findDependencies(self):
-               self.message("Finding module dependencies", 1)
-               import modulefinder
-               mf = modulefinder.ModuleFinder(excludes=self.excludeModules)
-               if USE_ZIPIMPORT:
-                       # zipimport imports zlib, must add it manually
-                       mf.import_hook("zlib")
-               # manually add our own site.py
-               site = mf.add_module("site")
-               site.__code__ = SITE_CO
-               mf.scan_code(SITE_CO, site)
-
-               # warnings.py gets imported implicitly from C
-               mf.import_hook("warnings")
-
-               includeModules = self.includeModules[:]
-               for name in self.includePackages:
-                       includeModules.extend(findPackageContents(name).keys())
-               for name in includeModules:
-                       try:
-                               mf.import_hook(name)
-                       except ImportError:
-                               self.missingModules.append(name)
-
-               mf.run_script(self.mainprogram)
-               modules = mf.modules.items()
-               modules.sort()
-               for name, mod in modules:
-                       if mod.__file__ and mod.__code__ is None:
-                               # C extension
-                               path = mod.__file__
-                               filename = os.path.basename(path)
-                               if USE_ZIPIMPORT:
-                                       # Python modules are stored in a Zip archive, but put
-                                       # extensions in Contents/Resources/.a and add a tiny "loader"
-                                       # program in the Zip archive. Due to Thomas Heller.
-                                       dstpath = pathjoin("Contents", "Resources", filename)
-                                       source = EXT_LOADER % {"name": name, "filename": filename}
-                                       code = compile(source, "<dynloader for %s>" % name, "exec")
-                                       mod.__code__ = code
-                               else:
-                                       # just copy the file
-                                       dstpath = name.split(".")[:-1] + [filename]
-                                       dstpath = pathjoin("Contents", "Resources", *dstpath)
-                               self.files.append((path, dstpath))
-                               self.binaries.append(dstpath)
-                       if mod.__code__ is not None:
-                               ispkg = mod.__path__ is not None
-                               if not USE_ZIPIMPORT or name != "site":
-                                       # Our site.py is doing the bootstrapping, so we must
-                                       # include a real .pyc file if USE_ZIPIMPORT is True.
-                                       self.pymodules.append((name, mod.__code__, ispkg))
-
-               if hasattr(mf, "any_missing_maybe"):
-                       missing, maybe = mf.any_missing_maybe()
-               else:
-                       missing = mf.any_missing()
-                       maybe = []
-               self.missingModules.extend(missing)
-               self.maybeMissingModules.extend(maybe)
-
-       def reportMissing(self):
-               missing = [name for name in self.missingModules
-                               if name not in MAYMISS_MODULES]
-               if self.maybeMissingModules:
-                       maybe = self.maybeMissingModules
-               else:
-                       maybe = [name for name in missing if "." in name]
-                       missing = [name for name in missing if "." not in name]
-               missing.sort()
-               maybe.sort()
-               if maybe:
-                       self.message("Warning: couldn't find the following submodules:", 1)
-                       self.message("    (Note that these could be false alarms -- "
-                                    "it's not always", 1)
-                       self.message("    possible to distinguish between \"from package "
-                                    "import submodule\" ", 1)
-                       self.message("    and \"from package import name\")", 1)
-                       for name in maybe:
-                               self.message("  ? " + name, 1)
-               if missing:
-                       self.message("Warning: couldn't find the following modules:", 1)
-                       for name in missing:
-                               self.message("  ? " + name, 1)
-
-       def report(self):
-               # XXX something decent
-               import pprint
-               pprint.pprint(self.__dict__)
-               if self.standalone:
-                       self.reportMissing()
+    # The name of the main nib, for Cocoa apps. *Must* be specified
+    # when building a Cocoa app.
+    nibname = None
+
+    # The name of the icon file to be copied to Resources and used for
+    # the Finder icon.
+    iconfile = None
+
+    # Symlink the executable instead of copying it.
+    symlink_exec = 0
+
+    # If True, build standalone app.
+    standalone = 0
+
+    # If True, build semi-standalone app (only includes third-party modules).
+    semi_standalone = 0
+
+    # If set, use this for #! lines in stead of sys.executable
+    python = None
+
+    # If True, add a real main program that emulates sys.argv before calling
+    # mainprogram
+    argv_emulation = 0
+
+    # The following attributes are only used when building a standalone app.
+
+    # Exclude these modules.
+    excludeModules = []
+
+    # Include these modules.
+    includeModules = []
+
+    # Include these packages.
+    includePackages = []
+
+    # Strip binaries from debug info.
+    strip = 0
+
+    # Found Python modules: [(name, codeobject, ispkg), ...]
+    pymodules = []
+
+    # Modules that modulefinder couldn't find:
+    missingModules = []
+    maybeMissingModules = []
+
+    def setup(self):
+        if ((self.standalone or self.semi_standalone)
+            and self.mainprogram is None):
+            raise BundleBuilderError, ("must specify 'mainprogram' when "
+                    "building a standalone application.")
+        if self.mainprogram is None and self.executable is None:
+            raise BundleBuilderError, ("must specify either or both of "
+                    "'executable' and 'mainprogram'")
+
+        self.execdir = pathjoin("Contents", self.platform)
+
+        if self.name is not None:
+            pass
+        elif self.mainprogram is not None:
+            self.name = os.path.splitext(os.path.basename(self.mainprogram))[0]
+        elif executable is not None:
+            self.name = os.path.splitext(os.path.basename(self.executable))[0]
+        if self.name[-4:] != ".app":
+            self.name += ".app"
+
+        if self.executable is None:
+            if not self.standalone and not isFramework():
+                self.symlink_exec = 1
+            if self.python:
+                self.executable = self.python
+            else:
+                self.executable = sys.executable
+
+        if self.nibname:
+            self.plist.NSMainNibFile = self.nibname
+            if not hasattr(self.plist, "NSPrincipalClass"):
+                self.plist.NSPrincipalClass = "NSApplication"
+
+        if self.standalone and isFramework():
+            self.addPythonFramework()
+
+        BundleBuilder.setup(self)
+
+        self.plist.CFBundleExecutable = self.name
+
+        if self.standalone or self.semi_standalone:
+            self.findDependencies()
+
+    def preProcess(self):
+        resdir = "Contents/Resources"
+        if self.executable is not None:
+            if self.mainprogram is None:
+                execname = self.name
+            else:
+                execname = os.path.basename(self.executable)
+            execpath = pathjoin(self.execdir, execname)
+            if not self.symlink_exec:
+                self.files.append((self.executable, execpath))
+            self.execpath = execpath
+
+        if self.mainprogram is not None:
+            mainprogram = os.path.basename(self.mainprogram)
+            self.files.append((self.mainprogram, pathjoin(resdir, mainprogram)))
+            if self.argv_emulation:
+                # Change the main program, and create the helper main program (which
+                # does argv collection and then calls the real main).
+                # Also update the included modules (if we're creating a standalone
+                # program) and the plist
+                realmainprogram = mainprogram
+                mainprogram = '__argvemulator_' + mainprogram
+                resdirpath = pathjoin(self.bundlepath, resdir)
+                mainprogrampath = pathjoin(resdirpath, mainprogram)
+                makedirs(resdirpath)
+                open(mainprogrampath, "w").write(ARGV_EMULATOR % locals())
+                if self.standalone or self.semi_standalone:
+                    self.includeModules.append("argvemulator")
+                    self.includeModules.append("os")
+                if not self.plist.has_key("CFBundleDocumentTypes"):
+                    self.plist["CFBundleDocumentTypes"] = [
+                        { "CFBundleTypeOSTypes" : [
+                            "****",
+                            "fold",
+                            "disk"],
+                          "CFBundleTypeRole": "Viewer"}]
+            # Write bootstrap script
+            executable = os.path.basename(self.executable)
+            execdir = pathjoin(self.bundlepath, self.execdir)
+            bootstrappath = pathjoin(execdir, self.name)
+            makedirs(execdir)
+            if self.standalone or self.semi_standalone:
+                # XXX we're screwed when the end user has deleted
+                # /usr/bin/python
+                hashbang = "/usr/bin/python"
+            elif self.python:
+                hashbang = self.python
+            else:
+                hashbang = os.path.realpath(sys.executable)
+            standalone = self.standalone
+            semi_standalone = self.semi_standalone
+            open(bootstrappath, "w").write(BOOTSTRAP_SCRIPT % locals())
+            os.chmod(bootstrappath, 0775)
+
+        if self.iconfile is not None:
+            iconbase = os.path.basename(self.iconfile)
+            self.plist.CFBundleIconFile = iconbase
+            self.files.append((self.iconfile, pathjoin(resdir, iconbase)))
+
+    def postProcess(self):
+        if self.standalone or self.semi_standalone:
+            self.addPythonModules()
+        if self.strip and not self.symlink:
+            self.stripBinaries()
+
+        if self.symlink_exec and self.executable:
+            self.message("Symlinking executable %s to %s" % (self.executable,
+                    self.execpath), 2)
+            dst = pathjoin(self.bundlepath, self.execpath)
+            makedirs(os.path.dirname(dst))
+            os.symlink(os.path.abspath(self.executable), dst)
+
+        if self.missingModules or self.maybeMissingModules:
+            self.reportMissing()
+
+    def addPythonFramework(self):
+        # If we're building a standalone app with Python.framework,
+        # include a minimal subset of Python.framework, *unless*
+        # Python.framework was specified manually in self.libs.
+        for lib in self.libs:
+            if os.path.basename(lib) == "Python.framework":
+                # a Python.framework was specified as a library
+                return
+
+        frameworkpath = sys.exec_prefix[:sys.exec_prefix.find(
+            "Python.framework") + len("Python.framework")]
+
+        version = sys.version[:3]
+        frameworkpath = pathjoin(frameworkpath, "Versions", version)
+        destbase = pathjoin("Contents", "Frameworks", "Python.framework",
+                            "Versions", version)
+        for item in PYTHONFRAMEWORKGOODIES:
+            src = pathjoin(frameworkpath, item)
+            dst = pathjoin(destbase, item)
+            self.files.append((src, dst))
+
+    def _getSiteCode(self):
+        return compile(SITE_PY % {"semi_standalone": self.semi_standalone},
+                     "<-bundlebuilder.py->", "exec")
+
+    def addPythonModules(self):
+        self.message("Adding Python modules", 1)
+
+        if USE_ZIPIMPORT:
+            # Create a zip file containing all modules as pyc.
+            import zipfile
+            relpath = pathjoin("Contents", "Resources", ZIP_ARCHIVE)
+            abspath = pathjoin(self.bundlepath, relpath)
+            zf = zipfile.ZipFile(abspath, "w", zipfile.ZIP_DEFLATED)
+            for name, code, ispkg in self.pymodules:
+                self.message("Adding Python module %s" % name, 2)
+                path, pyc = getPycData(name, code, ispkg)
+                zf.writestr(path, pyc)
+            zf.close()
+            # add site.pyc
+            sitepath = pathjoin(self.bundlepath, "Contents", "Resources",
+                    "site" + PYC_EXT)
+            writePyc(self._getSiteCode(), sitepath)
+        else:
+            # Create individual .pyc files.
+            for name, code, ispkg in self.pymodules:
+                if ispkg:
+                    name += ".__init__"
+                path = name.split(".")
+                path = pathjoin("Contents", "Resources", *path) + PYC_EXT
+
+                if ispkg:
+                    self.message("Adding Python package %s" % path, 2)
+                else:
+                    self.message("Adding Python module %s" % path, 2)
+
+                abspath = pathjoin(self.bundlepath, path)
+                makedirs(os.path.dirname(abspath))
+                writePyc(code, abspath)
+
+    def stripBinaries(self):
+        if not os.path.exists(STRIP_EXEC):
+            self.message("Error: can't strip binaries: no strip program at "
+                "%s" % STRIP_EXEC, 0)
+        else:
+            import stat
+            self.message("Stripping binaries", 1)
+            def walk(top):
+                for name in os.listdir(top):
+                    path = pathjoin(top, name)
+                    if os.path.islink(path):
+                        continue
+                    if os.path.isdir(path):
+                        walk(path)
+                    else:
+                        mod = os.stat(path)[stat.ST_MODE]
+                        if not (mod & 0100):
+                            continue
+                        relpath = path[len(self.bundlepath):]
+                        self.message("Stripping %s" % relpath, 2)
+                        inf, outf = os.popen4("%s -S \"%s\"" %
+                                              (STRIP_EXEC, path))
+                        output = outf.read().strip()
+                        if output:
+                            # usually not a real problem, like when we're
+                            # trying to strip a script
+                            self.message("Problem stripping %s:" % relpath, 3)
+                            self.message(output, 3)
+            walk(self.bundlepath)
+
+    def findDependencies(self):
+        self.message("Finding module dependencies", 1)
+        import modulefinder
+        mf = modulefinder.ModuleFinder(excludes=self.excludeModules)
+        if USE_ZIPIMPORT:
+            # zipimport imports zlib, must add it manually
+            mf.import_hook("zlib")
+        # manually add our own site.py
+        site = mf.add_module("site")
+        site.__code__ = self._getSiteCode()
+        mf.scan_code(site.__code__, site)
+
+        # warnings.py gets imported implicitly from C
+        mf.import_hook("warnings")
+
+        includeModules = self.includeModules[:]
+        for name in self.includePackages:
+            includeModules.extend(findPackageContents(name).keys())
+        for name in includeModules:
+            try:
+                mf.import_hook(name)
+            except ImportError:
+                self.missingModules.append(name)
+
+        mf.run_script(self.mainprogram)
+        modules = mf.modules.items()
+        modules.sort()
+        for name, mod in modules:
+            path = mod.__file__
+            if path and self.semi_standalone:
+                # skip the standard library
+                if path.startswith(LIB) and not path.startswith(SITE_PACKAGES):
+                    continue
+            if path and mod.__code__ is None:
+                # C extension
+                filename = os.path.basename(path)
+                pathitems = name.split(".")[:-1] + [filename]
+                dstpath = pathjoin(*pathitems)
+                if USE_ZIPIMPORT:
+                    if name != "zlib":
+                        # neatly pack all extension modules in a subdirectory,
+                        # except zlib, since it's neccesary for bootstrapping.
+                        dstpath = pathjoin("ExtensionModules", dstpath)
+                    # Python modules are stored in a Zip archive, but put
+                    # extensions in Contents/Resources/. Add a tiny "loader"
+                    # program in the Zip archive. Due to Thomas Heller.
+                    source = EXT_LOADER % {"name": name, "filename": dstpath}
+                    code = compile(source, "<dynloader for %s>" % name, "exec")
+                    mod.__code__ = code
+                self.files.append((path, pathjoin("Contents", "Resources", dstpath)))
+            if mod.__code__ is not None:
+                ispkg = mod.__path__ is not None
+                if not USE_ZIPIMPORT or name != "site":
+                    # Our site.py is doing the bootstrapping, so we must
+                    # include a real .pyc file if USE_ZIPIMPORT is True.
+                    self.pymodules.append((name, mod.__code__, ispkg))
+
+        if hasattr(mf, "any_missing_maybe"):
+            missing, maybe = mf.any_missing_maybe()
+        else:
+            missing = mf.any_missing()
+            maybe = []
+        self.missingModules.extend(missing)
+        self.maybeMissingModules.extend(maybe)
+
+    def reportMissing(self):
+        missing = [name for name in self.missingModules
+                if name not in MAYMISS_MODULES]
+        if self.maybeMissingModules:
+            maybe = self.maybeMissingModules
+        else:
+            maybe = [name for name in missing if "." in name]
+            missing = [name for name in missing if "." not in name]
+        missing.sort()
+        maybe.sort()
+        if maybe:
+            self.message("Warning: couldn't find the following submodules:", 1)
+            self.message("    (Note that these could be false alarms -- "
+                         "it's not always", 1)
+            self.message("    possible to distinguish between \"from package "
+                         "import submodule\" ", 1)
+            self.message("    and \"from package import name\")", 1)
+            for name in maybe:
+                self.message("  ? " + name, 1)
+        if missing:
+            self.message("Warning: couldn't find the following modules:", 1)
+            for name in missing:
+                self.message("  ? " + name, 1)
+
+    def report(self):
+        # XXX something decent
+        import pprint
+        pprint.pprint(self.__dict__)
+        if self.standalone or self.semi_standalone:
+            self.reportMissing()
 
 #
 # Utilities.
@@ -618,67 +705,67 @@ SUFFIXES = [_suf for _suf, _mode, _tp in imp.get_suffixes()]
 identifierRE = re.compile(r"[_a-zA-z][_a-zA-Z0-9]*$")
 
 def findPackageContents(name, searchpath=None):
-       head = name.split(".")[-1]
-       if identifierRE.match(head) is None:
-               return {}
-       try:
-               fp, path, (ext, mode, tp) = imp.find_module(head, searchpath)
-       except ImportError:
-               return {}
-       modules = {name: None}
-       if tp == imp.PKG_DIRECTORY and path:
-               files = os.listdir(path)
-               for sub in files:
-                       sub, ext = os.path.splitext(sub)
-                       fullname = name + "." + sub
-                       if sub != "__init__" and fullname not in modules:
-                               modules.update(findPackageContents(fullname, [path]))
-       return modules
+    head = name.split(".")[-1]
+    if identifierRE.match(head) is None:
+        return {}
+    try:
+        fp, path, (ext, mode, tp) = imp.find_module(head, searchpath)
+    except ImportError:
+        return {}
+    modules = {name: None}
+    if tp == imp.PKG_DIRECTORY and path:
+        files = os.listdir(path)
+        for sub in files:
+            sub, ext = os.path.splitext(sub)
+            fullname = name + "." + sub
+            if sub != "__init__" and fullname not in modules:
+                modules.update(findPackageContents(fullname, [path]))
+    return modules
 
 def writePyc(code, path):
-       f = open(path, "wb")
-       f.write(MAGIC)
-       f.write("\0" * 4)  # don't bother about a time stamp
-       marshal.dump(code, f)
-       f.close()
+    f = open(path, "wb")
+    f.write(MAGIC)
+    f.write("\0" * 4)  # don't bother about a time stamp
+    marshal.dump(code, f)
+    f.close()
 
 def copy(src, dst, mkdirs=0):
-       """Copy a file or a directory."""
-       if mkdirs:
-               makedirs(os.path.dirname(dst))
-       if os.path.isdir(src):
-               shutil.copytree(src, dst)
-       else:
-               shutil.copy2(src, dst)
+    """Copy a file or a directory."""
+    if mkdirs:
+        makedirs(os.path.dirname(dst))
+    if os.path.isdir(src):
+        shutil.copytree(src, dst, symlinks=1)
+    else:
+        shutil.copy2(src, dst)
 
 def copytodir(src, dstdir):
-       """Copy a file or a directory to an existing directory."""
-       dst = pathjoin(dstdir, os.path.basename(src))
-       copy(src, dst)
+    """Copy a file or a directory to an existing directory."""
+    dst = pathjoin(dstdir, os.path.basename(src))
+    copy(src, dst)
 
 def makedirs(dir):
-       """Make all directories leading up to 'dir' including the leaf
-       directory. Don't moan if any path element already exists."""
-       try:
-               os.makedirs(dir)
-       except OSError, why:
-               if why.errno != errno.EEXIST:
-                       raise
+    """Make all directories leading up to 'dir' including the leaf
+    directory. Don't moan if any path element already exists."""
+    try:
+        os.makedirs(dir)
+    except OSError, why:
+        if why.errno != errno.EEXIST:
+            raise
 
 def symlink(src, dst, mkdirs=0):
-       """Copy a file or a directory."""
-       if not os.path.exists(src):
-               raise IOError, "No such file or directory: '%s'" % src
-       if mkdirs:
-               makedirs(os.path.dirname(dst))
-       os.symlink(os.path.abspath(src), dst)
+    """Copy a file or a directory."""
+    if not os.path.exists(src):
+        raise IOError, "No such file or directory: '%s'" % src
+    if mkdirs:
+        makedirs(os.path.dirname(dst))
+    os.symlink(os.path.abspath(src), dst)
 
 def pathjoin(*args):
-       """Safe wrapper for os.path.join: asserts that all but the first
-       argument are relative paths."""
-       for seg in args[1:]:
-               assert seg[0] != "/"
-       return os.path.join(*args)
+    """Safe wrapper for os.path.join: asserts that all but the first
+    argument are relative paths."""
+    for seg in args[1:]:
+        assert seg[0] != "/"
+    return os.path.join(*args)
 
 
 cmdline_doc = """\
@@ -704,15 +791,22 @@ Options:
   -c, --creator=CCCC     4-char creator code (default: '????')
       --iconfile=FILE    filename of the icon (an .icns file) to be used
                          as the Finder icon
+      --bundle-id=ID     the CFBundleIdentifier, in reverse-dns format
+                         (eg. org.python.BuildApplet; this is used for
+                         the preferences file name)
   -l, --link             symlink files/folder instead of copying them
       --link-exec        symlink the executable instead of copying it
       --standalone       build a standalone application, which is fully
                          independent of a Python installation
+      --semi-standalone  build a standalone application, which depends on
+                         an installed Python, yet includes all third-party
+                         modules.
+      --python=FILE      Python to use in #! line in stead of current Python
       --lib=FILE         shared library or framework to be copied into
                          the bundle
-  -x, --exclude=MODULE   exclude module (with --standalone)
-  -i, --include=MODULE   include module (with --standalone)
-      --package=PACKAGE  include a whole package (with --standalone)
+  -x, --exclude=MODULE   exclude module (with --(semi-)standalone)
+  -i, --include=MODULE   include module (with --(semi-)standalone)
+      --package=PACKAGE  include a whole package (with --(semi-)standalone)
       --strip            strip binaries (remove debug info)
   -v, --verbose          increase verbosity level
   -q, --quiet            decrease verbosity level
@@ -720,97 +814,103 @@ Options:
 """
 
 def usage(msg=None):
-       if msg:
-               print msg
-       print cmdline_doc
-       sys.exit(1)
+    if msg:
+        print msg
+    print cmdline_doc
+    sys.exit(1)
 
 def main(builder=None):
-       if builder is None:
-               builder = AppBuilder(verbosity=1)
-
-       shortopts = "b:n:r:f:e:m:c:p:lx:i:hvqa"
-       longopts = ("builddir=", "name=", "resource=", "file=", "executable=",
-               "mainprogram=", "creator=", "nib=", "plist=", "link",
-               "link-exec", "help", "verbose", "quiet", "argv", "standalone",
-               "exclude=", "include=", "package=", "strip", "iconfile=",
-               "lib=")
-
-       try:
-               options, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
-       except getopt.error:
-               usage()
-
-       for opt, arg in options:
-               if opt in ('-b', '--builddir'):
-                       builder.builddir = arg
-               elif opt in ('-n', '--name'):
-                       builder.name = arg
-               elif opt in ('-r', '--resource'):
-                       builder.resources.append(arg)
-               elif opt in ('-f', '--file'):
-                       srcdst = arg.split(':')
-                       if len(srcdst) != 2:
-                               usage("-f or --file argument must be two paths, "
-                                     "separated by a colon")
-                       builder.files.append(srcdst)
-               elif opt in ('-e', '--executable'):
-                       builder.executable = arg
-               elif opt in ('-m', '--mainprogram'):
-                       builder.mainprogram = arg
-               elif opt in ('-a', '--argv'):
-                       builder.argv_emulation = 1
-               elif opt in ('-c', '--creator'):
-                       builder.creator = arg
-               elif opt == '--iconfile':
-                       builder.iconfile = arg
-               elif opt == "--lib":
-                       builder.libs.append(arg)
-               elif opt == "--nib":
-                       builder.nibname = arg
-               elif opt in ('-p', '--plist'):
-                       builder.plist = Plist.fromFile(arg)
-               elif opt in ('-l', '--link'):
-                       builder.symlink = 1
-               elif opt == '--link-exec':
-                       builder.symlink_exec = 1
-               elif opt in ('-h', '--help'):
-                       usage()
-               elif opt in ('-v', '--verbose'):
-                       builder.verbosity += 1
-               elif opt in ('-q', '--quiet'):
-                       builder.verbosity -= 1
-               elif opt == '--standalone':
-                       builder.standalone = 1
-               elif opt in ('-x', '--exclude'):
-                       builder.excludeModules.append(arg)
-               elif opt in ('-i', '--include'):
-                       builder.includeModules.append(arg)
-               elif opt == '--package':
-                       builder.includePackages.append(arg)
-               elif opt == '--strip':
-                       builder.strip = 1
-
-       if len(args) != 1:
-               usage("Must specify one command ('build', 'report' or 'help')")
-       command = args[0]
-
-       if command == "build":
-               builder.setup()
-               builder.build()
-       elif command == "report":
-               builder.setup()
-               builder.report()
-       elif command == "help":
-               usage()
-       else:
-               usage("Unknown command '%s'" % command)
+    if builder is None:
+        builder = AppBuilder(verbosity=1)
+
+    shortopts = "b:n:r:f:e:m:c:p:lx:i:hvqa"
+    longopts = ("builddir=", "name=", "resource=", "file=", "executable=",
+        "mainprogram=", "creator=", "nib=", "plist=", "link",
+        "link-exec", "help", "verbose", "quiet", "argv", "standalone",
+        "exclude=", "include=", "package=", "strip", "iconfile=",
+        "lib=", "python=", "semi-standalone", "bundle-id=")
+
+    try:
+        options, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
+    except getopt.error:
+        usage()
+
+    for opt, arg in options:
+        if opt in ('-b', '--builddir'):
+            builder.builddir = arg
+        elif opt in ('-n', '--name'):
+            builder.name = arg
+        elif opt in ('-r', '--resource'):
+            builder.resources.append(os.path.normpath(arg))
+        elif opt in ('-f', '--file'):
+            srcdst = arg.split(':')
+            if len(srcdst) != 2:
+                usage("-f or --file argument must be two paths, "
+                      "separated by a colon")
+            builder.files.append(srcdst)
+        elif opt in ('-e', '--executable'):
+            builder.executable = arg
+        elif opt in ('-m', '--mainprogram'):
+            builder.mainprogram = arg
+        elif opt in ('-a', '--argv'):
+            builder.argv_emulation = 1
+        elif opt in ('-c', '--creator'):
+            builder.creator = arg
+        elif opt == '--bundle-id':
+            builder.bundle_id = arg
+        elif opt == '--iconfile':
+            builder.iconfile = arg
+        elif opt == "--lib":
+            builder.libs.append(os.path.normpath(arg))
+        elif opt == "--nib":
+            builder.nibname = arg
+        elif opt in ('-p', '--plist'):
+            builder.plist = Plist.fromFile(arg)
+        elif opt in ('-l', '--link'):
+            builder.symlink = 1
+        elif opt == '--link-exec':
+            builder.symlink_exec = 1
+        elif opt in ('-h', '--help'):
+            usage()
+        elif opt in ('-v', '--verbose'):
+            builder.verbosity += 1
+        elif opt in ('-q', '--quiet'):
+            builder.verbosity -= 1
+        elif opt == '--standalone':
+            builder.standalone = 1
+        elif opt == '--semi-standalone':
+            builder.semi_standalone = 1
+        elif opt == '--python':
+            builder.python = arg
+        elif opt in ('-x', '--exclude'):
+            builder.excludeModules.append(arg)
+        elif opt in ('-i', '--include'):
+            builder.includeModules.append(arg)
+        elif opt == '--package':
+            builder.includePackages.append(arg)
+        elif opt == '--strip':
+            builder.strip = 1
+
+    if len(args) != 1:
+        usage("Must specify one command ('build', 'report' or 'help')")
+    command = args[0]
+
+    if command == "build":
+        builder.setup()
+        builder.build()
+    elif command == "report":
+        builder.setup()
+        builder.report()
+    elif command == "help":
+        usage()
+    else:
+        usage("Unknown command '%s'" % command)
 
 
 def buildapp(**kwargs):
-       builder = AppBuilder(**kwargs)
-       main(builder)
+    builder = AppBuilder(**kwargs)
+    main(builder)
 
 
 if __name__ == "__main__":
-       main()
+    main()
index 8793b02cf7f3749272b58d797c276cf4d92b7432..38f0779fbb97c9fd8576c56ee30315c4fd645984 100755 (executable)
@@ -15,11 +15,13 @@ fi
 
 function usage {
     echo ""
-    echo "Usage: $0  wx_version  py_version  [command flags...]"
-    echo "   wx_version     String to use for version in filenames, etc."
-    echo "   py_version     String to append to python (which python version to use.)"
+    echo "Usage: $0  [apple|local]  [command flags...]"
     echo ""
-    echo "command flags:"
+    echo "   apple          Build for Apple's python in /usr/bin"
+    echo "   local          Build for a locally installed python in /usr/local/bin"
+    echo "                  (for example Jaguar's MacPython)"
+    echo ""
+    echo "optional command flags:"
     echo "   skiptar        Don't unpack the tarball"
     echo "   use_cvs        Use the CVS workspace instead of a tarfile"
     echo "   skipconfig     Don't run configure"
@@ -27,17 +29,23 @@ function usage {
     echo "   skipinstall    Don't do the installation step"
     echo "   skipdmg        Don't make the package or diskimage"
     echo "   skipclean      Don't do the cleanup at the end"
+    echo ""
 }
 
 
-if [ $# -lt 2 ]; then
+if [ $# -lt 1 ]; then
     usage
     exit 1
 fi
 
-VERSION=$1
-PYVER=$2
-shift;shift
+KIND=$1
+case $KIND in
+    apple)    PYTHON=/usr/bin/python ;;
+    local)    PYTHON=/usr/local/bin/python ;;
+    *)        usage; exit 1 ;;
+esac
+PYTHONW=${PYTHON}w
+shift
 
 
 for flag in $*; do
@@ -57,13 +65,18 @@ for flag in $*; do
 done
 
 
-SRCDIR=/Volumes/Gate.Stuff/Development/wxPython/dist/$VERSION
+VERSION=`$PYTHON -c "import setup;print setup.VERSION"`
+PYVER=`$PYTHON -c "import sys; print sys.version[:3]"`
+PYPREFIX=`$PYTHON -c "import sys; print sys.exec_prefix"`
+SITEPACKAGES=$PYPREFIX/lib/python$PYVER/site-packages
+
+SRCDIR=/stuff/Development/wxPython/dist/$VERSION
 TARBALL=$SRCDIR/wxPythonSrc-$VERSION.tar.gz
-SITEPACKAGES=/Library/Frameworks/Python.framework/Versions/$PYVER/lib/python$PYVER/site-packages
 
-# TODO:  Should I change the prefix to /usr?
-PREFIX=/usr/local
+PREFIX=/usr/lib/wxPython-$VERSION
+BINPREFIX=/usr/bin
 
+WXROOT=`dirname $PWD`
 PROGDIR="`dirname \"$0\"`"
 TMPDIR=$PWD/_build_dmg
 
@@ -81,7 +94,7 @@ DESTDIR=$PWD/dist
 
 mkdir -p $BUILDROOT
 mkdir -p $INSTALLROOT
-mkdir -p $INSTALLDEVEL
+#mkdir -p $INSTALLDEVEL
 rm -rf $DMGDIR
 mkdir -p $DMGDIR/root
 
@@ -92,7 +105,8 @@ pushd $BUILDROOT
 # Unpack the tarball
 
 if [ -z "$skiptar" ]; then
-    tar xzvf $TARBALL
+    echo Unarchiving tarball...
+    tar xzf $TARBALL
 fi
 
 if [ "$use_cvs" = 1 ]; then
@@ -104,19 +118,21 @@ if [ "$use_cvs" = 1 ]; then
     if [ -e .last_copy ]; then
        FEXPR="-cnewer .last_copy"
     fi
-    find /projects/wx $FEXPR -print \
-       | grep -v wx/build \
+    MEASURE=$WXROOT//
+    find $WXROOT $FEXPR -print \
+       | grep -v $WXROOT/bld \
        | grep -v wxPython/build \
        | grep -v wxPython/_build \
        | grep -v CVS \
-       | cut -b 14- > filelist
+       | grep -v .pyc \
+       | cut -b ${#MEASURE}- > filelist
 
     for x in `cat filelist`; do
-       if [ -d "/projects/wx/$x" ]; then
+       if [ -d "$WXROOT/$x" ]; then
            mkdir -p "wxPythonSrc-$VERSION/$x"
        else
            echo $x
-           cp -p "/projects/wx/$x" "wxPythonSrc-$VERSION/$x"
+           cp -p "$WXROOT/$x" "wxPythonSrc-$VERSION/$x"
        fi
     done
 
@@ -126,60 +142,60 @@ fi
 
 cd wxPythonSrc-$VERSION
 WXDIR=`pwd`
-mkdir -p $WXDIR/build
-cd $WXDIR/build
+mkdir -p $WXDIR/bld
+cd $WXDIR/bld
 
 #----------------------------------------------------------------------
 
 
 # Configure wxWindows
 if [ -z "$skipconfig" ]; then
-    ../configure --with-mac --prefix=$PREFIX \
+    ../configure \
+       --prefix=$PREFIX \
+       --with-mac \
+       --disable-monolithic \
        --with-opengl \
-       --enable-precomp=no \
        --enable-geometry \
        --enable-optimise \
+       --enable-precomp=no \
+       \
        --with-libjpeg=builtin \
        --with-libpng=builtin \
        --with-libtiff=builtin \
-
-
-#      --with-zlib=builtin
-#      --enable-debug_flag
+       --with-zlib=builtin \
+       \
+       --enable-debug_flag
 
 fi
 
 # Build wxWindows and wxPython
 if [ -z "$skipbuild" ]; then
-    make
 
+    # Make wxWindows and some contribs
+    make 
+    make -C contrib/src/gizmos 
+    make -C contrib/src/ogl CXXFLAGS="-DwxUSE_DEPRECATED=0"
+    make -C contrib/src/stc
+    make -C contrib/src/xrc
+
+    if [ ! -e $WXDIR/include/wx/gizmos ]; then
+       # Make some links so the wxPython build can find all the headers it needs
+       pushd $WXDIR/include/wx
+       ln -s ../../contrib/include/wx/* .
+       popd
+    fi
+
+    # Build wxPython
     cd $WXDIR/wxPython
-    python$PYVER setup.py \
-       IN_CVS_TREE=1 \
-       WX_CONFIG="$WXDIR/build/wx-config --prefix=$WXDIR --exec-prefix=$WXDIR/build" \
+    $PYTHON setup.py \
+       NO_SCRIPTS=1 \
+       WX_CONFIG="$WXDIR/bld/wx-config --prefix=$WXDIR --exec-prefix=$WXDIR/bld" \
        build
 
 
-    # Build wxrc (XRC resource tool) but don't use the makefiles since they expect
-    # a shared version of the xrc lib to have been built...
-    cd $WXDIR/contrib/utils/wxrc
-    WX_CONFIG="$WXDIR/build/wx-config --prefix=$WXDIR --exec-prefix=$WXDIR/build"
-    wCC=`$WX_CONFIG --cc`
-    wCXX=`$WX_CONFIG --cxx`
-
-    for f in wxrc.cpp ../../src/xrc/*.cpp; do
-       echo $f
-       $wCXX `$WX_CONFIG --cxxflags` -I ../../include -I ../../src/xrc/expat/xmlparse -I ../../src/xrc/expat/xmltok -c $f
-    done
-    for f in ../../src/xrc/expat/xmlparse/xmlparse.c ../../src/xrc/expat/xmltok/xmlrole.c ../../src/xrc/expat/xmltok/xmltok.c; do
-       echo $f
-       $wCC `$WX_CONFIG --cxxflags` -I ../../include -I ../../src/xrc/expat/xmlparse -I ../../src/xrc/expat/xmltok -c $f
-    done
-
-    # the handlers are not needed
-    rm xh_*.o xmlrsall.o
-
-    $wCXX `$WX_CONFIG --libs` *.o -o wxrc
+    # Build wxrc (XRC resource tool) 
+    cd $WXDIR/bld/contrib/utils/wxrc
+    make 
     strip wxrc
 
 fi
@@ -188,37 +204,42 @@ fi
 # Install wxWindows
 
 if [ -z "$skipinstall" ]; then
-    cd $WXDIR/build
-    make prefix=$INSTALLROOT/$PREFIX install
+    cd $WXDIR/bld
+    make prefix=$INSTALLROOT$PREFIX install
+    make -C contrib/src/gizmos prefix=$INSTALLROOT$PREFIX install
+    make -C contrib/src/ogl CXXFLAGS="-DwxUSE_DEPRECATED=0" prefix=$INSTALLROOT/$PREFIX install
+    make -C contrib/src/stc prefix=$INSTALLROOT$PREFIX install
+    make -C contrib/src/xrc prefix=$INSTALLROOT$PREFIX install
 
 
     # and wxPython
     cd $WXDIR/wxPython
-    python$PYVER setup.py \
-       IN_CVS_TREE=1 \
-       WX_CONFIG="$WXDIR/build/wx-config --prefix=$WXDIR --exec-prefix=$WXDIR/build" \
+    $PYTHON setup.py \
+       NO_SCRIPTS=1 \
+       WX_CONFIG="$INSTALLROOT/$PREFIX/bin/wx-config --prefix=$INSTALLROOT/$PREFIX" \
        install \
        --root=$INSTALLROOT
 
+
     # install wxPython's tool scripts
+    mkdir -p $INSTALLROOT$BINPREFIX
     cd $WXDIR/wxPython/scripts
-    python$PYVER CreateMacScripts.py $INSTALLROOT $PREFIX/bin
+    python$PYVER CreateMacScripts.py $INSTALLROOT $BINPREFIX
 
     # Install wxrc
-    cp $WXDIR/contrib/utils/wxrc/wxrc $INSTALLROOT$PREFIX/bin
+    cp $WXDIR/bld/contrib/utils/wxrc/wxrc $INSTALLROOT$BINPREFIX
 
 
-    # Move wxWindows devel files and save for a separate installer package
-    mkdir -p $INSTALLDEVEL$PREFIX
-    mkdir -p $INSTALLDEVEL$PREFIX/bin
-    mkdir -p $INSTALLDEVEL$PREFIX/lib
-    mv -f $INSTALLROOT$PREFIX/include $INSTALLDEVEL$PREFIX
-    mv -f $INSTALLROOT$PREFIX/lib/wx  $INSTALLDEVEL$PREFIX/lib
-    mv -f $INSTALLROOT$PREFIX/bin/wx* $INSTALLDEVEL$PREFIX/bin
+    # install the wxPython headers
+    cd $WXDIR/wxPython
+    cp -R include $INSTALLROOT$PREFIX
+    mkdir -p      $INSTALLROOT$PREFIX/include/wx/wxPython/i_files
+    cp src/*.i    $INSTALLROOT$PREFIX/include/wx/wxPython/i_files
+
 
     # TODO for $INSTALLROOT and $INSTALLDEVEL ?
-    # chown -R root:admin
-    # chmod -R g+w
+    #chown -R root:admin $INSTALLROOT
+    #chmod -R g+w        $INSTALLROOT
 fi
 
 popd
@@ -230,63 +251,18 @@ if [ -z "$skipdmg" ]; then
 
     # Remove the .pyc/.pyo files they just take up space and can be recreated
     # during the install.
-    python $PROGDIR/../zappycfiles.py $INSTALLROOT/Library/Frameworks/Python.framework
-
-    # Copy the demo, samples, and such to the Applications dir
-    APPDIR=$INSTALLROOT/Applications/wxPythonOSX-$VERSION
-    mkdir -p $APPDIR
-    cp -pR $WXDIR/wxPython/demo $APPDIR
-    cp -pR $WXDIR/wxPython/samples $APPDIR
-
-    # Move sample launchers to .pyw files.
-    # TODO:  A better, more automated way to do this!!!
-    pushd $APPDIR/samples
-    for x in StyleEditor/STCStyleEditor \
-           doodle/superdoodle \
-           frogedit/FrogEdit \
-           pySketch/pySketch \
-           wxProject/wxProject; do
-        mv $x.py $x.pyw
-    done
-    popd
-
-    # Make an app to launch the demo
-    cat > $APPDIR/demo/RunDemo.pyw <<EOF
-import sys, os
-sys.path.insert(0, "/Applications/wxPythonOSX-$VERSION/demo")
-os.chdir("/Applications/wxPythonOSX-$VERSION/demo")
-import Main
-Main.main()
-EOF
-    pythonw $PROGDIR/../buildapp.py \
-       --builddir=$APPDIR \
-       --name=RunDemo \
-       --mainprogram=$APPDIR/demo/RunDemo.pyw \
-       --iconfile=$PROGDIR/RunDemo.icns \
-       build
-
-    # Make an app to launch PyShell
-    pythonw $PROGDIR/../buildapp.py \
-       --builddir=$APPDIR \
-       --name=PyShell \
-       --mainprogram=$INSTALLROOT$PREFIX/bin/pyshell.py \
-       --iconfile=$PROGDIR/PieShell.icns \
-       build
-
-     # Make an app to launch XRCed
-     pythonw $PROGDIR/../buildapp.py \
-       --builddir=$APPDIR \
-       --name=XRCed \
-       --mainprogram=$INSTALLROOT$PREFIX/bin/xrced.py \
-       --iconfile=$PROGDIR/XRCed.icns \
-       build
+    $PYTHON $PROGDIR/../zappycfiles.py $INSTALLROOT
 
 
     # Make the welcome message
+    case $KIND in
+       apple)  W_MSG="an Apple installed (Panther) version of" ;;
+       local)  W_MSG="a locally built version (or Jaguar version) of" ;;
+    esac
     cat > $RESOURCEDIR/Welcome.txt <<EOF
 Welcome!
 
-This program will install wxPython $VERSION for MacPython-OSX $PYVER.
+This program will install wxPython $VERSION for $W_MSG MacPython-OSX $PYVER.
 
 Build date:   `date`
 EOF
@@ -296,6 +272,7 @@ EOF
 #!/bin/sh
 # Cleanup any old install of the wxPython package
 rm -rf \$2$SITEPACKAGES/wxPython
+rm -rf \$2$SITEPACKAGES/wx
 exit 0
 EOF
     chmod +x $RESOURCEDIR/preflight
@@ -304,20 +281,17 @@ EOF
     cat > $RESOURCEDIR/postflight <<EOF
 #!/bin/sh -e
 # Compile the .py files in the wxPython pacakge
-/usr/local/bin/python \$2$SITEPACKAGES/../compileall.py \$2$SITEPACKAGES/wxPython
-/usr/local/bin/python -O \$2$SITEPACKAGES/../compileall.py \$2$SITEPACKAGES/wxPython
-
-# and in the demo
-/usr/local/bin/python \$2$SITEPACKAGES/../compileall.py /Applications/wxPythonOSX-$VERSION/demo
+$PYTHON \$2$SITEPACKAGES/../compileall.py \$2$SITEPACKAGES/wxPython
+$PYTHON \$2$SITEPACKAGES/../compileall.py \$2$SITEPACKAGES/wx
+$PYTHON -O \$2$SITEPACKAGES/../compileall.py \$2$SITEPACKAGES/wxPython
+$PYTHON -O \$2$SITEPACKAGES/../compileall.py \$2$SITEPACKAGES/wx
 
-# Make the demo/data dir writable
-chmod a+w /Applications/wxPythonOSX-$VERSION/demo/data
 
 # and the wxPython pacakge should be group writable
 chgrp -R admin \$2$SITEPACKAGES/wxPython
-chgrp -R admin /Applications/wxPythonOSX-$VERSION
 chmod -R g+w \$2$SITEPACKAGES/wxPython
-chmod -R g+w /Applications/wxPythonOSX-$VERSION
+chgrp -R admin \$2$SITEPACKAGES/wx
+chmod -R g+w \$2$SITEPACKAGES/wx
 
 exit 0
 EOF
@@ -325,63 +299,106 @@ EOF
 
 
 
-    # Finally, build the main package...
-    rm -rf wxPythonOSX.pkg
+    # Finally, build the main Installer Package...
+    rm -rf wxPythonOSX-$KIND.pkg
     python $PROGDIR/../buildpkg.py \
-       --Title=wxPythonOSX \
+       --Title=wxPythonOSX-$KIND \
        --Version=$VERSION \
-       --Description="wxPython $VERSION for MacPython-OSX $PYVER" \
+       --Description="wxPython $VERSION for $W_MSG MacPython-OSX $PYVER" \
        --NeedsAuthorization="YES" \
        --Relocatable="NO" \
        --InstallOnly="YES" \
        $INSTALLROOT \
        $RESOURCEDIR
 
-    mv wxPythonOSX.pkg $DMGDIR/root
+    mv wxPythonOSX-$KIND.pkg $DMGDIR/root
 
 
-    # and the devel package
-    rm -rf wxPythonOSX-devel.pkg
-    python $PROGDIR/../buildpkg.py \
-       --Title=wxPythonOSX-devel \
-       --Version=$VERSION \
-       --Description="Headers and such that allow you to link with the same wxMac that wxPython does" \
-       --NeedsAuthorization="YES" \
-       --Relocatable="NO" \
-       --InstallOnly="YES" \
-       $INSTALLROOT
+    # and the devel package
+    rm -rf wxPythonOSX-devel.pkg
+    python $PROGDIR/../buildpkg.py \
+#      --Title=wxPythonOSX-devel \
+#      --Version=$VERSION \
+#      --Description="Headers and such that allow you to link with the same wxMac that wxPython does" \
+#      --NeedsAuthorization="YES" \
+#      --Relocatable="NO" \
+#      --InstallOnly="YES" \
+#      $INSTALLDEVEL
 
-    mv wxPythonOSX-devel.pkg $DMGDIR/root
+    mv wxPythonOSX-devel.pkg $DMGDIR/root
 
 
     # Make a README.txt to go on the disk image
     cat > $DMGDIR/root/README.txt <<EOF
-The files on this disk image are Installer packages for wxPythonOSX
-$VERSION for MacPython-OSX $PVER.  You must already have MacPython-OSX
-installed.
+Welcome to wxPython!
+
+On this disk image you will find the installer for the wxPython $VERSION for $W_MSG MacPython-OSX $PYVER.  You must already have MacPython-OSX installed.  
+
+   wxPython-$KIND.pkg   The installer package.  It contains the wxPython 
+                        extension modules, wxMac dynamic libraries and
+                        headers, and some scripts for the command-line 
+                        tools.  
 
-The wxPython extension modules, library, demo and samples are
-contained in the wxPythonOSX package. You should install at least this
-package to use wxPython.
+Everything else here is optional and you can drag them out of the disk 
+image and drop them where ever you want.
 
-If you have any need to create applicaitons or extension modules that
-link with the same wxMac that wxPython does, then you can also install
-the wxPythonOSX-devel package to get the necessary header files and
-such.  Otherwise you don't need it.
+   docs/                A few readmes, change log, etc.  The full 
+                        documentation is downloadable separately. 
+
+   licence/             License docs.
+
+   demo/                A copy of the wxPython demo.
+
+   samples/             Several small sample applications that 
+                        demonstrate how to use wxPython.
 
 Happy Hacking!
 EOF
 
 
-    # license files, etc.
+    # license files, docs, etc.
     cp -pR $WXDIR/wxPython/licence $DMGDIR/root
-    cp $WXDIR/wxPython/CHANGES.txt $DMGDIR/root
+    rm -rf $WXDIR/wxPython/docs/xml-raw
+    cp -pR $WXDIR/wxPython/docs $DMGDIR/root
+    rm -rf $DMGDIR/root/docs/bin
+
+    # Copy the demo and samples to the disk image
+    cp -pR $WXDIR/wxPython/demo $DMGDIR/root
+    cp -pR $WXDIR/wxPython/samples $DMGDIR/root
+    rm $DMGDIR/root/demo/b
+
+    
+    # Make an app bundle to launch PyCrust
+    $PYTHONW $PROGDIR/../buildapp.py \
+       --builddir=$DMGDIR/root \
+       --name=PyCrust \
+       --mainprogram=$INSTALLROOT$BINPREFIX/pycrust.py \
+       --iconfile=$PROGDIR/PieShell.icns \
+       build
+
+    # Make an app to launch XRCed
+    $PYTHONW $PROGDIR/../buildapp.py \
+       --builddir=$DMGDIR/root \
+       --name=XRCed \
+       --mainprogram=$INSTALLROOT$BINPREFIX/xrced.py \
+       --iconfile=$PROGDIR/XRCed.icns \
+       build
+
+    # Make an app bundle to run the demo
+    $PYTHONW $PROGDIR/../buildapp.py \
+       --builddir=$DMGDIR/root \
+       --name="wxPython Demo" \
+       --mainprogram=$DMGDIR/root/demo/demo.py \
+       --iconfile=$PROGDIR/RunDemo.icns \
+       build
+    cp -pR $DMGDIR/root/demo/* "$DMGDIR/root/wxPython Demo.app/Contents/Resources"
+    
 
     # and then finally make a disk image containing the packages and etc.
-    $PROGDIR/../makedmg $DMGDIR/root $DMGDIR wxPythonOSX-$VERSION-py$PYVER
+    $PROGDIR/../makedmg $DMGDIR/root $DMGDIR wxPythonOSX-$VERSION-$KIND-Py$PYVER
 
-    echo Moving $DMGDIR/wxPythonOSX-$VERSION-py$PYVER.dmg to $DESTDIR
-    mv $DMGDIR/wxPythonOSX-$VERSION-py$PYVER.dmg $DESTDIR
+    echo Moving $DMGDIR/wxPythonOSX-$VERSION-$KIND-Py$PYVER.dmg to $DESTDIR
+    mv $DMGDIR/wxPythonOSX-$VERSION-$KIND-Py$PYVER.dmg  $DESTDIR
 fi
 
 
diff --git a/wxPython/distrib/mac/wxPythonOSX/resources/.cvsignore b/wxPython/distrib/mac/wxPythonOSX/resources/.cvsignore
new file mode 100644 (file)
index 0000000..ab253ac
--- /dev/null
@@ -0,0 +1,2 @@
+Welcome.txt
+postflight
diff --git a/wxPython/distrib/mac/wxPythonOSX/resources/ReadMe.rtf b/wxPython/distrib/mac/wxPythonOSX/resources/ReadMe.rtf
deleted file mode 100644 (file)
index ee8c394..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-{\rtf1\mac\ansicpg10000\cocoartf102
-{\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;\f2\fnil\fcharset77 Monaco;
-\f3\fnil\fcharset77 LucidaGrande;}
-{\colortbl;\red255\green255\blue255;\red0\green0\blue255;}
-\margl1440\margr1440\vieww11800\viewh14740\viewkind0
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f0\b\fs24 \cf0 About\
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f1\b0 \cf0 \
-This is a binary package of wxPython for MacPython on Mac OS X 10.2 or later. The wxMac binaries will be installed as well. MacPython-OSX, however, is not included with this package, but is also required to run wxPython. Before you continue you should have already installed the MacPython-OSX framework.\
-\
-Please note that the Mac OS ports of wxPython as well as wxWindows (a.k.a. wxMac) are works-in-progress. Report bugs via SourceForge [1] or discuss the problem on the mailing list(s) related to your questions (see below).\
-\
-
-\fs18 [1] \cf2 http://sf.net/tracker/?atid=109863&group_id=9863
-\fs24 \cf0 \
-\
-\
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f0\b \cf0 What will be installed and where\
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f1\b0 \cf0 \
-wxMac goes into
-\f2 /usr/local
-\f1  and wxPython will be installed into the appropriate subfolder of the Python framework. Choose the
-\f3 Show files
-\f1  command from the
-\f3 File
-\f1  menu for a complete file listing. (The menu item becomes available as soon as the license agreement is accepted in the next step.)
-\f2 \
-
-\f1 \
-\
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f0\b \cf0 Getting started with wxPython
-\f1\b0 \
-\
-You can verify that wxPython was succesfully installed by running the demo. It resides on the same disk image where you found this package.  Just double click the script named
-\f2 demo.py
-\f1  or drag and drop it onto the Python interpreter in your
-\f2 Application
-\f1  folder.\
-\
-The official wxPython site:\
-\
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f2 \cf2  http://wxPython.org\cf0 \
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f1 \cf0 \
-The best way to get help with wxWindows and wxPython is to subscribe to the mail lists and post questions there.  You can see info about the mail lists, including how to subscribe, at this website:\
-\
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f2 \cf2  http://wxPython.org/maillist.php\
-\
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f1 \cf0 \
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f0\b \cf0 Disclaimer
-\f1\b0 \
-\
-\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
-
-\f2 \cf0 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-\f1 \
-\
-\
-Robin Dunn\
-\
-}
\ No newline at end of file
diff --git a/wxPython/distrib/mac/wxPythonOSX/resources/preflight b/wxPython/distrib/mac/wxPythonOSX/resources/preflight
deleted file mode 100755 (executable)
index 79d6bf2..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-# Cleanup any old install of the wxPython package
-rm -rf $2/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/site-packages/wxPython
-exit 0
index dcd41334c6758d2a832bb012b81e8a4b8d01359b..0349220d9e9a98687b1af9b2dd98cb2eef0351b5 100644 (file)
@@ -10,11 +10,10 @@ doit = 1
 def main():
        if not sys.argv[1:]:
                if os.name == 'mac':
-                       import macfs
-                       fss, ok = macfs.GetDirectory('Directory to zap pyc files in')
-                       if not ok:
+                       import EasyDialogs
+                       dir = EasyDialogs.AskFolder(message='Directory to zap pyc files in')
+                       if not dir:
                                sys.exit(0)
-                       dir = fss.as_pathname()
                        zappyc(dir)
                else:
                        print 'Usage: zappyc dir ...'
index d8ab06fca099f7ae71a6f505c32a1d9eb8261a0f..093e3d4b7bff73a8cc90c6d17522ac21bcd10ed7 100644 (file)
@@ -1,6 +1,6 @@
 #----------------------------------------------------------------------
 # Name:         CreateMacScripts.py
-# Purpose:      Massages the scripts to be usable with MachoPython
+# Purpose:      Massages the scripts to be usable with MacPython-OSX
 #
 # Author:       Robin Dunn
 #