summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/wxversion.py
diff options
context:
space:
mode:
authorrahulp132020-03-17 14:55:41 +0530
committerrahulp132020-03-17 14:55:41 +0530
commit296443137f4288cb030e92859ccfbe3204bc1088 (patch)
treeca4798c2da1e7244edc3bc108d81b462b537aea2 /lib/python2.7/site-packages/wxversion.py
parent0db48f6533517ecebfd9f0693f89deca28408b76 (diff)
downloadKiCad-eSim-296443137f4288cb030e92859ccfbe3204bc1088.tar.gz
KiCad-eSim-296443137f4288cb030e92859ccfbe3204bc1088.tar.bz2
KiCad-eSim-296443137f4288cb030e92859ccfbe3204bc1088.zip
initial commit
Diffstat (limited to 'lib/python2.7/site-packages/wxversion.py')
-rw-r--r--lib/python2.7/site-packages/wxversion.py528
1 files changed, 528 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/wxversion.py b/lib/python2.7/site-packages/wxversion.py
new file mode 100644
index 0000000..94fd881
--- /dev/null
+++ b/lib/python2.7/site-packages/wxversion.py
@@ -0,0 +1,528 @@
+#----------------------------------------------------------------------
+# 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
+
+class AlreadyImportedError(VersionError):
+ 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 function should only be called once at the beginning
+ 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 AlreadyImportedError("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 AlreadyImportedError("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.App()
+ 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)
+
+