mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Add test for plugin dependencies
Also made minor changes to the function and class names, to be more consistent with QGIS naming conventions.
This commit is contained in:
parent
1622d73e25
commit
b85d5af0c0
@ -9,8 +9,8 @@ SET(PY_PLUGININSTALLER_FILES
|
||||
qgsplugininstallerpluginerrordialog.py
|
||||
qgsplugininstallerfetchingdialog.py
|
||||
qgsplugininstallerrepositorydialog.py
|
||||
qgsplugindependencies.py
|
||||
qgsplugindependenciesdialog.py
|
||||
plugindependencies.py
|
||||
unzip.py
|
||||
version_compare.py
|
||||
)
|
||||
|
@ -43,7 +43,7 @@ from .qgsplugininstallerpluginerrordialog import QgsPluginInstallerPluginErrorDi
|
||||
from .qgsplugininstallerfetchingdialog import QgsPluginInstallerFetchingDialog
|
||||
from .qgsplugininstallerrepositorydialog import QgsPluginInstallerRepositoryDialog
|
||||
from .unzip import unzip
|
||||
from .qgsplugindependencies import find_dependencies
|
||||
from .plugindependencies import find_dependencies
|
||||
from .qgsplugindependenciesdialog import QgsPluginDependenciesDialog
|
||||
|
||||
|
||||
|
@ -1,122 +0,0 @@
|
||||
# coding=utf-8
|
||||
"""Parse plugin metadata for plugin_dependencies and install/update
|
||||
required plugins
|
||||
|
||||
.. note:: 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.
|
||||
|
||||
"""
|
||||
|
||||
__author__ = 'elpaso@itopen.it'
|
||||
__date__ = '2018-05-29'
|
||||
__copyright__ = 'Copyright 2018, GISCE-TI S.L.'
|
||||
|
||||
from configparser import NoOptionError, NoSectionError
|
||||
from .version_compare import compareVersions
|
||||
from . import installer as plugin_installer
|
||||
|
||||
|
||||
def __plugin_name_map(plugin_data_values):
|
||||
return {
|
||||
plugin['name']: plugin['id']
|
||||
for plugin in plugin_data_values
|
||||
}
|
||||
|
||||
|
||||
def __get_plugin_deps(plugin_id):
|
||||
|
||||
result = {}
|
||||
from qgis.utils import plugins_metadata_parser
|
||||
parser = plugins_metadata_parser[plugin_id]
|
||||
try:
|
||||
plugin_deps = parser.get('general', 'plugin_dependencies')
|
||||
except (NoOptionError, NoSectionError):
|
||||
return result
|
||||
|
||||
for dep in plugin_deps.split(','):
|
||||
if dep.find('==') > 0:
|
||||
name, version_required = dep.split('==')
|
||||
else:
|
||||
name = dep
|
||||
version_required = None
|
||||
result[name] = version_required
|
||||
return result
|
||||
|
||||
|
||||
def find_dependencies(plugin_id, plugin_data=None, plugin_deps=None, installed_plugins=None):
|
||||
"""Finds the plugin dependencies and checks if they can be installed or upgraded
|
||||
|
||||
:param plugin_id: plugin id
|
||||
:type plugin_id: str
|
||||
:param plugin_data: for testing only: dictionary of plugin data from the repo, defaults to None
|
||||
:param plugin_data: dict, optional
|
||||
:param plugin_deps: for testing only: dict of plugin id -> version_required, parsed from metadata value for "plugin_dependencies", defaults to None
|
||||
:param plugin_deps: dict, optional
|
||||
:param installed_plugins: for testing only: dict of plugin id -> version_installed
|
||||
:param installed_plugins: dict, optional
|
||||
:return: result dictionaries keyed by plugin name with: to_install, to_upgrade, not_found
|
||||
:rtype: tuple of dicts
|
||||
"""
|
||||
|
||||
to_install = {}
|
||||
to_upgrade = {}
|
||||
not_found = {}
|
||||
|
||||
if plugin_deps is None:
|
||||
plugin_deps = __get_plugin_deps(plugin_id)
|
||||
|
||||
if installed_plugins is None:
|
||||
from qgis.utils import plugins_metadata_parser
|
||||
installed_plugins = {plugins_metadata_parser[k].get('general', 'name'): plugins_metadata_parser[k].get('general', 'version') for k, v in plugins_metadata_parser.items()}
|
||||
|
||||
if plugin_data is None:
|
||||
plugin_data = plugin_installer.plugins.all()
|
||||
|
||||
plugins_map = __plugin_name_map(plugin_data.values())
|
||||
|
||||
# Review all dependencies
|
||||
for name, version_required in plugin_deps.items():
|
||||
try:
|
||||
p_id = plugins_map[name]
|
||||
except KeyError:
|
||||
not_found.update({name: {
|
||||
'id': None,
|
||||
'version_installed': None,
|
||||
'version_required': None,
|
||||
'version_available': None,
|
||||
'action': None,
|
||||
'error': 'missing_id'
|
||||
}})
|
||||
continue
|
||||
|
||||
affected_plugin = dict({
|
||||
"id": p_id,
|
||||
# "version_installed": installed_plugins.get(p_id, {}).get('installed_plugins', None),
|
||||
"version_installed": installed_plugins.get(name, None),
|
||||
"version_required": version_required,
|
||||
"version_available": plugin_data[p_id].get('version_available', None),
|
||||
"action": None,
|
||||
})
|
||||
|
||||
# Install is needed
|
||||
if name not in installed_plugins:
|
||||
affected_plugin['action'] = 'install'
|
||||
destination_list = to_install
|
||||
# Upgrade is needed
|
||||
elif version_required is not None and compareVersions(installed_plugins[name], version_required) == 2:
|
||||
affected_plugin['action'] = 'upgrade'
|
||||
destination_list = to_upgrade
|
||||
# TODO @elpaso: review installed but not activated
|
||||
# No action is needed
|
||||
else:
|
||||
continue
|
||||
|
||||
if affected_plugin['version_required'] == affected_plugin['version_available'] or affected_plugin['version_required'] is None:
|
||||
destination_list.update({name: affected_plugin})
|
||||
else:
|
||||
affected_plugin['error'] = 'unavailable {}'.format(affected_plugin['action'])
|
||||
not_found.update({name: affected_plugin})
|
||||
|
||||
return to_install, to_upgrade, not_found
|
@ -282,6 +282,7 @@ def updateAvailablePlugins():
|
||||
available_plugins = plugins
|
||||
global plugins_metadata_parser
|
||||
plugins_metadata_parser = metadata_parser
|
||||
return metadata_parser
|
||||
|
||||
|
||||
def pluginMetadata(packageName, fct):
|
||||
|
@ -243,6 +243,7 @@ ADD_PYTHON_TEST(PyQgsAuthSettingsWidget test_authsettingswidget.py)
|
||||
ADD_PYTHON_TEST(PyQgsAuxiliaryStorage test_qgsauxiliarystorage.py)
|
||||
ADD_PYTHON_TEST(PyQgsAuthManagerOgr test_authmanager_ogr.py)
|
||||
ADD_PYTHON_TEST(PyQgsFieldValidator test_qgsfieldvalidator.py)
|
||||
ADD_PYTHON_TEST(PyQgsPluginDependencies test_plugindependencies.py)
|
||||
|
||||
IF (NOT WIN32)
|
||||
ADD_PYTHON_TEST(PyQgsLogger test_qgslogger.py)
|
||||
|
122
tests/src/python/test_plugindependencies.py
Normal file
122
tests/src/python/test_plugindependencies.py
Normal file
@ -0,0 +1,122 @@
|
||||
# coding=utf-8
|
||||
"""QGIS Plugin dependencies test
|
||||
|
||||
.. note:: 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.
|
||||
|
||||
"""
|
||||
|
||||
__author__ = 'elpaso@itopen.it'
|
||||
__date__ = '2018-09-19'
|
||||
__copyright__ = 'Copyright 2018, GISCE-TI S.L.'
|
||||
|
||||
import uuid
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import unittest
|
||||
from qgis.PyQt.QtCore import QCoreApplication
|
||||
from pyplugin_installer.plugindependencies import find_dependencies
|
||||
|
||||
|
||||
from qgis.testing import (
|
||||
start_app,
|
||||
unittest,
|
||||
)
|
||||
|
||||
from utilities import unitTestDataPath
|
||||
|
||||
TESTDATA_PATH = unitTestDataPath()
|
||||
|
||||
|
||||
class PluginDependenciesTest(unittest.TestCase):
|
||||
"""Test plugin dependencies"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Runs at start."""
|
||||
|
||||
QCoreApplication.setOrganizationName("QGIS")
|
||||
QCoreApplication.setOrganizationDomain("qgis.org")
|
||||
QCoreApplication.setApplicationName("QGIS-TEST-%s" % uuid.uuid1())
|
||||
qgis_app = start_app()
|
||||
|
||||
# Installed plugins
|
||||
cls.installed_plugins = {
|
||||
'MetaSearch': '0.3.5',
|
||||
'QuickWKT': '3.1',
|
||||
'db_manager': '0.1.20',
|
||||
'firstaid': '2.1.1',
|
||||
'InaSAFE': '5.0.0',
|
||||
'ipyconsole': '1.8',
|
||||
'plugin_reloader': '0.7.4',
|
||||
'processing': '2.12.99',
|
||||
'qgis-geocoding': '2.18',
|
||||
'qgisce': '0.9',
|
||||
'redistrict': '0.1'
|
||||
}
|
||||
|
||||
data_path = os.path.join(TESTDATA_PATH, 'plugindependencies_data.json')
|
||||
with open(data_path) as f:
|
||||
cls.plugin_data = json.loads(f.read())
|
||||
|
||||
def setUp(self):
|
||||
"""Runs before each test."""
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
"""Runs after each test."""
|
||||
pass
|
||||
|
||||
def test_find_dependencies(self):
|
||||
|
||||
to_install, to_upgrade, not_found = find_dependencies('qgisce', self.plugin_data, plugin_deps={'InaSAFE': None}, installed_plugins=self.installed_plugins)
|
||||
self.assertEqual(to_install, {})
|
||||
self.assertEqual(to_upgrade, {})
|
||||
self.assertEqual(not_found, {})
|
||||
|
||||
to_install, to_upgrade, not_found = find_dependencies('qgisce', self.plugin_data, plugin_deps={'InaSAFE': '110.1'}, installed_plugins=self.installed_plugins)
|
||||
self.assertEqual(to_install, {})
|
||||
self.assertEqual(to_upgrade, {})
|
||||
self.assertEqual(not_found['InaSAFE']['version_installed'], '5.0.0')
|
||||
|
||||
# QuickWkt is installed, version is not specified: ignore
|
||||
installed_plugins = self.installed_plugins
|
||||
installed_plugins['QuickWKT'] = '2.1'
|
||||
to_install, to_upgrade, not_found = find_dependencies('qgisce', self.plugin_data, plugin_deps={'QuickMapServices': '0.19.10.1', 'QuickWKT': None}, installed_plugins=self.installed_plugins)
|
||||
self.assertEqual(to_install['QuickMapServices']['version_required'], '0.19.10.1')
|
||||
self.assertEqual(to_upgrade, {})
|
||||
self.assertEqual(not_found, {})
|
||||
|
||||
# QuickWkt is installed, version requires upgrade and it's in the repo: upgrade
|
||||
to_install, to_upgrade, not_found = find_dependencies('qgisce', self.plugin_data, plugin_deps={'QuickWKT': '3.1'}, installed_plugins=installed_plugins)
|
||||
self.assertEqual(to_install, {})
|
||||
self.assertEqual(to_upgrade['QuickWKT']['version_required'], '3.1')
|
||||
self.assertEqual(not_found, {})
|
||||
|
||||
# QuickWkt is installed, version requires upgrade and it's NOT in the repo: not found
|
||||
to_install, to_upgrade, not_found = find_dependencies('qgisce', self.plugin_data, plugin_deps={'QuickWKT': '300.11234'}, installed_plugins=installed_plugins)
|
||||
self.assertEqual(to_install, {})
|
||||
self.assertEqual(to_upgrade, {})
|
||||
self.assertEqual(not_found['QuickWKT']['version_required'], '300.11234')
|
||||
self.assertEqual(not_found['QuickWKT']['version_installed'], '2.1')
|
||||
self.assertEqual(not_found['QuickWKT']['version_available'], '3.1')
|
||||
|
||||
# Installed version is > than required: ignore (no downgrade is currently possible)
|
||||
installed_plugins['QuickWKT'] = '300.1'
|
||||
to_install, to_upgrade, not_found = find_dependencies('qgisce', self.plugin_data, plugin_deps={'QuickWKT': '1.2'}, installed_plugins=installed_plugins)
|
||||
self.assertEqual(to_install, {})
|
||||
self.assertEqual(to_upgrade, {})
|
||||
self.assertEqual(not_found, {})
|
||||
|
||||
|
||||
def pluginSuite():
|
||||
return unittest.makeSuite(PluginDependenciesTest, 'test')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
suite = unittest.makeSuite(PluginDependenciesTest)
|
||||
runner = unittest.TextTestRunner(verbosity=2)
|
||||
runner.run(suite)
|
1
tests/testdata/plugindependencies_data.json
vendored
Normal file
1
tests/testdata/plugindependencies_data.json
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user