]>
Commit | Line | Data |
---|---|---|
61a0bf7c KO |
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 | ||
8c065688 KO |
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' | |
61a0bf7c KO |
24 | builtin_import = __builtin__.__import__ |
25 | ||
26 | debug = False | |
27 | use_gui = True | |
50010572 KO |
28 | checkImports = True |
29 | config = wx.Config("wxaddons") | |
30 | if config.Read("PerformChecks", "true") != "true": | |
31 | checkImports = False | |
61a0bf7c KO |
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)) | |
50010572 KO |
37 | |
38 | def check_imports(check): | |
39 | if check: | |
40 | config.Write("PerformChecks", "true") | |
41 | else: | |
42 | config.Write("PerformChecks", "false") | |
43 | ||
61a0bf7c KO |
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: | |
8c065688 | 106 | dl_and_install_addon(name, comp_version, url) |
61a0bf7c KO |
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 | ||
61a0bf7c KO |
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(): | |
8c065688 | 210 | import wxaddons.persistence |
61a0bf7c KO |
211 | import wxaddons.foo_bar |
212 | import googly | |
213 | ||
50010572 KO |
214 | if checkImports: |
215 | __builtin__.__import__ = import_hook | |
61a0bf7c | 216 |