require --> select, added checkInstalled and getInstalled
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30086 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -15,10 +15,16 @@
|
|||||||
"""
|
"""
|
||||||
If you have more than one version of wxPython installed this module
|
If you have more than one version of wxPython installed this module
|
||||||
allows your application to choose which version of wxPython will be
|
allows your application to choose which version of wxPython will be
|
||||||
imported when it does 'import wx'. You use it like this:
|
imported when it does 'import wx'. You use it like this::
|
||||||
|
|
||||||
import wxversion
|
import wxversion
|
||||||
wxversion.require('2.4')
|
wxversion.select('2.4')
|
||||||
|
import wx
|
||||||
|
|
||||||
|
Or additional build options can also be selected, like this::
|
||||||
|
|
||||||
|
import wxversion
|
||||||
|
wxversion.select('2.5.3-unicode')
|
||||||
import wx
|
import wx
|
||||||
|
|
||||||
Of course the default wxPython version can also be controlled by
|
Of course the default wxPython version can also be controlled by
|
||||||
@@ -30,19 +36,41 @@ environment correctly.
|
|||||||
It works by searching the sys.path for directories matching wx-* and
|
It works by searching the sys.path for directories matching wx-* and
|
||||||
then comparing them to what was passed to the require function. If a
|
then comparing them to what was passed to the require function. If a
|
||||||
match is found then that path is inserted into sys.path.
|
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 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
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys, os, glob, fnmatch
|
import sys, os, glob, fnmatch
|
||||||
|
|
||||||
|
|
||||||
_selected = None
|
_selected = None
|
||||||
class wxversionError(Exception):
|
class VersionError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
def require(versions):
|
def select(versions):
|
||||||
"""
|
"""
|
||||||
Search for a wxPython installation that matches version.
|
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 version: Specifies the version to look for, it can
|
:param version: Specifies the version to look for, it can
|
||||||
either be a string or a list of strings. Each
|
either be a string or a list of strings. Each
|
||||||
@@ -62,8 +90,6 @@ def require(versions):
|
|||||||
is increased for every specified optional component
|
is increased for every specified optional component
|
||||||
that is specified and that matches.
|
that is specified and that matches.
|
||||||
"""
|
"""
|
||||||
bestMatch = None
|
|
||||||
bestScore = 0
|
|
||||||
if type(versions) == str:
|
if type(versions) == str:
|
||||||
versions = [versions]
|
versions = [versions]
|
||||||
|
|
||||||
@@ -75,33 +101,72 @@ def require(versions):
|
|||||||
if _selected.Score(_wxPackageInfo(ver)) > 0:
|
if _selected.Score(_wxPackageInfo(ver)) > 0:
|
||||||
return
|
return
|
||||||
# otherwise, raise an exception
|
# otherwise, raise an exception
|
||||||
raise wxversionError("A previously selected wx version does not match the new request.")
|
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.
|
# If we get here then this is the first time wxversion is used.
|
||||||
# Ensure that wxPython hasn't been imported yet.
|
# Ensure that wxPython hasn't been imported yet.
|
||||||
if sys.modules.has_key('wx') or sys.modules.has_key('wxPython'):
|
if sys.modules.has_key('wx') or sys.modules.has_key('wxPython'):
|
||||||
raise wxversionError("wxversion.require() must be called before wxPython is imported")
|
raise VersionError("wxversion.require() must be called before wxPython is imported")
|
||||||
|
|
||||||
# Look for a matching version and manipulate the sys.path as
|
# Look for a matching version and manipulate the sys.path as
|
||||||
# needed to allow it to be imported.
|
# needed to allow it to be imported.
|
||||||
|
packages = _find_installed(True)
|
||||||
|
bestMatch = _get_best_match(packages, versions)
|
||||||
|
|
||||||
|
if bestMatch is None:
|
||||||
|
raise VersionError("Requested version of wxPython not found")
|
||||||
|
|
||||||
|
sys.path.insert(0, bestMatch.pathname)
|
||||||
|
_selected = bestMatch
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
def checkInstalled(versions):
|
||||||
|
"""
|
||||||
|
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 version: Same as in `select`, either a string or a list
|
||||||
|
of strings specifying the version(s) to check
|
||||||
|
for.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if type(versions) == str:
|
||||||
|
versions = [versions]
|
||||||
packages = _find_installed()
|
packages = _find_installed()
|
||||||
|
bestMatch = _get_best_match(packages, versions)
|
||||||
|
return bestMatch is not None
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
def getInstalled():
|
||||||
|
"""
|
||||||
|
Returns a list of strings representing the installed wxPython
|
||||||
|
versions that are found on the system.
|
||||||
|
"""
|
||||||
|
packages = _find_installed()
|
||||||
|
return [os.path.basename(p.pathname)[3:] for p in packages]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# private helpers...
|
||||||
|
|
||||||
|
def _get_best_match(packages, versions):
|
||||||
|
bestMatch = None
|
||||||
|
bestScore = 0
|
||||||
for pkg in packages:
|
for pkg in packages:
|
||||||
for ver in versions:
|
for ver in versions:
|
||||||
score = pkg.Score(_wxPackageInfo(ver))
|
score = pkg.Score(_wxPackageInfo(ver))
|
||||||
if score > bestScore:
|
if score > bestScore:
|
||||||
bestMatch = pkg
|
bestMatch = pkg
|
||||||
bestScore = score
|
bestScore = score
|
||||||
|
return bestMatch
|
||||||
if bestMatch is None:
|
|
||||||
raise wxversionError("Requested version of wxPython not found")
|
|
||||||
|
|
||||||
sys.path.insert(0, bestMatch.pathname)
|
|
||||||
_selected = bestMatch
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_pattern = "wx-[0-9].*"
|
_pattern = "wx-[0-9].*"
|
||||||
def _find_installed():
|
def _find_installed(removeExisting=False):
|
||||||
installed = []
|
installed = []
|
||||||
toRemove = []
|
toRemove = []
|
||||||
for pth in sys.path:
|
for pth in sys.path:
|
||||||
@@ -132,8 +197,9 @@ def _find_installed():
|
|||||||
continue
|
continue
|
||||||
installed.append(_wxPackageInfo(name, True))
|
installed.append(_wxPackageInfo(name, True))
|
||||||
|
|
||||||
for rem in toRemove:
|
if removeExisting:
|
||||||
del sys.path[sys.path.index(rem)]
|
for rem in toRemove:
|
||||||
|
del sys.path[sys.path.index(rem)]
|
||||||
|
|
||||||
installed.sort()
|
installed.sort()
|
||||||
installed.reverse()
|
installed.reverse()
|
||||||
@@ -153,14 +219,13 @@ class _wxPackageInfo(object):
|
|||||||
|
|
||||||
def Score(self, other):
|
def Score(self, other):
|
||||||
score = 0
|
score = 0
|
||||||
|
|
||||||
# whatever version components given in other must match exactly
|
# whatever version components given in other must match exactly
|
||||||
if len(self.version) > len(other.version):
|
minlen = min(len(self.version), len(other.version))
|
||||||
v = self.version[:len(other.version)]
|
if self.version[:minlen] != other.version[:minlen]:
|
||||||
else:
|
return 0
|
||||||
v = self.version
|
score += 1 # todo: should it be +=minlen to reward longer matches?
|
||||||
if v != other.version:
|
|
||||||
return 0
|
|
||||||
score += 1
|
|
||||||
for opt in other.options:
|
for opt in other.options:
|
||||||
if opt in self.options:
|
if opt in self.options:
|
||||||
score += 1
|
score += 1
|
||||||
@@ -177,7 +242,7 @@ class _wxPackageInfo(object):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import pprint
|
import pprint
|
||||||
@@ -186,7 +251,7 @@ if __name__ == '__main__':
|
|||||||
savepath = sys.path[:]
|
savepath = sys.path[:]
|
||||||
|
|
||||||
#test
|
#test
|
||||||
require(version)
|
select(version)
|
||||||
print "Asked for %s:\t got: %s" % (version, sys.path[0])
|
print "Asked for %s:\t got: %s" % (version, sys.path[0])
|
||||||
#pprint.pprint(sys.path)
|
#pprint.pprint(sys.path)
|
||||||
#print
|
#print
|
||||||
@@ -215,6 +280,10 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
|
|
||||||
# now run some tests
|
# now run some tests
|
||||||
|
pprint.pprint( getInstalled())
|
||||||
|
print checkInstalled("2.4")
|
||||||
|
print checkInstalled("2.5-unicode")
|
||||||
|
print checkInstalled("2.99-bogus")
|
||||||
test("2.4")
|
test("2.4")
|
||||||
test("2.5")
|
test("2.5")
|
||||||
test("2.5-gtk2")
|
test("2.5-gtk2")
|
||||||
@@ -232,14 +301,14 @@ if __name__ == '__main__':
|
|||||||
try:
|
try:
|
||||||
# expecting an error on this one
|
# expecting an error on this one
|
||||||
test("2.6")
|
test("2.6")
|
||||||
except wxversionError, e:
|
except VersionError, e:
|
||||||
print "Asked for 2.6:\t got Exception:", e
|
print "Asked for 2.6:\t got Exception:", e
|
||||||
|
|
||||||
# check for exception when incompatible versions are requested
|
# check for exception when incompatible versions are requested
|
||||||
try:
|
try:
|
||||||
require("2.4")
|
select("2.4")
|
||||||
require("2.5")
|
select("2.5")
|
||||||
except wxversionError, e:
|
except VersionError, e:
|
||||||
print "Asked for incompatible versions, got Exception:", e
|
print "Asked for incompatible versions, got Exception:", e
|
||||||
|
|
||||||
# cleanup
|
# cleanup
|
||||||
|
Reference in New Issue
Block a user