]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxaddons/__init__.py
Yielding from a non-gui thread needs to bail out, otherwise we end up
[wxWidgets.git] / wxPython / wxaddons / __init__.py
1 #----------------------------------------------------------------------
2 # Name: __init__.py
3 # Purpose: Import logic and common functions for wxaddons module
4 #
5 # Author: Kevin Ollivier
6 #
7 # Created: 15-Nov-2006
8 # RCS-ID: $Id$
9 # Copyright: (c) 2006 Kevin Ollivier
10 # Licence: wxWindows license
11 #----------------------------------------------------------------------
12
13 import sys, os, string
14 import xmlrpclib
15 import __builtin__
16 import wx
17
18 # NB: For some reason that I haven't been able to track down, on Mac (at least)
19 # calling xmlrpc methods no longer works after the wx.App is started. Therefore,
20 # we grab the package URL even before prompting the user if they want to install
21 # the package in order for us to have the info we need before the wx.App is started.
22
23 domain = 'http://wxaddons.wxcommunity.com'
24 builtin_import = __builtin__.__import__
25
26 debug = False
27 use_gui = True
28 checkImports = True
29 config = wx.Config("wxaddons")
30 if config.Read("PerformChecks", "true") != "true":
31 checkImports = False
32
33 if use_gui and not wx.App.IsDisplayAvailable():
34 use_gui = False
35
36 s = xmlrpclib.Server('%s/xmlrpc-server.php' % domain, verbose=(debug == True))
37
38 def check_imports(check):
39 if check:
40 config.Write("PerformChecks", "true")
41 else:
42 config.Write("PerformChecks", "false")
43
44 def version_greater_than_or_equal(version1, version2):
45 """
46 Checks if version1 >= version2, returning true if so,
47 false if otherwise.
48 """
49 greater_than = True
50
51 for index in range(0, len(version1)-1):
52 if version1[index] > version2[index]:
53 greater_than = True
54 break
55 elif version[index] < current_version[index]:
56 greater_than = False
57 break
58
59 return greater_than
60
61 def prompt_install(name, version):
62 should_install = False
63 message = "The wxaddon %s is not installed, but was found on the wxaddons site. Would you like to download and install it?" % (name + " " + version)
64 if use_gui:
65 app = wx.PySimpleApp()
66 app.MainLoop()
67 result = wx.MessageBox(message, "Install Dependency?", style=wx.YES_NO)
68 if result == wx.YES:
69 should_install = True
70 else:
71 result = raw_input(message + " [y/n]")
72 if result[0].lower() == "y":
73 should_install = True
74
75 return should_install
76
77 def require_addon_version(name, version=[], canBeNewer=True):
78 # Check the install receipt to see if we've got an appropriate version
79 config = wx.Config("wxaddons-receipts")
80 needs_update = True
81 if config.HasGroup(name):
82 config.SetPath(name)
83 current_version = config.Read("version", "0.0").split(".")
84
85 needs_update = version_greater_than_or_equal(version, current_version)
86
87 if needs_update:
88 comp_xml = s.getComponent(name)
89 if not comp_xml:
90 raise
91
92 comp = xmlrpclib.loads(comp_xml)[0][0]
93 comp_version = comp["version"].split(".")
94
95 update_comp = False
96 if canBeNewer:
97 update_comp = version_greater_than_or_equal(comp_version, version)
98 else:
99 update_comp = (version == comp_version)
100
101 if update_comp:
102 url = get_url(name, version)
103 should_install = prompt_install(name, comp_version)
104
105 if should_install:
106 dl_and_install_addon(name, comp_version, url)
107
108 def get_url(name, version):
109 url = ""
110 release_xml = s.getReleases(name)
111 if not release_xml:
112 return ""
113
114 releases = xmlrpclib.loads(release_xml)[0][0]
115 for release in releases:
116 if release['version'] == version:
117 url = release['url']
118
119 return url
120
121 def dl_and_install_addon(name, version, url):
122 installed = True
123 tempdir = None
124 cwd = os.getcwd()
125
126 if use_gui:
127 progress = wx.ProgressDialog("Installing Dependency",
128 "Preparing to install the %s addon module." % name,
129 4,
130 style=wx.PD_APP_MODAL|wx.PD_SMOOTH)
131
132 message = "Downloading tarball..."
133 print message
134 if use_gui: progress.Update(1, message)
135 import urllib
136 temp_archive, headers = urllib.urlretrieve(url)
137
138 message = "Extracting files..."
139 print message
140 if use_gui: progress.Update(2, message)
141 import tempfile
142 tempdir = tempfile.mkdtemp()
143
144 os.chdir(tempdir)
145 import tarfile
146 tar = tarfile.open(temp_archive, "r:gz")
147 for tarinfo in tar:
148 tar.extract(tarinfo)
149 tar.close()
150
151 os.chdir(name)
152
153 message = "Installing %s" % name
154 if use_gui: progress.Update(3, message)
155 # TODO: Add support for modified PYTHONPATH?
156 # Also, do we need admin install support here?
157 retval = os.system(sys.executable + " " + string.join(("setup.py", "install"), " "))
158 if use_gui: progress.Update(4)
159
160 if retval == 0:
161 message = "The %s addon was successfully installed." % name
162 print message
163 if use_gui:
164 wx.MessageBox(message, "Installation Successful")
165 else:
166 installed = False
167
168 # cleanup
169 if use_gui: progress.Destroy()
170 os.chdir(cwd)
171 import shutil
172 shutil.rmtree(tempdir)
173 os.remove(temp_archive)
174
175 return installed
176
177 def import_hook(name, globals=None, locals=None, fromlist=None):
178 # Fast path: see if the module has already been imported.
179 try:
180 return builtin_import(name, globals, locals, fromlist)
181 except:
182 if name.startswith("wxaddons"):
183 print "Querying %s for module." % domain
184 try:
185 modname = name.split(".")[1]
186 comp = None
187 comp_xml = s.getComponent(modname)
188 if not comp_xml:
189 raise
190
191 comp = xmlrpclib.loads(comp_xml)[0][0]
192 url = get_url(comp["name"], comp["version"])
193 should_install = prompt_install(comp["name"], comp["version"])
194
195 if should_install:
196 try:
197 success = dl_and_install_addon(comp["name"], comp["version"], url)
198 if not success:
199 raise
200 except:
201 raise
202
203
204 except:
205 raise
206 else:
207 raise
208
209 def runTests():
210 import wxaddons.persistence
211 import wxaddons.foo_bar
212 import googly
213
214 if checkImports:
215 __builtin__.__import__ = import_hook
216