]> git.saurik.com Git - wxWidgets.git/blob - wxPython/distrib/mac/uninstall_wxPython.py
Use a working dir for the uninstaller that does exist.
[wxWidgets.git] / wxPython / distrib / mac / uninstall_wxPython.py
1 #!/usr/bin/env python
2 """
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.
7
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
12 yourself.
13 """
14
15 import sys, os, glob
16 import cPickle, urllib
17
18 RCPTDIR = "/Library/Receipts"
19 RSRCDIR = "Contents/Resources"
20
21 # only clean up dirs that have one of these as a prefix. We do this
22 # because the file list returned from lsbom will include /, /usr,
23 # /usr/local, etc.
24 PREFIXES = [ '/Library/Python/2.3/',
25 '/Library/Python/2.4/',
26 '/usr/local/lib/',
27 ]
28
29
30 class AccessError(Exception):
31 pass
32
33
34 class InstalledReceipt(object):
35 def __init__(self, rcptPath):
36 self.rcptPath = rcptPath
37 self.rsrcPath = os.path.join(rcptPath, RSRCDIR)
38 self.bomFile = glob.glob(os.path.join(self.rsrcPath, "*.bom"))[0]
39 self.findMetaData()
40
41
42 def findMetaData(self):
43 # TODO: Make this be able to also look at Info.plist files
44 infoFile = glob.glob(os.path.join(self.rsrcPath, "*.info"))[0]
45 self.mdata = {}
46 for line in open(infoFile, "r").readlines():
47 line = line.strip()
48 if line and line[0] != '#':
49 ls = line.split()
50 self.mdata[ls[0]] = line[len(ls[0])+1:]
51
52
53 def getFileList(self):
54 p = os.popen("lsbom -s %s" % self.bomFile, "r")
55 data = p.read()
56 data.strip()
57 data = filter(lambda s: s!='' and s!='.', data.split('\n'))
58 loc = self.mdata['DefaultLocation']
59 return [loc+item for item in data]
60
61
62 def walkFiles(self, handleFile, handleDir):
63 dirs = []
64 names = self.getFileList()
65
66 # the plain files
67 for name in names:
68 name = os.path.abspath(name)
69 if os.path.isdir(name):
70 dirs.append(name)
71 else:
72 handleFile(name)
73
74 # the directories
75 dirs.reverse()
76 for dir in dirs:
77 for prefix in PREFIXES:
78 if dir.startswith(prefix):
79 handleDir(dir)
80 break
81
82 # Finally, remove the Receipts package, bottom-up
83 for dirpath, dirname, filenames in os.walk(self.rcptPath, False):
84 for name in filenames:
85 name = os.path.join(dirpath, name)
86 handleFile(name)
87 handleDir(dirpath)
88
89
90
91 def showFiles(self):
92 def show(name):
93 if os.path.exists(name):
94 print "Will remove:", name
95 self.walkFiles(show, show)
96
97
98 def testUninstallAccess(self):
99 def testFile(name):
100 if os.path.exists(name):
101 if not os.access(name, os.W_OK):
102 raise AccessError(name)
103 self.walkFiles(testFile, testFile)
104
105
106 def doUninstall(self):
107 def removeFile(name):
108 if os.path.exists(name):
109 print "Removing:", name
110 os.unlink(name)
111 def removeDir(name):
112 print "Removing:", name
113 if os.path.exists(name):
114 hasFiles = os.listdir(name)
115 if hasFiles: # perhaps some left over symlinks, or .pyc files
116 for file in hasFiles:
117 os.unlink(os.path.join(name, file))
118 os.rmdir(name)
119
120 try:
121 self.testUninstallAccess()
122 except AccessError, e:
123 print "UNABLE TO UNINSTALL!\nNo permission to remove: ", e.args[0]
124 sys.exit()
125
126 self.walkFiles(removeFile, removeDir)
127
128
129
130
131 def findInstalled():
132 installed = []
133 for name in glob.glob(os.path.join(RCPTDIR, "wxPython*")):
134 ir = InstalledReceipt(name)
135 installed.append(ir)
136
137 return installed
138
139
140 # Just in case a Python < 2.3 is used to run this
141 try:
142 enumerate
143 except NameError:
144 def enumerate(sequence):
145 return zip(range(len(sequence)), sequence)
146
147
148 def main():
149 if len(sys.argv) > 1 and sys.argv[1] == "-doit":
150 inst = cPickle.loads(urllib.unquote(sys.argv[2]))
151 inst.doUninstall()
152 sys.exit()
153
154 print __doc__
155 installed = findInstalled()
156
157 if not installed:
158 print "*** No wxPython installations found! ***"
159 raw_input("Press RETURN...")
160 sys.exit()
161
162 for i, inst in enumerate(installed):
163 print " %d. %s \t%s" % (i+1, inst.mdata["Title"], inst.mdata["Version"])
164
165 print
166 ans = raw_input("Enter the number of the install to examine or 'Q' to quit: ")
167 if ans in ['Q', 'q']:
168 sys.exit()
169 inst = installed[int(ans) - 1]
170
171 while True:
172 print
173 print """
174 Title: %(Title)s
175 Version: %(Version)s
176 Description: %(Description)s
177 """ % inst.mdata
178
179 ans = raw_input("(U)ninstall, (S)how what will be removed, or (Q)uit? [u,s,q] ")
180 if ans in ['Q', 'q']:
181 sys.exit()
182
183 elif ans in ['S', 's']:
184 inst.showFiles()
185
186 elif ans in ['U', 'u']:
187 print
188 print "Launching uninstaller with sudo, please enter your password if prompted:"
189 os.system("sudo %s -doit %s" %
190 (sys.argv[0],
191 urllib.quote(cPickle.dumps(inst))))
192 sys.exit()
193
194
195 if __name__ == '__main__':
196 main()