]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/distrib/mac/uninstall_wxPython.py
   3 This script will search for installed versions of wxPython on OSX and 
   4 allow the user to choose one to uninstall.  It then will use the 
   5 metadata stored about the installed package to remove all the files 
   6 associated with that install. 
   8 Only the files installed by the main Installer Package will be 
   9 removed.  This includes the Python modules and the wxWidgets shared 
  10 libraries. If you also installed the demo or docs by dragging them out 
  11 of the disk image, then you will need to drag them to the Trash 
  16 from fnmatch 
import fnmatchcase
 
  17 import cPickle
, urllib
 
  19 RCPTDIR 
= "/Library/Receipts" 
  20 RSRCDIR 
= "Contents/Resources" 
  22 # Only completly clean out dirs that have one of these as a prefix. 
  23 # We do this because the file list returned from lsbom will include /, 
  24 # /usr, /usr/local, etc. 
  25 PREFIXES 
= [ '/Library/Python/2.3/', 
  26              '/Library/Python/2.4/', 
  27              '/Library/Python/2.5/', 
  28              '/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/site-packages/', 
  29              '/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/', 
  30              '/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/', 
  34 # The files that match one of the items in this list will only be 
  35 # removed if the last installation of wxPython on the system is being 
  37 COMMON_FILES 
= [ '/usr/local/bin/*', 
  44 class AccessError(Exception): 
  47 class ReceiptError(Exception): 
  51 class InstalledReceipt(object): 
  52     def __init__(self
, rcptPath
): 
  53         self
.rcptPath 
= rcptPath
 
  54         self
.rsrcPath 
= os
.path
.join(rcptPath
, RSRCDIR
) 
  55         bf 
= glob
.glob(os
.path
.join(self
.rsrcPath
, "*.bom")) 
  59             print "WARNING: Unable to find %s/*.bom" % self
.rsrcPath
 
  64     def findMetaData(self
): 
  65         # TODO: Make this be able to also look at Info.plist files 
  66         infoFiles 
= glob
.glob(os
.path
.join(self
.rsrcPath
, "*.info")) 
  68             # there should be only one 
  69             infoFile 
= infoFiles
[0] 
  71             for line 
in open(infoFile
, "r").readlines(): 
  73                 if line 
and line
[0] != '#': 
  75                     self
.mdata
[ls
[0]] = line
[len(ls
[0])+1:] 
  77             print "WARNING: Unable to find %s/*.info" % self
.rsrcPath
 
  81     def getFileList(self
): 
  82         p 
= os
.popen("lsbom -s %s" % self
.bomFile
, "r") 
  85         data 
= filter(lambda s
: s
!='' and s
!='.', data
.split('\n')) 
  86         loc 
= self
.mdata
['DefaultLocation'] 
  87         return [loc
+item 
for item 
in data
] 
  90     def walkFiles(self
, handleFile
, handleDir
): 
  92         names 
= self
.getFileList() 
  96             name 
= os
.path
.abspath(name
) 
  97             if os
.path
.isdir(name
): 
 105             for prefix 
in PREFIXES
: 
 106                 if dir.startswith(prefix
): 
 110         # Finally, remove the Receipts package, bottom-up 
 111         for dirpath
, dirname
, filenames 
in os
.walk(self
.rcptPath
, False): 
 112             for name 
in filenames
: 
 113                 name 
= os
.path
.join(dirpath
, name
) 
 117     # wxaddons should be always kept as the user may have installed 
 118     # third-party modules seperate from wxpython. 
 119     def testWxaddons(self
, name
): 
 120         for prefix 
in PREFIXES
: 
 121             if name
.startswith(prefix 
+ "wxaddons"): 
 125     def testCommon(self
, name
): 
 126         for cmn 
in COMMON_FILES
: 
 127             if fnmatchcase(name
, cmn
) or fnmatchcase(os
.path
.basename(name
), cmn
): 
 134             if os
.path
.exists(name
): 
 135                 if not self
.lastInstall 
and self
.testCommon(name
): 
 137                 if self
.testWxaddons(name
): 
 139                 print "Will remove:", name
 
 140         self
.walkFiles(show
, show
) 
 143     def testUninstallAccess(self
): 
 145             if os
.path
.exists(name
): 
 146                 if not self
.lastInstall 
and self
.testCommon(name
): 
 148                 if not os
.access(name
, os
.W_OK
): 
 149                     raise AccessError(name
) 
 150         self
.walkFiles(testFile
, testFile
) 
 153     def doUninstall(self
): 
 154         def removeFile(name
): 
 155             if os
.path
.exists(name
): 
 156                 if not self
.lastInstall 
and self
.testCommon(name
): 
 158                 if self
.testWxaddons(name
): 
 160                 print "Removing:", name
 
 163             print "Removing:", name
 
 164             if os
.path
.exists(name
) and not self
.testWxaddons(name
): 
 165                 hasFiles 
= os
.listdir(name
) 
 166                 if hasFiles
:  # perhaps some stale symlinks, or .pyc files 
 167                     for file in hasFiles
: 
 168                         os
.unlink(os
.path
.join(name
, file)) 
 172             self
.testUninstallAccess() 
 173         except AccessError
, e
: 
 174             print "UNABLE TO UNINSTALL!\nNo permission to remove: ", e
.args
[0] 
 177         self
.walkFiles(removeFile
, removeDir
) 
 184     for name 
in glob
.glob(os
.path
.join(RCPTDIR
, "wxPython*")): 
 186             ir 
= InstalledReceipt(name
) 
 189             pass  # just skip it... 
 194 # Just in case a Python < 2.3 is used to run this 
 198     def enumerate(sequence
): 
 199         return zip(range(len(sequence
)), sequence
) 
 203     if len(sys
.argv
) > 1 and sys
.argv
[1] == "-doit": 
 204         inst 
= cPickle
.loads(urllib
.unquote(sys
.argv
[2])) 
 209     installed 
= findInstalled() 
 212         print "*** No wxPython installations found!  ***" 
 213         raw_input("Press RETURN...") 
 216     for i
, inst 
in enumerate(installed
): 
 217         print " %2d.  %-40s    %s" % (i
+1, inst
.mdata
["Title"], inst
.mdata
["Version"]) 
 220     ans 
= raw_input("Enter the number of the install to examine or 'Q' to quit: ") 
 221     if ans 
in ['Q', 'q']: 
 223     inst 
= installed
[int(ans
) - 1] 
 224     inst
.lastInstall 
= len(installed
) == 1 
 231         Description: %(Description)s 
 234         ans 
= raw_input("(U)ninstall, (S)how what will be removed, or (Q)uit? [u,s,q] ") 
 235         if ans 
in ['Q', 'q']: 
 238         elif ans 
in ['S', 's']: 
 241         elif ans 
in ['U', 'u']: 
 243             print "Launching uninstaller with sudo, please enter your password if prompted:" 
 244             os
.system("sudo %s -doit %s" % 
 246                        urllib
.quote(cPickle
.dumps(inst
)))) 
 250 if __name__ 
== '__main__':