From d9d08ad0f7839892fd5c6fdf842c1fc2a73ca7b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Behmo?= Date: Mon, 1 Nov 2021 20:35:58 +0100 Subject: [PATCH 1/2] improvement: don't crash on unloadable plugins In some cases, plugins declare an entry point but cannot be loaded. This is the case when they depend on a version of tutor that is not the one that is currently installed. This use case is very frequent when working on multiple versions at the same time (i.e: right now, while we are working on the Maple release). In such cases, it's best just to ignore the plugin entirely rather than having to re-install all plugins in the virtualenv. --- CHANGELOG.md | 2 ++ tutor/plugins.py | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b774c6..e8b6fc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Note: Breaking changes between versions are indicated by "💥". ## Unreleased +- [Improvement] Ignore Python plugins which cannot be loaded. + ## v12.1.6 (2021-11-02) - [Improvement] Upgrade all services to open-release/lilac.3. diff --git a/tutor/plugins.py b/tutor/plugins.py index d8b96a1..d89ad24 100644 --- a/tutor/plugins.py +++ b/tutor/plugins.py @@ -231,14 +231,18 @@ class EntrypointPlugin(BasePlugin): def iter_load(cls) -> Iterator["EntrypointPlugin"]: for entrypoint in pkg_resources.iter_entry_points(cls.ENTRYPOINT): try: + error: Optional[str] = None yield cls(entrypoint) - except: + except pkg_resources.VersionConflict as e: + error = e.report() + except Exception as e: + error = str(e) + if error: fmt.echo_error( - "Failed to load entrypoint '{} = {}' from distribution {}".format( - entrypoint.name, entrypoint.module_name, entrypoint.dist + "Failed to load entrypoint '{} = {}' from distribution {}: {}".format( + entrypoint.name, entrypoint.module_name, entrypoint.dist, error ) ) - raise class OfficialPlugin(BasePlugin): From 485f47f6d03364d7d2fb112d588f0e6f26a28698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Behmo?= Date: Mon, 1 Nov 2021 20:42:23 +0100 Subject: [PATCH 2/2] fix: always print plugins sorted by name `tutor plugins list` used to print plugins in random oredr. To be honest this has always bothered me. --- CHANGELOG.md | 1 + tutor/plugins.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8b6fc5..ca1a09d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Note: Breaking changes between versions are indicated by "💥". ## Unreleased +- [Improvement] Make `tutor plugins list` print plugins sorted by name. - [Improvement] Ignore Python plugins which cannot be loaded. ## v12.1.6 (2021-11-02) diff --git a/tutor/plugins.py b/tutor/plugins.py index d89ad24..3cdfbf0 100644 --- a/tutor/plugins.py +++ b/tutor/plugins.py @@ -363,11 +363,14 @@ class Plugins: prevent too many re-computations, which happens a lot. """ installed_plugin_names = set() + plugins = [] for PluginClass in cls.PLUGIN_CLASSES: for plugin in PluginClass.iter_installed(): if plugin.name not in installed_plugin_names: installed_plugin_names.add(plugin.name) - yield plugin + plugins.append(plugin) + plugins = sorted(plugins, key=lambda plugin: plugin.name) + yield from plugins def iter_enabled(self) -> Iterator[BasePlugin]: for plugin in self.iter_installed():