From 85245f48ad351409d50cbecfab874827eb0f719b Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Fri, 22 Oct 2004 02:50:05 +0000 Subject: [PATCH 1/1] wxPython on OSX can now be built in Unicode mode, can support multiple version installs, and comes with an uninstaller script. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30055 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- wxPython/config.py | 2 +- wxPython/distrib/mac/uninstall_wxPython.py | 196 +++++++++++++++ wxPython/distrib/mac/wxPythonOSX/build | 267 +++++++++++++++------ wxPython/docs/CHANGES.txt | 4 + 4 files changed, 394 insertions(+), 75 deletions(-) create mode 100755 wxPython/distrib/mac/uninstall_wxPython.py diff --git a/wxPython/config.py b/wxPython/config.py index b76666bcaf..4089667e0a 100644 --- a/wxPython/config.py +++ b/wxPython/config.py @@ -606,7 +606,7 @@ if debug: if FINAL: HYBRID = 0 -if UNICODE and WXPORT not in ['msw', 'gtk2']: +if UNICODE and WXPORT not in ['msw', 'gtk2', 'mac']: raise SystemExit, "UNICODE mode not currently supported on this WXPORT: "+WXPORT diff --git a/wxPython/distrib/mac/uninstall_wxPython.py b/wxPython/distrib/mac/uninstall_wxPython.py new file mode 100755 index 0000000000..80373c232e --- /dev/null +++ b/wxPython/distrib/mac/uninstall_wxPython.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python +""" +This script will search for installed versions of wxPython on OSX and +allow the user to choose one to uninstall. It then will use the +metadata stored about the installed package to remove all the files +associated with that install. + +Only the files installed by the main Installer Package will be +removed. This includes the Python modules and the wxWidgets shared +libraries. If you also installed the demo or docs by dragging them out +of the disk image, then you will need to drag them to the Trash +yourself. +""" + +import sys, os, glob +import cPickle, urllib + +RCPTDIR = "/Library/Receipts" +RSRCDIR = "Contents/Resources" + +# only clean up dirs that have one of these as a prefix. We do this +# because the file list returned from lsbom will include /, /usr, +# /usr/local, etc. +PREFIXES = [ '/Library/Python/2.3/', + '/Library/Python/2.4/', + '/usr/local/lib/', + ] + + +class AccessError(Exception): + pass + + +class InstalledReceipt(object): + def __init__(self, rcptPath): + self.rcptPath = rcptPath + self.rsrcPath = os.path.join(rcptPath, RSRCDIR) + self.bomFile = glob.glob(os.path.join(self.rsrcPath, "*.bom"))[0] + self.findMetaData() + + + def findMetaData(self): + # TODO: Make this be able to also look at Info.plist files + infoFile = glob.glob(os.path.join(self.rsrcPath, "*.info"))[0] + self.mdata = {} + for line in open(infoFile, "r").readlines(): + line = line.strip() + if line and line[0] != '#': + ls = line.split() + self.mdata[ls[0]] = line[len(ls[0])+1:] + + + def getFileList(self): + p = os.popen("lsbom -s %s" % self.bomFile, "r") + data = p.read() + data.strip() + data = filter(lambda s: s!='' and s!='.', data.split('\n')) + loc = self.mdata['DefaultLocation'] + return [loc+item for item in data] + + + def walkFiles(self, handleFile, handleDir): + dirs = [] + names = self.getFileList() + + # the plain files + for name in names: + name = os.path.abspath(name) + if os.path.isdir(name): + dirs.append(name) + else: + handleFile(name) + + # the directories + dirs.reverse() + for dir in dirs: + for prefix in PREFIXES: + if dir.startswith(prefix): + handleDir(dir) + break + + # Finally, remove the Receipts package, bottom-up + for dirpath, dirname, filenames in os.walk(self.rcptPath, False): + for name in filenames: + name = os.path.join(dirpath, name) + handleFile(name) + handleDir(dirpath) + + + + def showFiles(self): + def show(name): + if os.path.exists(name): + print "Will remove:", name + self.walkFiles(show, show) + + + def testUninstallAccess(self): + def testFile(name): + if os.path.exists(name): + if not os.access(name, os.W_OK): + raise AccessError(name) + self.walkFiles(testFile, testFile) + + + def doUninstall(self): + def removeFile(name): + if os.path.exists(name): + print "Removing:", name + os.unlink(name) + def removeDir(name): + print "Removing:", name + if os.path.exists(name): + hasFiles = os.listdir(name) + if hasFiles: # perhaps some left over symlinks, or .pyc files + for file in hasFiles: + os.unlink(os.path.join(name, file)) + os.rmdir(name) + + try: + self.testUninstallAccess() + except AccessError, e: + print "UNABLE TO UNINSTALL!\nNo permission to remove: ", e.args[0] + sys.exit() + + self.walkFiles(removeFile, removeDir) + + + + +def findInstalled(): + installed = [] + for name in glob.glob(os.path.join(RCPTDIR, "wxPython*")): + ir = InstalledReceipt(name) + installed.append(ir) + + return installed + + +# Just in case a Python < 2.3 is used to run this +try: + enumerate +except NameError: + def enumerate(sequence): + return zip(range(len(sequence)), sequence) + + +def main(): + if len(sys.argv) > 1 and sys.argv[1] == "-doit": + inst = cPickle.loads(urllib.unquote(sys.argv[2])) + inst.doUninstall() + sys.exit() + + print __doc__ + installed = findInstalled() + + if not installed: + print "*** No wxPython installations found! ***" + raw_input("Press RETURN...") + sys.exit() + + for i, inst in enumerate(installed): + print " %d. %s \t%s" % (i+1, inst.mdata["Title"], inst.mdata["Version"]) + + print + ans = raw_input("Enter the number of the install to examine or 'Q' to quit: ") + if ans in ['Q', 'q']: + sys.exit() + inst = installed[int(ans) - 1] + + while True: + print + print """ + Title: %(Title)s + Version: %(Version)s + Description: %(Description)s + """ % inst.mdata + + ans = raw_input("(U)ninstall, (S)how what will be removed, or (Q)uit? [u,s,q] ") + if ans in ['Q', 'q']: + sys.exit() + + elif ans in ['S', 's']: + inst.showFiles() + + elif ans in ['U', 'u']: + print + print "Launching uninstaller with sudo, please enter your password if prompted:" + os.system("sudo %s -doit %s" % + (sys.argv[0], + urllib.quote(cPickle.dumps(inst)))) + sys.exit() + + +if __name__ == '__main__': + main() diff --git a/wxPython/distrib/mac/wxPythonOSX/build b/wxPython/distrib/mac/wxPythonOSX/build index a28104cbbb..53404d8e2b 100755 --- a/wxPython/distrib/mac/wxPythonOSX/build +++ b/wxPython/distrib/mac/wxPythonOSX/build @@ -31,6 +31,7 @@ function usage { echo " skiptar Don't unpack the tarball" echo " inplace Don't use the tarball, build from the CVS tree instead" echo " (The Docs and Demo tarballs are still required for a full build.)" + echo " unicode Make a unicode build" echo " skipconfig Don't run configure" echo " skipbuild Don't build wxWidgets or wxPython" echo " skipinstall Don't do the installation step" @@ -61,6 +62,7 @@ skipinstall=no skipdmg=no skipclean=no inplace=no +unicode=no for flag in $*; do case ${flag} in @@ -71,6 +73,7 @@ for flag in $*; do skipdmg) skipdmg=yes ;; skipclean) skipclean=yes ;; inplace) inplace=yes; skiptar=yes ;; + unicode) unicode=yes ;; *) echo "Unknown flag \"${flag}\"" usage @@ -86,9 +89,15 @@ PYLIB=$PYPREFIX/lib/python$PYVER SITEPACKAGES=$PYLIB/site-packages SHORTVER=`echo $VERSION | cut -c 1,2,3` -# TODO: enable selecting unicode or ansi builds, then set this accordingly... -CHARTYPE=ansi - +if [ $unicode == yes ]; then + CHARTYPE=unicode + UNICODEOPT=--enable-unicode + PYUNICODEOPT=1 +else + CHARTYPE=ansi + UNICODEOPT=--disable-unicode + PYUNICODEOPT=0 +fi if [ -z "$TARBALLDIR" ]; then @@ -118,7 +127,7 @@ fi -PREFIX=/usr/local/lib/wxPython-$VERSION +PREFIX=/usr/local/lib/wxPython-$CHARTYPE-$VERSION BINPREFIX=/usr/local/bin WXROOT=`dirname $PWD` @@ -126,9 +135,15 @@ PROGDIR="`dirname \"$0\"`" TMPDIR=$PWD/_build_dmg BUILDROOT=$TMPDIR/build -INSTALLROOT=$TMPDIR/install -INSTALLDEVEL=$TMPDIR/install-devel + +INSTALLROOT=$TMPDIR/install-root +INSTALLCOMMON=$TMPDIR/install-common +INSTALLAPPS=$TMPDIR/install-apps + DMGDIR=$TMPDIR/dmg +DMGROOT=$DMGDIR/root +DMGAPPS=$DMGDIR/apps + RESOURCEDIR=$PROGDIR/resources DESTDIR=$PWD/dist SRCROOT=$BUILDROOT/wxPython-src-$VERSION @@ -139,11 +154,13 @@ SRCROOT=$BUILDROOT/wxPython-src-$VERSION mkdir -p $BUILDROOT mkdir -p $INSTALLROOT -#mkdir -p $INSTALLDEVEL +mkdir -p $INSTALLCOMMON +mkdir -p $INSTALLAPPS + rm -rf $DMGDIR -mkdir -p $DMGDIR/root/Apps -mkdir -p $DMGDIR/root/Docs -mkdir -p $DMGDIR/root/Samples +mkdir -p $DMGROOT +mkdir -p $DMGAPPS/Docs +mkdir -p $DMGAPPS/Samples pushd $BUILDROOT @@ -191,11 +208,8 @@ if [ $skipconfig != yes ]; then --enable-debug_flag \ --enable-precomp=no \ --enable-optimise \ + $UNICODEOPT -## --with-libjpeg=builtin \ -## --with-libpng=builtin \ -## --with-libtiff=builtin \ -## --with-zlib=builtin \ fi @@ -205,8 +219,10 @@ if [ $skipbuild != yes ]; then # Make wxWidgets and some contribs # For some reason Rez and DeRez have started locking up if run as root... - chmod a+w lib - su robind -c "make lib/libwx_macd-2.5.3.r" + if [ "$UID" = "0" ]; then + chmod a+w lib + su robind -c "make lib/libwx_macd-2.5.3.r" + fi make make -C contrib/src/gizmos @@ -216,6 +232,7 @@ if [ $skipbuild != yes ]; then # Build wxPython cd $WXDIR/wxPython $PYTHON setup.py \ + UNICODE=$PYUNICODEOPT \ NO_SCRIPTS=1 \ EP_ADD_OPTS=1 \ WX_CONFIG="$WXBLD/wx-config --inplace" \ @@ -242,6 +259,7 @@ if [ $skipinstall != yes ]; then # and wxPython cd $WXDIR/wxPython $PYTHON setup.py \ + UNICODE=$PYUNICODEOPT \ NO_SCRIPTS=1 \ EP_ADD_OPTS=1 \ WX_CONFIG="$INSTALLROOT/$PREFIX/bin/wx-config --prefix=$INSTALLROOT/$PREFIX" \ @@ -263,21 +281,34 @@ if [ $skipinstall != yes ]; then SITEPACKAGES=/Library/Python/$PYVER fi + # move the common files to $INSTALLCOMMON + mkdir -p $INSTALLCOMMON$SITEPACKAGES + mv $INSTALLROOT$SITEPACKAGES/wx.pth $INSTALLCOMMON$SITEPACKAGES + mv $INSTALLROOT$SITEPACKAGES/wxversion.py $INSTALLCOMMON$SITEPACKAGES - # install wxPython's tool scripts - mkdir -p $INSTALLROOT$BINPREFIX + # install wxPython's tool scripts in COMMON too + mkdir -p $INSTALLCOMMON$BINPREFIX cd $WXDIR/wxPython/scripts - python$PYVER CreateMacScripts.py $INSTALLROOT $BINPREFIX + python$PYVER CreateMacScripts.py $INSTALLCOMMON $BINPREFIX + + # Remove the .pyc/.pyo files they just take up space and can be recreated + # during the install. + pushd $WXDIR/wxPython + $PYTHON $PROGDIR/../zappycfiles.py $INSTALLROOT > /dev/null + popd - # Set premissions for files in $INSTALLROOT + # Set premissions for files in $INSTALLROOT and $INSTALLCOMMON if [ "$UID" = "0" ]; then - chown -R root:admin $INSTALLROOT - chmod -R g+w $INSTALLROOT + chown -R root:admin $INSTALLROOT $INSTALLCOMMON + chmod -R g+w $INSTALLROOT $INSTALLCOMMON fi fi -PKGDIR=`cat $INSTALLROOT/Library/Python/$PYVER/wx.pth` +if [ "$KIND" = "panther" ]; then + SITEPACKAGES=/Library/Python/$PYVER +fi +PKGDIR=`cat $INSTALLCOMMON$SITEPACKAGES/wx.pth` popd @@ -286,22 +317,27 @@ popd # Make the Installer packages and disk image if [ $skipdmg != yes ]; then - # Remove the .pyc/.pyo files they just take up space and can be recreated - # during the install. - $PYTHON $PROGDIR/../zappycfiles.py $INSTALLROOT > /dev/null - + #----------------------------------------------- + # The main runtime installer package # Make the welcome message case $KIND in panther) W_MSG="the Panther (OS X 10.3.x) version of" ;; jaguar) W_MSG="the Jaguar (OS X 10.2.x) version of" ;; esac + + cat > $RESOURCEDIR/Welcome.txt < "$DMGDIR/root/README 1st.txt" < $RESOURCEDIR/Welcome.txt < "$DMGROOT/README 1st.txt" < "$DMGAPPS/README 1st.txt" < "$DMGDIR/root/Docs/Build ERROR.txt" < "$DMGAPPS/Docs/Build ERROR.txt" < "$DMGDIR/root/Docs/README 1st.txt" < "$DMGAPPS/Docs/README 1st.txt" < "$DMGDIR/root/Samples/Build ERROR.txt" < "$DMGAPPS/Samples/Build ERROR.txt" <