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

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

Merged
merged 5 commits into from
Mar 21, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 138 additions & 54 deletions redbot/core/core_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from redbot.core import rpc
from redbot.core.context import RedContext
from .utils import TYPE_CHECKING
from .utils.chat_formatting import pagify, box
from .utils.chat_formatting import pagify, box, inline

if TYPE_CHECKING:
from redbot.core.bot import Red
Expand Down Expand Up @@ -312,71 +312,155 @@ def conf_check(m):
@commands.command()
@checks.is_owner()
async def load(self, ctx, *, cog_name: str):
"""Loads a package"""
try:
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."))
"""Loads packages"""

failed_packages = []
loaded_packages = []
notfound_packages = []

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

try:
await ctx.bot.load_extension(spec)
except Exception as e:
log.exception("Package loading 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

await ctx.send(_("Failed to load package. Check your console or "
"logs for details."))
else:
await ctx.bot.add_loaded_package(cog_name)
await ctx.send(_("Done."))
for spec, name in cogspecs:
try:
await ctx.bot.load_extension(spec)
except Exception as e:
log.exception("Package loading 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))
else:
await ctx.bot.add_loaded_package(name)
loaded_packages.append(inline(name))

if loaded_packages:
fmt = "Loaded {packs}"
formed = self.get_package_strings(loaded_packages, fmt)
await ctx.send(_(formed))

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()
@checks.is_owner()
async def unload(self, ctx, *, cog_name: str):
"""Unloads a package"""
if cog_name in ctx.bot.extensions:
ctx.bot.unload_extension(cog_name)
await ctx.bot.remove_loaded_package(cog_name)
await ctx.send(_("Done."))
else:
await ctx.send(_("That extension is not loaded."))
"""Unloads packages"""
cognames = [c.strip() for c in cog_name.split(' ')]
failed_packages = []
unloaded_packages = []

for c in cognames:
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")
@checks.is_owner()
async def _reload(self, ctx, *, cog_name: str):
"""Reloads a package"""
ctx.bot.unload_extension(cog_name)
"""Reloads packages"""

try:
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
cognames = [c.strip() for c in cog_name.split(' ')]

for c in cognames:
ctx.bot.unload_extension(c)

try:
self.cleanup_and_refresh_modules(spec.name)
await ctx.bot.load_extension(spec)
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

await ctx.send(_("Failed to reload package. Check your console or "
"logs for details."))
else:
await ctx.send(_("Done."))
cogspecs = []
failed_packages = []
loaded_packages = []
notfound_packages = []

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))

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")
@checks.is_owner()
Expand Down