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
This commit is contained in:
		
							
								
								
									
										196
									
								
								wxPython/distrib/mac/uninstall_wxPython.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										196
									
								
								wxPython/distrib/mac/uninstall_wxPython.py
									
									
									
									
									
										Executable file
									
								
							@@ -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()
 | 
			
		||||
		Reference in New Issue
	
	Block a user