File: plugindependencies.py

package info (click to toggle)
qgis 3.40.6%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,181,336 kB
  • sloc: cpp: 1,593,302; python: 370,494; xml: 23,474; perl: 3,664; sh: 3,482; ansic: 2,257; sql: 2,133; yacc: 1,068; lex: 577; javascript: 540; lisp: 411; makefile: 157
file content (151 lines) | stat: -rw-r--r-- 5,705 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
"""Parse plugin metadata for plugin_dependencies

.. 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
from qgis.utils import updateAvailablePlugins, metadataParser, get_plugin_deps


def __plugin_name_map(plugin_data_values):
    return {plugin["name"]: plugin["id"] for plugin in plugin_data_values}


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 or installed_plugins is None:
        updateAvailablePlugins()

    if plugin_deps is None:
        plugin_deps = get_plugin_deps(plugin_id)

    if installed_plugins is None:
        metadata_parser = metadataParser()
        installed_plugins = {
            metadata_parser[k]
            .get("general", "name"): metadata_parser[k]
            .get("general", "version")
            for k, v in 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,
                        "use_stable_version": 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),
                "use_stable_version": True,  # Prefer stable by default
                "action": None,
            }
        )
        version_available_stable = plugin_data[p_id].get(
            "version_available_stable", None
        )
        version_available_experimental = plugin_data[p_id].get(
            "version_available_experimental", None
        )

        if (
            version_required is not None
            and version_required == version_available_stable
        ):
            affected_plugin["version_available"] = version_available_stable
            affected_plugin["use_stable_version"] = True
        elif (
            version_required is not None
            and version_required == version_available_experimental
        ):
            affected_plugin["version_available"] = version_available_experimental
            affected_plugin["use_stable_version"] = False
        elif version_required is None:
            if version_available_stable:  # None if not found, "" if not offered
                # Prefer the stable version, if any
                affected_plugin["version_available"] = version_available_stable
                affected_plugin["use_stable_version"] = True
            else:  # The only available version is experimental
                affected_plugin["version_available"] = version_available_experimental
                affected_plugin["use_stable_version"] = False

        # 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 (
            version_required == affected_plugin["version_available"]
            or 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