[V3] Allow load, unload and reload to deal with multiple packages (#1441)

* [V3] Allow load, unload and reload to deal with multiple packages

This PR allows multiple packages to be loaded, unloaded or reloaded with the one command, the packages are delimited by the space character as suggested by Will
This is just the functionality, I'm sure the code could be better

* introduced helper function for getting package load strings

* missed characters

* forgotten import 👀

Forgot to include the import `inline` method from chat_formatting
This commit is contained in:
James 2018-03-21 13:32:54 +13:00 committed by palmtree5
parent 83471e0866
commit 153d710eb4

View File

@ -22,7 +22,7 @@ from redbot.core import i18n
from redbot.core import rpc from redbot.core import rpc
from redbot.core.context import RedContext from redbot.core.context import RedContext
from .utils import TYPE_CHECKING from .utils import TYPE_CHECKING
from .utils.chat_formatting import pagify, box from .utils.chat_formatting import pagify, box, inline
if TYPE_CHECKING: if TYPE_CHECKING:
from redbot.core.bot import Red from redbot.core.bot import Red
@ -312,71 +312,155 @@ class Core:
@commands.command() @commands.command()
@checks.is_owner() @checks.is_owner()
async def load(self, ctx, *, cog_name: str): async def load(self, ctx, *, cog_name: str):
"""Loads a package""" """Loads packages"""
try:
spec = await ctx.bot.cog_mgr.find_cog(cog_name) failed_packages = []
except RuntimeError: loaded_packages = []
await ctx.send(_("No module by that name was found in any" notfound_packages = []
" cog path."))
cognames = [c.strip() for c in cog_name.split(' ')]
cogspecs = []
for c in cognames:
try:
spec = await ctx.bot.cog_mgr.find_cog(c)
cogspecs.append((spec, c))
except RuntimeError:
notfound_packages.append(inline(c))
#await ctx.send(_("No module named '{}' was found in any"
# " cog path.").format(c))
if len(cogspecs) == 0:
return return
try: for spec, name in cogspecs:
await ctx.bot.load_extension(spec) try:
except Exception as e: await ctx.bot.load_extension(spec)
log.exception("Package loading failed", exc_info=e) except Exception as e:
log.exception("Package loading failed", exc_info=e)
exception_log = ("Exception in command '{}'\n" exception_log = ("Exception in command '{}'\n"
"".format(ctx.command.qualified_name)) "".format(ctx.command.qualified_name))
exception_log += "".join(traceback.format_exception(type(e), exception_log += "".join(traceback.format_exception(type(e),
e, e.__traceback__)) e, e.__traceback__))
self.bot._last_exception = exception_log self.bot._last_exception = exception_log
failed_packages.append(inline(name))
else:
await ctx.bot.add_loaded_package(name)
loaded_packages.append(inline(name))
await ctx.send(_("Failed to load package. Check your console or " if loaded_packages:
"logs for details.")) fmt = "Loaded {packs}"
else: formed = self.get_package_strings(loaded_packages, fmt)
await ctx.bot.add_loaded_package(cog_name) await ctx.send(_(formed))
await ctx.send(_("Done."))
if failed_packages:
fmt = ("Failed to load package{plural} {packs}. Check your console or "
"logs for details.")
formed = self.get_package_strings(failed_packages, fmt)
await ctx.send(_(formed))
if notfound_packages:
fmt = 'The package{plural} {packs} {other} not found in any cog path.'
formed = self.get_package_strings(notfound_packages, fmt, ('was', 'were'))
await ctx.send(_(formed))
@commands.group() @commands.group()
@checks.is_owner() @checks.is_owner()
async def unload(self, ctx, *, cog_name: str): async def unload(self, ctx, *, cog_name: str):
"""Unloads a package""" """Unloads packages"""
if cog_name in ctx.bot.extensions: cognames = [c.strip() for c in cog_name.split(' ')]
ctx.bot.unload_extension(cog_name) failed_packages = []
await ctx.bot.remove_loaded_package(cog_name) unloaded_packages = []
await ctx.send(_("Done."))
else: for c in cognames:
await ctx.send(_("That extension is not loaded.")) if c in ctx.bot.extensions:
ctx.bot.unload_extension(c)
await ctx.bot.remove_loaded_package(c)
unloaded_packages.append(inline(c))
else:
failed_packages.append(inline(c))
if unloaded_packages:
fmt = "Package{plural} {packs} {other} unloaded."
formed = self.get_package_strings(unloaded_packages, fmt, ('was', 'were'))
await ctx.send(_(formed))
if failed_packages:
fmt = "The package{plural} {packs} {other} not loaded."
formed = self.get_package_strings(failed_packages, fmt, ('is', 'are'))
await ctx.send(_(formed))
@commands.command(name="reload") @commands.command(name="reload")
@checks.is_owner() @checks.is_owner()
async def _reload(self, ctx, *, cog_name: str): async def _reload(self, ctx, *, cog_name: str):
"""Reloads a package""" """Reloads packages"""
ctx.bot.unload_extension(cog_name)
try: cognames = [c.strip() for c in cog_name.split(' ')]
spec = await ctx.bot.cog_mgr.find_cog(cog_name)
except RuntimeError:
await ctx.send(_("No module by that name was found in any"
" cog path."))
return
try: for c in cognames:
self.cleanup_and_refresh_modules(spec.name) ctx.bot.unload_extension(c)
await ctx.bot.load_extension(spec)
except Exception as e:
log.exception("Package reloading failed", exc_info=e)
exception_log = ("Exception in command '{}'\n" cogspecs = []
"".format(ctx.command.qualified_name)) failed_packages = []
exception_log += "".join(traceback.format_exception(type(e), loaded_packages = []
e, e.__traceback__)) notfound_packages = []
self.bot._last_exception = exception_log
await ctx.send(_("Failed to reload package. Check your console or " for c in cognames:
"logs for details.")) try:
else: spec = await ctx.bot.cog_mgr.find_cog(c)
await ctx.send(_("Done.")) cogspecs.append((spec, c))
except RuntimeError:
notfound_packages.append(inline(c))
for spec, name in cogspecs:
try:
self.cleanup_and_refresh_modules(spec.name)
await ctx.bot.load_extension(spec)
loaded_packages.append(inline(name))
except Exception as e:
log.exception("Package reloading failed", exc_info=e)
exception_log = ("Exception in command '{}'\n"
"".format(ctx.command.qualified_name))
exception_log += "".join(traceback.format_exception(type(e),
e, e.__traceback__))
self.bot._last_exception = exception_log
failed_packages.append(inline(name))
if loaded_packages:
fmt = "Package{plural} {packs} {other} reloaded."
formed = self.get_package_strings(loaded_packages, fmt, ('was', 'were'))
await ctx.send(_(formed))
if failed_packages:
fmt = ("Failed to reload package{plural} {packs}. Check your "
"logs for details")
formed = self.get_package_strings(failed_packages, fmt)
await ctx.send(_(formed))
if notfound_packages:
fmt = 'The package{plural} {packs} {other} not found in any cog path.'
formed = self.get_package_strings(notfound_packages, fmt, ('was', 'were'))
await ctx.send(_(formed))
def get_package_strings(self, packages: list, fmt: str, other: tuple=None):
"""
Gets the strings needed for the load, unload and reload commands
"""
if other is None:
other = ('', '')
plural = 's' if len(packages) > 1 else ''
use_and, other = ('', other[0]) if len(packages) == 1 else (' and ', other[1])
packages_string = ', '.join(packages[:-1]) + use_and + packages[-1]
form = {'plural': plural,
'packs' : packages_string,
'other' : other
}
final_string = fmt.format(**form)
return final_string
@commands.command(name="shutdown") @commands.command(name="shutdown")
@checks.is_owner() @checks.is_owner()