]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/wxversion/wxversion.py
move wxPython to new trunk
[wxWidgets.git] / wxPython / wxversion / wxversion.py
diff --git a/wxPython/wxversion/wxversion.py b/wxPython/wxversion/wxversion.py
deleted file mode 100644 (file)
index cd10d44..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-#----------------------------------------------------------------------
-# Name:        wxversion
-# Purpose:     Allows a wxPython program to search for alternate 
-#              installations of the wxPython packages and modify sys.path
-#              so they will be found when "import wx" is done.
-#
-# Author:      Robin Dunn
-#
-# Created:     24-Sept-2004
-# RCS-ID:      $Id$
-# Copyright:   (c) 2004 by Total Control Software
-# Licence:     wxWindows license
-#----------------------------------------------------------------------
-
-"""
-If you have more than one version of wxPython installed this module
-allows your application to choose which version of wxPython will be
-imported when it does 'import wx'.  The main function of this module
-is `select` and you use it like this::
-
-    import wxversion
-    wxversion.select('2.4')
-    import wx
-
-Or additional build options can also be selected, although they will
-not be required if they are not installed, like this::
-
-    import wxversion
-    wxversion.select('2.5.3-unicode')
-    import wx
-
-Or you can require an exact match on the build options like this::
-
-    import wxversion
-    wxversion.select('2.5.3-unicode', optionsRequired=True)
-    import wx
-
-Finally you can also specify a collection of versions that are allowed
-by your application, like this::
-
-    import wxversion
-    wxversion.select(['2.5.4', '2.5.5', '2.6'])
-    import wx
-
-
-Of course the default wxPython version can also be controlled by
-setting PYTHONPATH or by editing the wx.pth path configuration file,
-but using wxversion will allow an application to manage the version
-selection itself rather than depend on the user to setup the
-environment correctly.
-
-It works by searching the sys.path for directories matching wx-* and
-then comparing them to what was passed to the select function.  If a
-match is found then that path is inserted into sys.path.
-
-NOTE: If you are making a 'bundle' of your application with a tool
-like py2exe then you should *not* use the wxversion module since it
-looks at the filesystem for the directories on sys.path, it will fail
-in a bundled environment.  Instead you should simply ensure that the
-version of wxPython that you want is found by default on the sys.path
-when making the bundled version by setting PYTHONPATH.  Then that
-version will be included in your bundle and your app will work as
-expected.  Py2exe and the others usually have a way to tell at runtime
-if they are running from a bundle or running raw, so you can check
-that and only use wxversion if needed.  For example, for py2exe::
-
-    if not hasattr(sys, 'frozen'):
-        import wxversion
-        wxversion.select('2.5')
-    import wx
-
-More documentation on wxversion and multi-version installs can be
-found at: http://wiki.wxpython.org/index.cgi/MultiVersionInstalls
-
-"""
-
-import re, sys, os, glob, fnmatch
-
-
-_selected = None
-class VersionError(Exception):
-    pass
-
-#----------------------------------------------------------------------
-
-def select(versions, optionsRequired=False):
-    """
-    Search for a wxPython installation that matches version.  If one
-    is found then sys.path is modified so that version will be
-    imported with a 'import wx', otherwise a VersionError exception is
-    raised.  This funciton should only be caled once at the begining
-    of the application before wxPython is imported.
-
-        :param versions: Specifies the version to look for, it can
-            either be a string or a list of strings.  Each string is
-            compared to the installed wxPythons and the best match is
-            inserted into the sys.path, allowing an 'import wx' to
-            find that version.
-
-            The version string is composed of the dotted version
-            number (at least 2 of the 4 components) optionally
-            followed by hyphen ('-') separated options (wx port,
-            unicode/ansi, flavour, etc.)  A match is determined by how
-            much of the installed version matches what is given in the
-            version parameter.  If the version number components don't
-            match then the score is zero, otherwise the score is
-            increased for every specified optional component that is
-            specified and that matches.
-
-            Please note, however, that it is possible for a match to
-            be selected that doesn't exactly match the versions
-            requested.  The only component that is required to be
-            matched is the version number.  If you need to require a
-            match on the other components as well, then please use the
-            optional ``optionsRequired`` parameter described next.
-
-        :param optionsRequired: Allows you to specify that the other
-             components of the version string (such as the port name
-             or character type) are also required to be present for an
-             installed version to be considered a match.  Using this
-             parameter allows you to change the selection from a soft,
-             as close as possible match to a hard, exact match.
-        
-    """
-    if type(versions) == str:
-        versions = [versions]
-
-    global _selected
-    if _selected is not None:
-        # A version was previously selected, ensure that it matches
-        # this new request
-        for ver in versions:
-            if _selected.Score(_wxPackageInfo(ver), optionsRequired) > 0:
-                return
-        # otherwise, raise an exception
-        raise VersionError("A previously selected wx version does not match the new request.")
-
-    # If we get here then this is the first time wxversion is used, 
-    # ensure that wxPython hasn't been imported yet.
-    if sys.modules.has_key('wx') or sys.modules.has_key('wxPython'):
-        raise VersionError("wxversion.select() must be called before wxPython is imported")
-    
-    # Look for a matching version and manipulate the sys.path as
-    # needed to allow it to be imported.
-    installed = _find_installed(True)
-    bestMatch = _get_best_match(installed, versions, optionsRequired)
-    
-    if bestMatch is None:
-        raise VersionError("Requested version of wxPython not found")
-
-    sys.path.insert(0, bestMatch.pathname)
-    # q.v. Bug #1409256
-    path64 = re.sub('/lib/','/lib64/',bestMatch.pathname)
-    if os.path.isdir(path64):
-        sys.path.insert(0, path64)
-    _selected = bestMatch
-        
-#----------------------------------------------------------------------
-
-UPDATE_URL = "http://wxPython.org/"
-#UPDATE_URL = "http://sourceforge.net/project/showfiles.php?group_id=10718"
-
-_EM_DEBUG=0
-
-def ensureMinimal(minVersion, optionsRequired=False):
-    """
-    Checks to see if the default version of wxPython is greater-than
-    or equal to `minVersion`.  If not then it will try to find an
-    installed version that is >= minVersion.  If none are available
-    then a message is displayed that will inform the user and will
-    offer to open their web browser to the wxPython downloads page,
-    and will then exit the application.
-    """
-    assert type(minVersion) == str
-
-    # ensure that wxPython hasn't been imported yet.
-    if sys.modules.has_key('wx') or sys.modules.has_key('wxPython'):
-        raise VersionError("wxversion.ensureMinimal() must be called before wxPython is imported")
-
-    bestMatch = None
-    minv = _wxPackageInfo(minVersion)
-
-    # check the default version first
-    defaultPath = _find_default()
-    if defaultPath:
-        defv = _wxPackageInfo(defaultPath, True)
-        if defv >= minv and minv.CheckOptions(defv, optionsRequired):
-            bestMatch = defv
-
-    # if still no match then check look at all installed versions
-    if bestMatch is None:
-        installed = _find_installed()
-        # The list is in reverse sorted order, so find the first
-        # one that is big enough and optionally matches the
-        # options
-        for inst in installed:
-            if inst >= minv and minv.CheckOptions(inst, optionsRequired):
-                bestMatch = inst
-                break
-
-    # if still no match then prompt the user
-    if bestMatch is None:
-        if _EM_DEBUG: # We'll do it this way just for the test code below
-            raise VersionError("Requested version of wxPython not found")
-        
-        import wx, webbrowser
-        versions = "\n".join(["      "+ver for ver in getInstalled()])
-        app = wx.PySimpleApp()
-        result = wx.MessageBox("This application requires a version of wxPython "
-                               "greater than or equal to %s, but a matching version "
-                               "was not found.\n\n"
-                               "You currently have these version(s) installed:\n%s\n\n"
-                               "Would you like to download a new version of wxPython?\n"
-                               % (minVersion, versions),
-                      "wxPython Upgrade Needed", style=wx.YES_NO)
-        if result == wx.YES:
-            webbrowser.open(UPDATE_URL)
-        app.MainLoop()
-        sys.exit()
-
-    sys.path.insert(0, bestMatch.pathname)
-    # q.v. Bug #1409256
-    path64 = re.sub('/lib/','/lib64/',bestMatch.pathname)
-    if os.path.isdir(path64):
-        sys.path.insert(0, path64)
-    global _selected
-    _selected = bestMatch
-        
-
-#----------------------------------------------------------------------
-
-def checkInstalled(versions, optionsRequired=False):
-    """
-    Check if there is a version of wxPython installed that matches one
-    of the versions given.  Returns True if so, False if not.  This
-    can be used to determine if calling `select` will succeed or not.
-
-        :param versions: Same as in `select`, either a string or a list
-            of strings specifying the version(s) to check for.
-
-        :param optionsRequired: Same as in `select`.
-    """
-    
-    if type(versions) == str:
-        versions = [versions]
-    installed = _find_installed()
-    bestMatch = _get_best_match(installed, versions, optionsRequired)
-    return bestMatch is not None
-
-#----------------------------------------------------------------------
-
-def getInstalled():
-    """
-    Returns a list of strings representing the installed wxPython
-    versions that are found on the system.
-    """
-    installed = _find_installed()
-    return [os.path.basename(p.pathname)[3:] for p in installed]
-
-
-
-#----------------------------------------------------------------------
-# private helpers...
-
-def _get_best_match(installed, versions, optionsRequired):
-    bestMatch = None
-    bestScore = 0
-    for pkg in installed:
-        for ver in versions:
-            score = pkg.Score(_wxPackageInfo(ver), optionsRequired)
-            if score > bestScore:
-                bestMatch = pkg
-                bestScore = score
-    return bestMatch
-
-
-_pattern = "wx-[0-9].*"
-def _find_installed(removeExisting=False):
-    installed = []
-    toRemove = []
-    for pth in sys.path:
-
-        # empty means to look in the current dir
-        if not pth:
-            pth = '.'
-
-        # skip it if it's not a package dir
-        if not os.path.isdir(pth):
-            continue
-        
-        base = os.path.basename(pth)
-
-        # if it's a wx path that's already in the sys.path then mark
-        # it for removal and then skip it
-        if fnmatch.fnmatchcase(base, _pattern):
-            toRemove.append(pth)
-            continue
-
-        # now look in the dir for matching subdirs
-        for name in glob.glob(os.path.join(pth, _pattern)):
-            # make sure it's a directory
-            if not os.path.isdir(name):
-                continue
-            # and has a wx subdir
-            if not os.path.exists(os.path.join(name, 'wx')):
-                continue
-            installed.append(_wxPackageInfo(name, True))
-
-    if removeExisting:
-        for rem in toRemove:
-            del sys.path[sys.path.index(rem)]
-        
-    installed.sort()
-    installed.reverse()
-    return installed
-
-
-# Scan the sys.path looking for either a directory matching _pattern,
-# or a wx.pth file
-def _find_default():
-    for pth in sys.path:
-        # empty means to look in the current dir
-        if not pth:
-            pth = '.'
-
-        # skip it if it's not a package dir
-        if not os.path.isdir(pth):
-            continue
-        
-        # does it match the pattern?
-        base = os.path.basename(pth)
-        if fnmatch.fnmatchcase(base, _pattern):
-            return pth
-
-    for pth in sys.path:
-        if not pth:
-            pth = '.'
-        if not os.path.isdir(pth):
-            continue
-        if os.path.exists(os.path.join(pth, 'wx.pth')):
-            base = open(os.path.join(pth, 'wx.pth')).read()
-            return os.path.join(pth, base)
-
-    return None
-
-
-class _wxPackageInfo(object):
-    def __init__(self, pathname, stripFirst=False):
-        self.pathname = pathname
-        base = os.path.basename(pathname)
-        segments = base.split('-')
-        if stripFirst:
-            segments = segments[1:]
-        self.version = tuple([int(x) for x in segments[0].split('.')])
-        self.options = segments[1:]
-
-
-    def Score(self, other, optionsRequired):
-        score = 0
-        
-        # whatever number of version components given in other must
-        # match exactly
-        minlen = min(len(self.version), len(other.version))
-        if self.version[:minlen] != other.version[:minlen]:
-            return 0        
-        score += 1
-
-        # check for matching options, if optionsRequired then the
-        # options are not optional ;-)
-        for opt in other.options:
-            if opt in self.options:
-                score += 1
-            elif optionsRequired:
-                return 0
-            
-        return score
-
-    
-    def CheckOptions(self, other, optionsRequired):
-        # if options are not required then this always succeeds
-        if not optionsRequired:
-            return True
-        # otherwise, if we have any option not present in other, then
-        # the match fails.
-        for opt in self.options:
-            if opt not in other.options:
-                return False
-        return True
-
-            
-   
-    def __lt__(self, other):
-        return self.version < other.version or \
-               (self.version == other.version and self.options < other.options)
-    def __le__(self, other):
-        return self.version <= other.version or \
-               (self.version == other.version and self.options <= other.options)
-    
-    def __gt__(self, other):
-        return self.version > other.version or \
-               (self.version == other.version and self.options > other.options)
-    def __ge__(self, other):
-        return self.version >= other.version or \
-               (self.version == other.version and self.options >= other.options)
-    
-    def __eq__(self, other):
-        return self.version == other.version and self.options == other.options
-        
-    
-
-#----------------------------------------------------------------------
-
-if __name__ == '__main__':
-    import pprint
-
-    #ensureMinimal('2.5')
-    #pprint.pprint(sys.path)
-    #sys.exit()
-    
-    
-    def test(version, optionsRequired=False):
-        # setup
-        savepath = sys.path[:]
-
-        #test
-        select(version, optionsRequired)
-        print "Asked for %s, (%s):\t got: %s" % (version, optionsRequired, sys.path[0])
-
-        # reset
-        sys.path = savepath[:]
-        global _selected
-        _selected = None
-
-
-    def testEM(version, optionsRequired=False):
-        # setup
-        savepath = sys.path[:]
-
-        #test
-        ensureMinimal(version, optionsRequired)
-        print "EM: Asked for %s, (%s):\t got: %s" % (version, optionsRequired, sys.path[0])
-
-        # reset
-        sys.path = savepath[:]
-        global _selected
-        _selected = None
-        
-        
-    # make some test dirs
-    names = ['wx-2.4-gtk-ansi',
-             'wx-2.5.2-gtk2-unicode',
-             'wx-2.5.3-gtk-ansi',
-             'wx-2.6-gtk2-unicode',
-             'wx-2.6-gtk2-ansi',
-             'wx-2.6-gtk-ansi',
-             'wx-2.7.1-gtk2-ansi',
-             ]
-    for name in names:
-        d = os.path.join('/tmp', name)
-        os.mkdir(d)
-        os.mkdir(os.path.join(d, 'wx'))
-
-    # setup sys.path to see those dirs
-    sys.path.append('/tmp')
-    
-
-    # now run some tests
-    pprint.pprint( getInstalled())
-    print checkInstalled("2.4")
-    print checkInstalled("2.5-unicode")
-    print checkInstalled("2.99-bogus")
-    print "Current sys.path:"
-    pprint.pprint(sys.path)
-    print
-    
-    test("2.4")
-    test("2.5")
-    test("2.5-gtk2")
-    test("2.5.2")
-    test("2.5-ansi")
-    test("2.5-unicode")
-    test("2.6")
-    test("2.6-ansi")
-    test(["2.6-unicode", "2.7-unicode"])
-    test(["2.6", "2.7"])
-    test(["2.6-unicode", "2.7-unicode"], optionsRequired=True)
-    
-    
-    
-    # There isn't a unicode match for this one, but it will give the best
-    # available 2.4.  Should it give an error instead?  I don't think so...
-    test("2.4-unicode") 
-
-    # Try asking for multiple versions
-    test(["2.5.2", "2.5.3", "2.6"])
-
-    try:
-        # expecting an error on this one
-        test("2.9")
-    except VersionError, e:
-        print "Asked for 2.9:\t got Exception:", e 
-
-    # check for exception when incompatible versions are requested
-    try:
-        select("2.4")
-        select("2.5")
-    except VersionError, e:
-        print "Asked for incompatible versions, got Exception:", e 
-
-    _EM_DEBUG=1
-    testEM("2.6")
-    testEM("2.6-unicode")
-    testEM("2.6-unicode", True)
-    try:
-        testEM("2.9")
-    except VersionError, e:
-        print "EM: Asked for 2.9:\t got Exception:", e 
-
-    # cleanup
-    for name in names:
-        d = os.path.join('/tmp', name)
-        os.rmdir(os.path.join(d, 'wx'))
-        os.rmdir(d)
-
-