Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin: reload using new interface #1490

Closed
wants to merge 15 commits into from
Closed

Conversation

Exirel
Copy link
Contributor

@Exirel Exirel commented Feb 16, 2019

Based on #1479 - this PR starts at the plugin: add AbstractPluginHandler.reload commit.

Using the new plugin interface defined in sopel.plugins, I replaced how plugins are reloaded in sopel.modules.reload:

  • sopel.bot.Sopel now exposes methods to add, remove, and reload plugins
  • sopel.modules.reload uses the bot's method to reload plugins (all of them, or only one)
  • sopel.plugin.handlers.AbstractPluginHandler defines a new reload method
  • sopel.plugin.handlers.AbstractPluginHandler's implementations use the bot's new methods to add or remove the plugin

It Is Not Perfect And Here Is Why

There are problems unsolved and questions unanswered here:

  1. Problem: module tree is not reloaded, only the main file (can and must be fixed),
  2. Problem: Python's imp.reload and importlib.reload do not remove names undefined in a new version of a reloaded module (fix possible only with Py3.4+),
  3. Problem: Job's management is still a mess (same as before),
  4. Question: should we use (updated) configuration?

Problem 1: Reload Module Tree

This one is a big problem to solve, because there is more than meets the eye:

  • reloading the module tree must not reload built-in or externals modules,
  • but because of that a reload may fail if an external module has been changed in a way that it requires a reload...

This leads me to conclude that .reload should not be used in production in these cases. And they are hard as hell to fix, or even to warn the user about.

So it's half a problem, half a question. And I don't have the answer either way.

Problem 2: Python's reload Is Weird

Note: this behavior is the one currently in place in Sopel. This is not new.

Both imp.reload and importlib.reload have this weird behavior, explained by this line from the documentation (python2 reload / python3 importlib.reload):

If the new version of a module does not define a name that was defined by the old version, the old definition remains.

Meaning that:

  1. a module has a function something, is loaded at Sopel's startup
  2. this module is modified, and something does not exist anymore
  3. .reload <this-module> command is used
  4. something still exists and is seen by Sopel, no matter what we do,

However, this can be fixed... with Python 3.4's public internals (namely, importlib.util and importlib.machinery) (see a snippet of code). By the way, using Py3.4's public machinery would fix Problem 1 too...

Problem 3: Job Are Weird Too

Note: this behavior is the one currently in place in Sopel. This is not new.

I didn't change any of the "unregister a job" behavior, so this is something that requires more work. The good part is: this can be done in a future PR, without any consequences so far, because it's already like that right now.

Question: Does .reload Should Use Updated Configuration?

In Sopel's current version, .reload uses the current configuration (potentially modified since startup), to gather a list of plugins:

  • if a plugin has been disabled, it might not be unloaded properly,
  • if a plugin has been enabled, it will load it, somehow

And that is a problem for me, because it means inconsistency and unexpected behavior. I would rather have something stable, that always work, in a predicable way, than the current behavior.

That's why this new version reloads the list of plugins as it exists at the moment in the bot's memory (ie. in bot._plugins). We could, if we want, change this behavior to unload a plugin (enabled or not), and to load only the plugin if it's still enabled, and enable all new enabled plugins.

And that's the question: what should we do?

Each plugin has a name, but it might not be unique. These plugins have
the same "name" (here, "xkcd"):

* `sopel.modules.xkcd`,
* `~/.sopel/modules/xkcd.py`,

but only one can be loaded as the `xkcd` plugin.

For that purpose, the previous implementation used a `dict`, without
consideration for loading order.

The new implementation uses an `OrderedDict`, to keep the same behavior
(last plugin found overrides previous ones), but also to make sure to
always load the core plugin at the end of the process.
@Exirel
Copy link
Contributor Author

Exirel commented Feb 17, 2019

Looking at issues:

Overall, "reload" in Python is very hard, and I'm not sure we can really fix it. There are too many use cases and corner cases where we don't have the right tools for that.

@Exirel
Copy link
Contributor Author

Exirel commented Mar 25, 2019

So, after further consideration, I've some issues to fix first.

@Exirel
Copy link
Contributor Author

Exirel commented Mar 25, 2019

So, I decided to merge this branch into #1479 because it makes my job way easier, and I think it does not make sense anymore to separate the new loading from reloading using new loading.

So, I keep that around for history (I keep the branch as-is, too), but everything will happen in #1479 now!

@Exirel Exirel closed this Mar 25, 2019
@dgw
Copy link
Member

dgw commented Mar 25, 2019

So, I decided to merge this branch into #1479 because it makes my job way easier, and I think it does not make sense anymore to separate the new loading from reloading using new loading.

Makes sense to me. :)

@dgw dgw removed this from the 7.0.0 milestone Mar 25, 2019
@dgw dgw added Replaced Superseded by a newer PR and removed Work In Progress labels Mar 25, 2019
@Exirel Exirel mentioned this pull request Mar 25, 2019
@Exirel Exirel deleted the plugin-reload branch March 26, 2019 18:29
@dgw dgw removed their request for review March 27, 2019 21:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Replaced Superseded by a newer PR Tweak
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants