Skip to content

Commit

Permalink
reload: use new plugin interface
Browse files Browse the repository at this point in the history
  • Loading branch information
Exirel committed Feb 17, 2019
1 parent 09cae10 commit 2b3b760
Showing 1 changed file with 39 additions and 89 deletions.
128 changes: 39 additions & 89 deletions sopel/modules/reload.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,27 @@
"""
from __future__ import unicode_literals, absolute_import, print_function, division

import collections
import sys
import time
from sopel.tools import iteritems
import sopel.loader
import sopel.module
import os
import subprocess

try:
from importlib import reload
except ImportError:
import sopel.module
from sopel import plugins, tools


def _load(bot, plugin):
# handle loading's errors (if any)
try:
from imp import reload
except ImportError:
pass # fallback to builtin if neither module is available
plugin.load()
if plugin.has_setup():
plugin.setup(bot)
plugin.register(bot)
except Exception as e:
filename, lineno = tools.get_raising_file_and_line()
rel_path = os.path.relpath(filename, os.path.dirname(__file__))
raising_stmt = "%s:%d" % (rel_path, lineno)
tools.stderr(
"Error loading %s: %s (%s)" % (plugin.name, e, raising_stmt))
raise


@sopel.module.nickname_commands("reload")
Expand All @@ -36,80 +42,14 @@ def f_reload(bot, trigger):
name = trigger.group(2)

if not name or name == '*' or name.upper() == 'ALL THE THINGS':
bot._callables = {
'high': collections.defaultdict(list),
'medium': collections.defaultdict(list),
'low': collections.defaultdict(list)
}
bot._command_groups = collections.defaultdict(list)

for m in sopel.loader.enumerate_modules(bot.config):
reload_module_tree(bot, m, silent=True)

bot.reload_plugins()
return bot.reply('done')

if (name not in sys.modules and name not in sopel.loader.enumerate_modules(bot.config)):
if not bot.has_plugin(name):
return bot.reply('"%s" not loaded, try the `load` command' % name)

reload_module_tree(bot, name)


def reload_module_tree(bot, name, seen=None, silent=False):
from types import ModuleType

old_module = sys.modules[name]

if seen is None:
seen = {}
if name not in seen:
seen[name] = []

old_callables = {}
for obj_name, obj in iteritems(vars(old_module)):
if callable(obj):
bot.unregister(obj)
elif (type(obj) is ModuleType and
obj.__name__.startswith(name + '.') and
obj.__name__ not in sys.builtin_module_names):
# recurse into submodules, see issue 1056
if obj not in seen[name]:
seen[name].append(obj)
reload(obj)
reload_module_tree(bot, obj.__name__, seen, silent)

modules = sopel.loader.enumerate_modules(bot.config)
if name not in modules:
return # Only reload the top-level module, once recursion is finished

# Also remove all references to sopel callables from top level of the
# module, so that they will not get loaded again if reloading the
# module does not override them.
for obj_name in old_callables.keys():
delattr(old_module, obj_name)

# Also delete the setup function
# Sub-modules shouldn't have setup functions, so do after the recursion check
if hasattr(old_module, "setup"):
delattr(old_module, "setup")

path, type_ = modules[name]
load_module(bot, name, path, type_, silent)


def load_module(bot, name, path, type_, silent=False):
module, mtime = sopel.loader.load_module(name, path, type_)
relevant_parts = sopel.loader.clean_module(module, bot.config)

bot.register(*relevant_parts)

# TODO sys.modules[name] = module
if hasattr(module, 'setup'):
module.setup(bot)

modified = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime))

if not silent:
bot.reply('%r (version: %s)' % (module, modified))
bot.reload_plugin(name)
return bot.reply('done: %s reloaded' % name)


@sopel.module.nickname_commands('update')
Expand All @@ -135,18 +75,28 @@ def f_load(bot, trigger):
return

name = trigger.group(2)
path = ''
if not name:
return bot.reply('Load what?')

if name in sys.modules:
if bot.has_plugin(name):
return bot.reply('Module already loaded, use reload')

mods = sopel.loader.enumerate_modules(bot.config)
if name not in mods:
return bot.reply('Module %s not found' % name)
path, type_ = mods[name]
load_module(bot, name, path, type_)
for plugin, is_enabled in plugins.enumerate_plugins(bot.config):
if plugin.name == name:
if is_enabled:
try:
_load(bot, plugin)
bot.reply('Module %s loaded' % name)
except Exception as error:
bot.reply(
'Module %s can not be loaded: %s' % (name, error))
else:
bot.reply('Module %s is disabled' % name)

break
else:
# Will be triggered only if "break" is not found
bot.reply('Module %s not found' % name)


# Catch PM based messages
Expand Down

0 comments on commit 2b3b760

Please sign in to comment.