+#----------------------------------------------------------------------
+# Name: __init__.py
+# Purpose: Import logic and common functions for wxaddons module
+#
+# Author: Kevin Ollivier
+#
+# Created: 15-Nov-2006
+# RCS-ID: $Id$
+# Copyright: (c) 2006 Kevin Ollivier
+# Licence: wxWindows license
+#----------------------------------------------------------------------
+
+import sys, os, string
+import xmlrpclib
+import __builtin__
+import wx
+
+# NB: For some reason that I haven't been able to track down, on Mac (at least)
+# calling xmlrpc methods no longer works after the wx.App is started. Therefore,
+# we grab the package URL even before prompting the user if they want to install
+# the package in order for us to have the info we need before the wx.App is started.
+
+domain = 'http://wxaddons.wxcommunity.com'
+builtin_import = __builtin__.__import__
+
+debug = False
+use_gui = True
+checkImports = True
+config = wx.Config("wxaddons")
+if config.Read("PerformChecks", "true") != "true":
+ checkImports = False
+
+if use_gui and not wx.App.IsDisplayAvailable():
+ use_gui = False
+
+s = xmlrpclib.Server('%s/xmlrpc-server.php' % domain, verbose=(debug == True))
+
+def check_imports(check):
+ if check:
+ config.Write("PerformChecks", "true")
+ else:
+ config.Write("PerformChecks", "false")
+
+def version_greater_than_or_equal(version1, version2):
+ """
+ Checks if version1 >= version2, returning true if so,
+ false if otherwise.
+ """
+ greater_than = True
+
+ for index in range(0, len(version1)-1):
+ if version1[index] > version2[index]:
+ greater_than = True
+ break
+ elif version[index] < current_version[index]:
+ greater_than = False
+ break
+
+ return greater_than
+
+def prompt_install(name, version):
+ should_install = False
+ message = "The wxaddon %s is not installed, but was found on the wxaddons site. Would you like to download and install it?" % (name + " " + version)
+ if use_gui:
+ app = wx.PySimpleApp()
+ app.MainLoop()
+ result = wx.MessageBox(message, "Install Dependency?", style=wx.YES_NO)
+ if result == wx.YES:
+ should_install = True
+ else:
+ result = raw_input(message + " [y/n]")
+ if result[0].lower() == "y":
+ should_install = True
+
+ return should_install
+
+def require_addon_version(name, version=[], canBeNewer=True):
+ # Check the install receipt to see if we've got an appropriate version
+ config = wx.Config("wxaddons-receipts")
+ needs_update = True
+ if config.HasGroup(name):
+ config.SetPath(name)
+ current_version = config.Read("version", "0.0").split(".")
+
+ needs_update = version_greater_than_or_equal(version, current_version)
+
+ if needs_update:
+ comp_xml = s.getComponent(name)
+ if not comp_xml:
+ raise
+
+ comp = xmlrpclib.loads(comp_xml)[0][0]
+ comp_version = comp["version"].split(".")
+
+ update_comp = False
+ if canBeNewer:
+ update_comp = version_greater_than_or_equal(comp_version, version)
+ else:
+ update_comp = (version == comp_version)
+
+ if update_comp:
+ url = get_url(name, version)
+ should_install = prompt_install(name, comp_version)
+
+ if should_install:
+ dl_and_install_addon(name, comp_version, url)
+
+def get_url(name, version):
+ url = ""
+ release_xml = s.getReleases(name)
+ if not release_xml:
+ return ""
+
+ releases = xmlrpclib.loads(release_xml)[0][0]
+ for release in releases:
+ if release['version'] == version:
+ url = release['url']
+
+ return url
+
+def dl_and_install_addon(name, version, url):
+ installed = True
+ tempdir = None
+ cwd = os.getcwd()
+
+ if use_gui:
+ progress = wx.ProgressDialog("Installing Dependency",
+ "Preparing to install the %s addon module." % name,
+ 4,
+ style=wx.PD_APP_MODAL|wx.PD_SMOOTH)
+
+ message = "Downloading tarball..."
+ print message
+ if use_gui: progress.Update(1, message)
+ import urllib
+ temp_archive, headers = urllib.urlretrieve(url)
+
+ message = "Extracting files..."
+ print message
+ if use_gui: progress.Update(2, message)
+ import tempfile
+ tempdir = tempfile.mkdtemp()
+
+ os.chdir(tempdir)
+ import tarfile
+ tar = tarfile.open(temp_archive, "r:gz")
+ for tarinfo in tar:
+ tar.extract(tarinfo)
+ tar.close()
+
+ os.chdir(name)
+
+ message = "Installing %s" % name
+ if use_gui: progress.Update(3, message)
+ # TODO: Add support for modified PYTHONPATH?
+ # Also, do we need admin install support here?
+ retval = os.system(sys.executable + " " + string.join(("setup.py", "install"), " "))
+ if use_gui: progress.Update(4)
+
+ if retval == 0:
+ message = "The %s addon was successfully installed." % name
+ print message
+ if use_gui:
+ wx.MessageBox(message, "Installation Successful")
+ else:
+ installed = False
+
+ # cleanup
+ if use_gui: progress.Destroy()
+ os.chdir(cwd)
+ import shutil
+ shutil.rmtree(tempdir)
+ os.remove(temp_archive)
+
+ return installed
+
+def import_hook(name, globals=None, locals=None, fromlist=None):
+ # Fast path: see if the module has already been imported.
+ try:
+ return builtin_import(name, globals, locals, fromlist)
+ except:
+ if name.startswith("wxaddons"):
+ print "Querying %s for module." % domain
+ try:
+ modname = name.split(".")[1]
+ comp = None
+ comp_xml = s.getComponent(modname)
+ if not comp_xml:
+ raise
+
+ comp = xmlrpclib.loads(comp_xml)[0][0]
+ url = get_url(comp["name"], comp["version"])
+ should_install = prompt_install(comp["name"], comp["version"])
+
+ if should_install:
+ try:
+ success = dl_and_install_addon(comp["name"], comp["version"], url)
+ if not success:
+ raise
+ except:
+ raise
+
+
+ except:
+ raise
+ else:
+ raise
+
+def runTests():
+ import wxaddons.persistence
+ import wxaddons.foo_bar
+ import googly
+
+if checkImports:
+ __builtin__.__import__ = import_hook
+