From 016bdd542a660d67a8a5156d5f34de9fe1e31cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 29 Jun 2015 10:13:44 +0200 Subject: [PATCH] Fix: More flexibility when parsing plugin compatibility If compatibility information is provided only as a version number it's prefixed with >= for the check (so stating a compatibility of only 1.2.0 will now make the plugin compatible to all versions that follow too). Alternatively the compatibility information may now contain stuff like ">=1.2,<1.3" in which case the plugin will only be shown as compatible to OctoPrint versions 1.2 and up but not 1.3 or anything above that. (cherry picked from commit d5692d7) --- .../plugins/pluginmanager/__init__.py | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/octoprint/plugins/pluginmanager/__init__.py b/src/octoprint/plugins/pluginmanager/__init__.py index 152d9b41..ab228763 100644 --- a/src/octoprint/plugins/pluginmanager/__init__.py +++ b/src/octoprint/plugins/pluginmanager/__init__.py @@ -510,22 +510,46 @@ class PluginManagerPlugin(octoprint.plugin.SimpleApiPlugin, if "compatibility" in entry: if "octoprint" in entry["compatibility"] and entry["compatibility"]["octoprint"] is not None and len(entry["compatibility"]["octoprint"]): - import semantic_version - for octo_compat in entry["compatibility"]["octoprint"]: - s = semantic_version.Spec("=={}".format(octo_compat)) - if semantic_version.Version(octoprint_version) in s: - break - else: - result["is_compatible"]["octoprint"] = False + result["is_compatible"]["octoprint"] = self._is_octoprint_compatible(octoprint_version, entry["compatibility"]["octoprint"]) if "os" in entry["compatibility"] and entry["compatibility"]["os"] is not None and len(entry["compatibility"]["os"]): - result["is_compatible"]["os"] = current_os in entry["compatibility"]["os"] + result["is_compatible"]["os"] = self._is_os_compatible(current_os, entry["compatibility"]["os"]) return result self._repository_plugins = map(map_repository_entry, repo_data) return True + def _is_octoprint_compatible(self, octoprint_version, compatibility_entries): + """ + Tests if the current ``octoprint_version`` is compatible to any of the provided ``compatibility_entries``. + """ + import semantic_version + + for octo_compat in compatibility_entries: + for version_string in (octo_compat, ">={}".format(octo_compat)): + try: + s = semantic_version.Spec(version_string) + if semantic_version.Version(octoprint_version) in s: + break + except ValueError: + # that just means that octo_compat directly wasn't a valid version spec string, so we try + # prefixing that with ">=" next and check again + pass + else: + continue + break + else: + return False + + return True + + def _is_os_compatible(self, current_os, compatibility_entries): + """ + Tests if the ``current_os`` matches any of the provided ``compatibility_entries``. + """ + return current_os in compatibility_entries + def _get_os(self): if sys.platform == "win32": return "windows"