[QGIS Commit] r9625 - trunk/qgis/python/plugins/plugin_installer
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Tue Nov 11 19:26:40 EST 2008
Author: borysiasty
Date: 2008-11-11 19:26:40 -0500 (Tue, 11 Nov 2008)
New Revision: 9625
Added:
trunk/qgis/python/plugins/plugin_installer/version_compare.py
Modified:
trunk/qgis/python/plugins/plugin_installer/__init__.py
trunk/qgis/python/plugins/plugin_installer/i18n.cpp
trunk/qgis/python/plugins/plugin_installer/installer_data.py
trunk/qgis/python/plugins/plugin_installer/installer_gui.py
trunk/qgis/python/plugins/plugin_installer/installer_plugin.py
Log:
Plugin Installer update: plugin compatibility checking
Modified: trunk/qgis/python/plugins/plugin_installer/__init__.py
===================================================================
--- trunk/qgis/python/plugins/plugin_installer/__init__.py 2008-11-11 15:30:31 UTC (rev 9624)
+++ trunk/qgis/python/plugins/plugin_installer/__init__.py 2008-11-12 00:26:40 UTC (rev 9625)
@@ -20,7 +20,7 @@
return "perrygeo, borysiasty"
def version():
- return "Version 0.9"
+ return "Version 0.9.1"
def classFactory(iface):
from installer_plugin import InstallerPlugin
Modified: trunk/qgis/python/plugins/plugin_installer/i18n.cpp
===================================================================
--- trunk/qgis/python/plugins/plugin_installer/i18n.cpp 2008-11-11 15:30:31 UTC (rev 9624)
+++ trunk/qgis/python/plugins/plugin_installer/i18n.cpp 2008-11-12 00:26:40 UTC (rev 9625)
@@ -142,7 +142,8 @@
tr("This plugin is installed, but I can't find it in any enabled repository")
tr("This plugin is not installed and is seen for the first time")
tr("This plugin is installed and is newer than its version available in a repository")
- tr("This plugin seems to be invalid or have unfulfilled dependencies\nIt has been installed, but can't be loaded")
+ tr("This plugin is incompatible and probably won't work with your Quantum GIS version")
+ tr("This plugin probably depends on some components missing in your system\nIt has been installed, but can't be loaded")
tr("not installed", "singular")
tr("installed", "singular")
tr("upgradeable", "singular")
@@ -158,8 +159,8 @@
tr("That's the newest available version")
tr("installed version")
tr("There is no version available for download")
- tr("This plugin seems to be invalid or have unfulfilled dependencies")
- tr("This plugin seems to be invalid or have unfulfilled dependencies\nIt has been installed, but can't be loaded")
+ tr("This plugin is invalid or has unfulfilled dependencies")
+ tr("This plugin is designed for a higher version of Quantum GIS")
tr("only locally available")
// def treeClicked
Modified: trunk/qgis/python/plugins/plugin_installer/installer_data.py
===================================================================
--- trunk/qgis/python/plugins/plugin_installer/installer_data.py 2008-11-11 15:30:31 UTC (rev 9624)
+++ trunk/qgis/python/plugins/plugin_installer/installer_data.py 2008-11-12 00:26:40 UTC (rev 9625)
@@ -19,6 +19,7 @@
from PyQt4.QtNetwork import *
from qgis.core import *
from unzip import unzip
+from version_compare import compareVersions, normalizeVersion
"""
@@ -37,7 +38,8 @@
"desc_repo" string,
"desc_local" string,
"author" string,
- "status" string, ("not installed", "installed", "upgradeable", "orphan", "new", "newer", "invalid")
+ "status" string, ("not installed", "installed", "upgradeable", "orphan", "new", "newer")
+ "error" string, ("", "broken", "incompatible" )
"homepage" string,
"url" string,
"filename" string,
@@ -47,12 +49,12 @@
"""
-QGIS_VER = 1
try:
- if str(QGis.qgisVersion)[0] == "0":
- QGIS_VER = 0
+ QGIS_VER = QGis.qgisVersion
+ QGIS_MAJOR_VER = 0
except:
- pass
+ QGIS_VER = QGis.QGIS_VERSION
+ QGIS_MAJOR_VER = 1
reposGroup = "/Qgis/plugin-repos"
@@ -134,14 +136,14 @@
for i in self.all().values():
presentURLs += [str(i["url"])]
for i in knownRepos:
- if i[QGIS_VER+1] and presentURLs.count(i[QGIS_VER+1]) == 0:
+ if i[QGIS_MAJOR_VER+1] and presentURLs.count(i[QGIS_MAJOR_VER+1]) == 0:
settings = QSettings()
settings.beginGroup(reposGroup)
repoName = QString(i[0])
if self.all().has_key(repoName):
repoName = repoName + "(2)"
# add to settings
- settings.setValue(repoName+"/url", QVariant(i[QGIS_VER+1]))
+ settings.setValue(repoName+"/url", QVariant(i[QGIS_MAJOR_VER+1]))
settings.setValue(repoName+"/enabled", QVariant(True))
@@ -208,15 +210,15 @@
settings.beginGroup(reposGroup)
# first, update the QSettings repositories if needed
if len(settings.childGroups()) == 0: # add the default repository when there isn't any
- settings.setValue(knownRepos[0][0]+"/url", QVariant(knownRepos[0][QGIS_VER+1]))
+ settings.setValue(knownRepos[0][0]+"/url", QVariant(knownRepos[0][QGIS_MAJOR_VER+1]))
else: # else update invalid urls
for key in settings.childGroups():
url = settings.value(key+"/url", QVariant()).toString()
allOk = True
for repo in knownRepos:
- if repo[3] == url or repo[4] == url or (repo[QGIS_VER+1] != url and repo[int(not QGIS_VER)+1] == url):
- if repo[QGIS_VER+1]: #update the URL
- settings.setValue(key+"/url", QVariant(repo[QGIS_VER+1]))
+ if repo[3] == url or repo[4] == url or (repo[QGIS_MAJOR_VER+1] != url and repo[int(not QGIS_MAJOR_VER)+1] == url):
+ if repo[QGIS_MAJOR_VER+1]: #update the URL
+ settings.setValue(key+"/url", QVariant(repo[QGIS_MAJOR_VER+1]))
settings.setValue(key+"/valid", QVariant(True))
allOk = False
else: # mark as invalid
@@ -299,12 +301,14 @@
"url" : pluginNodes.item(i).firstChildElement("download_url").text().trimmed(),
"filename" : pluginNodes.item(i).firstChildElement("file_name").text().trimmed(),
"status" : "not installed",
+ "error" : "",
"version_inst" : "",
"repository" : reposName,
"localdir" : name,
"read-only" : False}
- plugins.addPlugin(plugin)
-
+ #if compatible, add the plugin to list
+ if compareVersions(QGIS_VER, pluginNodes.item(i).firstChildElement("qgis_minimum_version").text().trimmed()) < 2:
+ plugins.addPlugin(plugin)
plugins.workarounds()
self.mRepositories[reposName]["state"] = 2
else:
@@ -361,114 +365,13 @@
# ----------------------------------------- #
- def normalizeVersion(self,ver):
- """ remove the prefix from given version string """
- if not ver:
- return QString()
- if ver.toUpper().left(7) == "VERSION":
- ver.remove(0,7)
- elif ver.toUpper().left(4) == "VER.":
- ver.remove(0,4)
- if ver[0] == " ":
- ver.remove(0,1)
- return ver
-
-
- # ----------------------------------------- #
- def compareVersions(self,a,b):
- """ compare two plugin versions """
- # -------- #
- def classify(s):
- if s in [".","-","_"," "]:
- return 0
- try:
- float(s)
- return 1
- except:
- return 2
- # -------- #
- def chop(s):
- s2 = [s[0]]
- for i in range(1,len(s)):
- if classify(s[i]) == 0:
- pass
- elif classify(s[i]) == classify(s[i-1]):
- s2[len(s2)-1] += s[i]
- else:
- s2 += [s[i]]
- return s2
- # -------- #
- def compare(s1,s2):
- # check if the matter is easy solvable:
- if s1 == s2:
- return 0
- if not s1:
- return 2
- if not s2:
- return 1
- # try to compare as numeric values (but only if the first character is not 0):
- if s1[0] != '0' and s2[0] != '0':
- try:
- if float(s1) == float(s2):
- return 0
- elif float(s1) > float(s2):
- return 1
- else:
- return 2
- except:
- pass
- # if the strings aren't numeric or start from 0, compare them as a strings:
- # but first, set ALPHA < BETA < RC < FINAL < ANYTHING_ELSE
- if s1 == 'FINAL':
- s1 = 'Z' + s1
- elif not s1 in ['ALPHA','BETA','RC']:
- s1 = 'ZZ' + s1
- if s2 == 'FINAL':
- s2 = 'Z' + s2
- elif not s2 in ['ALPHA','BETA','RC']:
- s2 = 'ZZ' + s2
- # the real test:
- if s1 > s2:
- return 1
- else:
- return 2
- # -------- #
- if not a or not b:
- return 0
- a = unicode(a).upper()
- b = unicode(b).upper()
- if a == b:
- return 0
-
- v1 = chop(a)
- v2 = chop(b)
- l = len(v1)
- if l > len(v2):
- l = len(v2)
-
- for i in range(l):
- if compare(v1[i],v2[i]):
- return compare(v1[i],v2[i])
-
- if len(v1) > l:
- return compare(v1[l],u'')
- if len(v2) > l:
- return compare(u'',v2[l])
- # if everything else fails...
- if unicode(a) > unicode(b):
- return 1
- else:
- return 2
-
-
- # ----------------------------------------- #
def addPlugin(self, plugins):
""" add a plugin (first from given) to the mPlugins dict """
key = plugins.keys()[0]
plugin = plugins[key]
- plugin["version_avail"] = self.normalizeVersion(QString(plugin["version_avail"]))
- plugin["version_inst"] = self.normalizeVersion(QString(plugin["version_inst"]))
- if not self.mPlugins.has_key(key) or self.compareVersions(self.mPlugins[key]["version_avail"],plugin["version_avail"]) == 2:
+ plugin["version_avail"] = normalizeVersion(plugin["version_avail"])
+ plugin["version_inst"] = normalizeVersion(plugin["version_inst"])
+ if not self.mPlugins.has_key(key) or compareVersions(self.mPlugins[key]["version_avail"],plugin["version_avail"]) == 2:
self.mPlugins[key] = plugin # add the plugin if not present yet or if is newer than existing one
@@ -485,7 +388,7 @@
path = QgsApplication.pkgDataPath()
else:
path = QgsApplication.qgisSettingsDirPath()
- path = QDir.cleanPath(unicode(path) + "python/plugins/" + key)
+ path = QDir.cleanPath(unicode(path) + "/python/plugins/" + key)
if not QDir(path).exists():
return
try:
@@ -510,15 +413,22 @@
exec("homepage = %s.homepage()" % key)
except:
homepage = ""
- stat = ""
+ try:
+ exec("qgisMinimumVersion = %s.qgisMinimumVersion()" % key)
+ if compareVersions(QGIS_VER, qgisMinimumVersion) == 2:
+ error = "incompatible"
+ else:
+ error = ""
+ except:
+ error = ""
except:
nam = key
- stat = "invalid"
ver = ""
desc = ""
auth = ""
homepage = ""
- normVer = self.normalizeVersion(QString(ver))
+ error = "broken"
+ normVer = normalizeVersion(ver)
plugin = {
"name" : nam,
"version_inst" : normVer,
@@ -529,7 +439,8 @@
"homepage" : homepage,
"url" : path,
"filename" : "",
- "status" : stat,
+ "status" : "",
+ "error" : error,
"repository" : "",
"localdir" : key,
"read-only" : readOnly}
@@ -538,12 +449,11 @@
else:
self.mPlugins[key]["localdir"] = plugin["localdir"]
self.mPlugins[key]["read-only"] = plugin["read-only"]
- if plugin["status"] == "invalid":
- self.mPlugins[key]["status"] = plugin["status"]
- else:
- self.mPlugins[key]["name"] = plugin["name"] # local name has higher priority, except invalid plugins
- self.mPlugins[key]["version_inst"] = plugin["version_inst"]
- self.mPlugins[key]["desc_local"] = plugin["desc_local"]
+ self.mPlugins[key]["error"] = plugin["error"]
+ if plugin["name"]:
+ self.mPlugins[key]["name"] = plugin["name"] # local name has higher priority
+ self.mPlugins[key]["version_inst"] = plugin["version_inst"]
+ self.mPlugins[key]["desc_local"] = plugin["desc_local"]
# set status
#
# installed available status
@@ -553,16 +463,16 @@
# same same "installed"
# less greater "upgradeable"
# greater less "newer"
- # *marked as invalid* "invalid"
- if self.mPlugins[key]["status"] == "invalid":
- pass
+
+ if not self.mPlugins[key]["version_avail"]:
+ self.mPlugins[key]["status"] = "orphan"
+ elif self.mPlugins[key]["error"] == "broken":
+ self.mPlugins[key]["status"] = "installed"
elif not self.mPlugins[key]["version_inst"]:
self.mPlugins[key]["status"] = "not installed"
- elif not self.mPlugins[key]["version_avail"]:
- self.mPlugins[key]["status"] = "orphan"
- elif self.compareVersions(self.mPlugins[key]["version_avail"],self.mPlugins[key]["version_inst"]) == 0:
+ elif compareVersions(self.mPlugins[key]["version_avail"],self.mPlugins[key]["version_inst"]) == 0:
self.mPlugins[key]["status"] = "installed"
- elif self.compareVersions(self.mPlugins[key]["version_avail"],self.mPlugins[key]["version_inst"]) == 1:
+ elif compareVersions(self.mPlugins[key]["version_avail"],self.mPlugins[key]["version_inst"]) == 1:
self.mPlugins[key]["status"] = "upgradeable"
else:
self.mPlugins[key]["status"] = "newer"
@@ -576,12 +486,13 @@
pluginDir = QDir.cleanPath(unicode(QgsApplication.pkgDataPath()) + "/python/plugins")
pluginDir = QDir(pluginDir)
pluginDir.setFilter(QDir.AllDirs)
+ for key in pluginDir.entryList():
+ key = str(key)
+ if not key in [".",".."]:
+ self.updatePlugin(key, True)
except:
- return QCoreApplication.translate("QgsPluginInstaller","Couldn't open the system plugin directory")
- for key in pluginDir.entryList():
- key = str(key)
- if not key in [".",".."]:
- self.updatePlugin(key, True)
+ # return QCoreApplication.translate("QgsPluginInstaller","Couldn't open the system plugin directory")
+ pass # it's not necessary to stop due to this error
# ...then try to add locally installed ones
try:
pluginDir = QDir.cleanPath(unicode(QgsApplication.qgisSettingsDirPath()) + "/python/plugins")
Modified: trunk/qgis/python/plugins/plugin_installer/installer_gui.py
===================================================================
--- trunk/qgis/python/plugins/plugin_installer/installer_gui.py 2008-11-11 15:30:31 UTC (rev 9624)
+++ trunk/qgis/python/plugins/plugin_installer/installer_gui.py 2008-11-12 00:26:40 UTC (rev 9625)
@@ -363,7 +363,7 @@
return False
if self.comboFilter2.currentIndex() == 1 and not plugin["status"] in ["not installed","new"]:
return False
- if self.comboFilter2.currentIndex() == 2 and not plugin["status"] in ["installed","upgradeable","newer","orphan","invalid"]:
+ if self.comboFilter2.currentIndex() == 2 and not plugin["status"] in ["installed","upgradeable","newer","orphan"]:
return False
if self.comboFilter2.currentIndex() == 3 and not plugin["status"] in ["upgradeable","new"]:
return False
@@ -381,47 +381,63 @@
# ----------------------------------------- #
def populatePluginTree(self):
""" fill up the pluginTree """
- descrip={"not installed" : self.tr("This plugin is not installed"),
+ statusTips={"not installed" : self.tr("This plugin is not installed"),
"installed" : self.tr("This plugin is installed"),
"upgradeable" : self.tr("This plugin is installed, but there is an updated version available"),
"orphan" : self.tr("This plugin is installed, but I can't find it in any enabled repository"),
"new" : self.tr("This plugin is not installed and is seen for the first time"),
"newer" : self.tr("This plugin is installed and is newer than its version available in a repository"),
- "invalid" : self.tr("This plugin seems to be invalid or have unfulfilled dependencies\nIt has been installed, but can't be loaded")}
- status ={"not installed" : self.tr("not installed", "singular"),
+ "incompatible" : self.tr("This plugin is incompatible and probably won't work with your Quantum GIS version"),
+ "broken" : self.tr("This plugin probably depends on some components missing in your system\nIt has been installed, but can't be loaded")}
+ statuses ={"not installed" : self.tr("not installed", "singular"),
"installed" : self.tr("installed", "singular"),
"upgradeable" : self.tr("upgradeable", "singular"),
"orphan" : self.tr("installed", "singular"),
"new" : self.tr("new!", "singular"),
"newer" : self.tr("installed", "singular"),
- "invalid" : self.tr("invalid", "singular")}
- order = ["invalid","upgradeable","new","not installed","installed","orphan","newer"]
+ "incompatible" : self.tr("invalid", "singular"),
+ "broken" : self.tr("invalid", "singular")}
+ orderInvalid = ["incompatible","broken"]
+ orderValid = ["upgradeable","new","not installed","installed","orphan","newer"]
def addItem(p):
if self.filterCheck(p):
- statusTip = descrip[p["status"]]
+ statusTip=""
+ if p["error"]:
+ statusTip = statusTips[p["error"]]
+ else:
+ statusTip = statusTips[p["status"]]
if p["read-only"]:
- statusTip += "\n" + self.tr("Note that it's an uninsatallable core plugin")
+ statusTip = statusTip + "\n" + self.tr("Note that it's an uninsatallable core plugin")
+ installedVersion = p["version_inst"]
+ if not installedVersion:
+ installedVersion = "?"
+ availableVersion = p["version_avail"]
+ if not availableVersion:
+ availableVersion = "?"
if p["status"] == "upgradeable":
- ver = p["version_inst"] + " -> " + p["version_avail"]
+ ver = installedVersion + " -> " + availableVersion
elif p["status"] == "newer":
- ver = p["version_inst"] + " (" + p["version_avail"] + ")"
- elif p["status"] in ["not installed", "new", "invalid"]:
- ver = p["version_avail"]
+ ver = installedVersion + " (" + availableVersion + ")"
+ elif p["status"] in ["not installed", "new"]:
+ ver = availableVersion
else:
- ver = p["version_inst"]
+ ver = installedVersion
if p["status"] in ["upgradeable","newer"]:
- verTip = self.tr("installed version") + ": " + p["version_inst"] + "\n" + self.tr("available version") + ": " + p["version_avail"]
+ verTip = self.tr("installed version") + ": " + installedVersion + "\n" + self.tr("available version") + ": " + availableVersion
elif p["status"] in ["not installed", "new"]:
- verTip = self.tr("available version") + ": " + p["version_avail"]
+ verTip = self.tr("available version") + ": " + availableVersion
elif p["status"] == "installed":
- verTip = self.tr("installed version") + ": " + p["version_inst"] + "\n" + self.tr("That's the newest available version")
+ verTip = self.tr("installed version") + ": " + installedVersion + "\n" + self.tr("That's the newest available version")
elif p["status"] == "orphan":
- verTip = self.tr("installed version") + ": " + p["version_inst"] + "\n" + self.tr("There is no version available for download")
+ verTip = self.tr("installed version") + ": " + installedVersion + "\n" + self.tr("There is no version available for download")
else:
verTip = ""
- if p["status"] == "invalid":
- desc = self.tr("This plugin seems to be invalid or have unfulfilled dependencies")
- descTip = self.tr("This plugin seems to be invalid or have unfulfilled dependencies\nIt has been installed, but can't be loaded")
+ if p["error"] == "broken":
+ desc = self.tr("This plugin is invalid or has unfulfilled dependencies")
+ descTip = statusTips[p["error"]]
+ elif p["error"] == "incompatible":
+ desc = self.tr("This plugin is designed for a higher version of Quantum GIS")
+ descTip = statusTips[p["error"]]
else:
desc = p["desc_local"]
descTip = p["desc_repo"]
@@ -432,7 +448,10 @@
else:
repository = p["repository"]
a = QTreeWidgetItem(self.treePlugins)
- a.setText(0,status[p["status"]])
+ if p["error"]:
+ a.setText(0,statuses[p["error"]])
+ else:
+ a.setText(0,statuses[p["status"]])
a.setToolTip(0,statusTip)
a.setText(1,p["name"])
a.setText(2,ver)
@@ -448,9 +467,9 @@
a.setToolTip(5,p["url"])
# set fonts and colours
for i in [0,1,2,3,4,5]:
- if p["status"] == "invalid":
+ if p["error"]:
a.setForeground(i,QBrush(QColor(Qt.red)))
- if p["status"] in ["new","upgradeable","invalid"]:
+ if p["status"] in ["new","upgradeable"] or p["error"]:
font = QFont()
font.setWeight(QFont.Bold)
a.setFont(i,font)
@@ -458,10 +477,14 @@
if not plugins.all():
return
self.treePlugins.clear()
- for i in order:
+ for i in orderInvalid:
for p in plugins.all().values():
- if p["status"] == i:
+ if p["error"] == i:
addItem(p)
+ for i in orderValid:
+ for p in plugins.all().values():
+ if p["status"] == i and not p["error"]:
+ addItem(p)
# resize the columns
for i in [0,1,2,3,4,5]:
self.treePlugins.resizeColumnToContents(i)
@@ -482,8 +505,7 @@
"upgradeable":(True,True,self.tr("Upgrade plugin")),
"orphan":(False,True,self.tr("Install/upgrade plugin")),
"new":(True, False,self.tr("Install plugin")),
- "newer":(True,True,self.tr("Downgrade plugin")),
- "invalid":(False,True,self.tr("Reinstall plugin"))}
+ "newer":(True,True,self.tr("Downgrade plugin"))}
self.buttonInstall.setEnabled(False)
self.buttonInstall.setText(self.tr("Install/upgrade plugin"))
self.buttonUninstall.setEnabled(False)
@@ -557,7 +579,7 @@
if not plugin:
return
warning = self.tr("Are you sure you want to uninstall the following plugin?") + "\n" + plugin["name"]
- if plugin["status"] == "orphan":
+ if plugin["status"] == "orphan" and not plugin["error"]:
warning += "\n\n"+self.tr("Warning: this plugin isn't available in any accessible repository!")
if QMessageBox.warning(self, self.tr("QGIS Python Plugin Installer"), warning , QMessageBox.Yes, QMessageBox.No) == QMessageBox.No:
return
Modified: trunk/qgis/python/plugins/plugin_installer/installer_plugin.py
===================================================================
--- trunk/qgis/python/plugins/plugin_installer/installer_plugin.py 2008-11-11 15:30:31 UTC (rev 9624)
+++ trunk/qgis/python/plugins/plugin_installer/installer_plugin.py 2008-11-12 00:26:40 UTC (rev 9625)
@@ -26,7 +26,7 @@
# ----------------------------------------- #
def __init__(self, iface):
self.iface = iface
- if QGIS_VER: # new plugin API
+ if QGIS_MAJOR_VER: # new plugin API
self.mainWindow = self.iface.mainWindow
else: # old plugin API
self.mainWindow = self.iface.getMainWindow
@@ -37,7 +37,7 @@
self.action = QAction(QIcon(":/plugins/installer/plugin_installer.png"), QCoreApplication.translate("QgsPluginInstaller","Fetch Python Plugins..."), self.mainWindow())
self.action.setWhatsThis(QCoreApplication.translate("QgsPluginInstaller","Install more plugins from remote repositories"))
self.action.setStatusTip(QCoreApplication.translate("QgsPluginInstaller","Install more plugins from remote repositories"))
- if QGIS_VER: # new plugin API
+ if QGIS_MAJOR_VER: # new plugin API
nextAction = self.iface.actionManagePlugins()
self.iface.pluginMenu().insertAction(nextAction,self.action)
else: # old plugin API
Added: trunk/qgis/python/plugins/plugin_installer/version_compare.py
===================================================================
--- trunk/qgis/python/plugins/plugin_installer/version_compare.py (rev 0)
+++ trunk/qgis/python/plugins/plugin_installer/version_compare.py 2008-11-12 00:26:40 UTC (rev 9625)
@@ -0,0 +1,143 @@
+"""
+This is a Python module to compare version numbers. It's case insensitive
+and recognizes all major notations, prefixes (ver. and version), delimiters
+(. - and _) and suffixes (alpha, beta, rc, preview and final).
+
+Usage: compareVersions(version1, version2)
+
+The function accepts arguments of any type convertable to unicode string
+and returns integer value:
+0 - the versions are equal
+1 - version 1 is higher
+2 - version 2 is higher
+
+-----------------------------------------------------------------------------
+HOW IT WORKS...
+First, both arguments are converted to uppercase unicode and stripped of
+'VERSION' or 'VER.' prefix. Then they are chopped into a list of particular
+numeric and alphabetic elements. The dots, dashes and underlines are recognized
+as delimiters. Also numbers and non numbers are separated. See example below:
+
+'Ver 0.03-120_rc7foo' is converted to ['0','03','120','RC','7','FOO']
+
+Then every pair of elements, from left to right, is compared as string
+or as number to provide the best result (you know, 11>9 but also '03'>'007').
+The comparing stops when one of elements is greater. If comparing achieves
+the end of the shorter list and the matter is still unresolved, the longer
+list is usually recognized as higher, except following suffixes:
+ALPHA, BETA, RC and PREVIEW which make the version number lower.
+
+/***************************************************************************
+ * *
+ * Copyright (C) 2008-11-11 Borys Jurgiel *
+ * *
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+"""
+
+# ------------------------------------------------------------------------ #
+def normalizeVersion(s):
+ """ remove possible prefix from given string and convert to uppercase """
+ if not s:
+ return unicode()
+ s = unicode(s).upper()
+ s = s.replace('VERSION','')
+ s = s.replace('VER.','')
+ s = s.replace('VER','')
+ s = s.lstrip()
+ return s
+
+
+# ------------------------------------------------------------------------ #
+def classifyCharacter(c):
+ """ return 0 for delimiter, 1 for digit and 2 for alphabetic character """
+ if c in [".","-","_"," "]:
+ return 0
+ if c.isdigit():
+ return 1
+ else:
+ return 2
+
+
+# ------------------------------------------------------------------------ #
+def chopString(s):
+ """ convert string to list of numbers and words """
+ l = [s[0]]
+ for i in range(1,len(s)):
+ if classifyCharacter(s[i]) == 0:
+ pass
+ elif classifyCharacter(s[i]) == classifyCharacter(s[i-1]):
+ l[len(l)-1] += s[i]
+ else:
+ l += [s[i]]
+ return l
+
+
+# ------------------------------------------------------------------------ #
+def compareElements(s1,s2):
+ """ compare two particular elements """
+ # check if the matter is easy solvable:
+ if s1 == s2:
+ return 0
+ # try to compare as numeric values (but only if the first character is not 0):
+ if s1 and s2 and s1.isnumeric() and s2.isnumeric() and s1[0] != '0' and s2[0] != '0':
+ if float(s1) == float(s2):
+ return 0
+ elif float(s1) > float(s2):
+ return 1
+ else:
+ return 2
+ # if the strings aren't numeric or start from 0, compare them as a strings:
+ # but first, set ALPHA < BETA < PREVIEW < RC < FINAL < [NOTHING] < [ANYTHING_ELSE]
+ if s1 == 'FINAL':
+ s1 = 'Z' + s1
+ elif not s1 in ['ALPHA','BETA','PREVIEW','RC']:
+ s1 = 'ZZ' + s1
+ if s2 == 'FINAL':
+ s2 = 'Z' + s2
+ elif not s2 in ['ALPHA','BETA','PREVIEW','RC']:
+ s2 = 'ZZ' + s2
+ # the final test:
+ if s1 > s2:
+ return 1
+ else:
+ return 2
+
+
+# ------------------------------------------------------------------------ #
+def compareVersions(a,b):
+ """ Compare two version numbers. Return 0 if a==b or error, 1 if a<b and 2 if b>a """
+ if not a or not b:
+ return 0
+ a = normalizeVersion(a)
+ b = normalizeVersion(b)
+ if a == b:
+ return 0
+ # convert the strings to the lists
+ v1 = chopString(a)
+ v2 = chopString(b)
+ # set the shorter string as a base
+ l = len(v1)
+ if l > len(v2):
+ l = len(v2)
+ # try to determine within the common length
+ for i in range(l):
+ if compareElements(v1[i],v2[i]):
+ return compareElements(v1[i],v2[i])
+ # if the lists are identical till the end of the shorther string, try to compare the odd tail
+ #with the simple space (because the 'alpha', 'beta', 'preview' and 'rc' are LESS then nothing)
+ if len(v1) > l:
+ return compareElements(v1[l],u' ')
+ if len(v2) > l:
+ return compareElements(u' ',v2[l])
+ # if everything else fails...
+ if a > b:
+ return 1
+ else:
+ return 2
More information about the QGIS-commit
mailing list