mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-07 11:48:55 -05:00
Fix RPC cog load and unload by returning dicts (#5453)
* use dicts for CoreLogic package management returns * address review * failed_packages->notloaded_packages in _unload Co-authored-by: jack1142 <6032823+jack1142@users.noreply.github.com>
This commit is contained in:
parent
a228a0d0b3
commit
d27dbded8a
@ -116,11 +116,7 @@ class CoreLogic:
|
|||||||
self.bot.register_rpc_handler(self._version_info)
|
self.bot.register_rpc_handler(self._version_info)
|
||||||
self.bot.register_rpc_handler(self._invite_url)
|
self.bot.register_rpc_handler(self._invite_url)
|
||||||
|
|
||||||
async def _load(
|
async def _load(self, pkg_names: Iterable[str]) -> Dict[str, Union[List[str], Dict[str, str]]]:
|
||||||
self, pkg_names: Iterable[str]
|
|
||||||
) -> Tuple[
|
|
||||||
List[str], List[str], List[str], List[str], List[str], List[Tuple[str, str]], Set[str]
|
|
||||||
]:
|
|
||||||
"""
|
"""
|
||||||
Loads packages by name.
|
Loads packages by name.
|
||||||
|
|
||||||
@ -131,23 +127,23 @@ class CoreLogic:
|
|||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
tuple
|
dict
|
||||||
7-tuple of:
|
Dictionary with keys:
|
||||||
1. List of names of packages that loaded successfully
|
``loaded_packages``: List of names of packages that loaded successfully
|
||||||
2. List of names of packages that failed to load without specified reason
|
``failed_packages``: List of names of packages that failed to load without specified reason
|
||||||
3. List of names of packages that don't have a valid package name
|
``invalid_pkg_names``: List of names of packages that don't have a valid package name
|
||||||
4. List of names of packages that weren't found in any cog path
|
``notfound_packages``: List of names of packages that weren't found in any cog path
|
||||||
5. List of names of packages that are already loaded
|
``alreadyloaded_packages``: List of names of packages that are already loaded
|
||||||
6. List of 2-tuples (pkg_name, reason) for packages
|
``failed_with_reason_packages``: Dictionary of packages that failed to load with
|
||||||
that failed to load with a specified reason
|
a specified reason with mapping of package names -> failure reason
|
||||||
7. Set of repo names that use deprecated shared libraries
|
``repos_with_shared_libs``: List of repo names that use deprecated shared libraries
|
||||||
"""
|
"""
|
||||||
failed_packages = []
|
failed_packages = []
|
||||||
loaded_packages = []
|
loaded_packages = []
|
||||||
invalid_pkg_names = []
|
invalid_pkg_names = []
|
||||||
notfound_packages = []
|
notfound_packages = []
|
||||||
alreadyloaded_packages = []
|
alreadyloaded_packages = []
|
||||||
failed_with_reason_packages = []
|
failed_with_reason_packages = {}
|
||||||
repos_with_shared_libs = set()
|
repos_with_shared_libs = set()
|
||||||
|
|
||||||
bot = self.bot
|
bot = self.bot
|
||||||
@ -179,7 +175,7 @@ class CoreLogic:
|
|||||||
except errors.PackageAlreadyLoaded:
|
except errors.PackageAlreadyLoaded:
|
||||||
alreadyloaded_packages.append(name)
|
alreadyloaded_packages.append(name)
|
||||||
except errors.CogLoadError as e:
|
except errors.CogLoadError as e:
|
||||||
failed_with_reason_packages.append((name, str(e)))
|
failed_with_reason_packages[name] = str(e)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if isinstance(e, commands.CommandRegistrationError):
|
if isinstance(e, commands.CommandRegistrationError):
|
||||||
if e.alias_conflict:
|
if e.alias_conflict:
|
||||||
@ -192,7 +188,7 @@ class CoreLogic:
|
|||||||
"Command {command_name} is already an existing command"
|
"Command {command_name} is already an existing command"
|
||||||
" or alias in one of the loaded cogs."
|
" or alias in one of the loaded cogs."
|
||||||
).format(command_name=inline(e.name))
|
).format(command_name=inline(e.name))
|
||||||
failed_with_reason_packages.append((name, error_message))
|
failed_with_reason_packages[name] = error_message
|
||||||
continue
|
continue
|
||||||
|
|
||||||
log.exception("Package loading failed", exc_info=e)
|
log.exception("Package loading failed", exc_info=e)
|
||||||
@ -219,15 +215,15 @@ class CoreLogic:
|
|||||||
if maybe_repo is not None:
|
if maybe_repo is not None:
|
||||||
repos_with_shared_libs.add(maybe_repo.name)
|
repos_with_shared_libs.add(maybe_repo.name)
|
||||||
|
|
||||||
return (
|
return {
|
||||||
loaded_packages,
|
"loaded_packages": loaded_packages,
|
||||||
failed_packages,
|
"failed_packages": failed_packages,
|
||||||
invalid_pkg_names,
|
"invalid_pkg_names": invalid_pkg_names,
|
||||||
notfound_packages,
|
"notfound_packages": notfound_packages,
|
||||||
alreadyloaded_packages,
|
"alreadyloaded_packages": alreadyloaded_packages,
|
||||||
failed_with_reason_packages,
|
"failed_with_reason_packages": failed_with_reason_packages,
|
||||||
repos_with_shared_libs,
|
"repos_with_shared_libs": list(repos_with_shared_libs),
|
||||||
)
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _cleanup_and_refresh_modules(module_name: str) -> None:
|
def _cleanup_and_refresh_modules(module_name: str) -> None:
|
||||||
@ -255,7 +251,7 @@ class CoreLogic:
|
|||||||
for child_name, lib in children.items():
|
for child_name, lib in children.items():
|
||||||
importlib._bootstrap._exec(lib.__spec__, lib)
|
importlib._bootstrap._exec(lib.__spec__, lib)
|
||||||
|
|
||||||
async def _unload(self, pkg_names: Iterable[str]) -> Tuple[List[str], List[str]]:
|
async def _unload(self, pkg_names: Iterable[str]) -> Dict[str, List[str]]:
|
||||||
"""
|
"""
|
||||||
Unloads packages with the given names.
|
Unloads packages with the given names.
|
||||||
|
|
||||||
@ -266,10 +262,13 @@ class CoreLogic:
|
|||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
tuple
|
dict
|
||||||
2 element tuple of successful unloads and failed unloads.
|
Dictionary with keys:
|
||||||
|
``unloaded_packages``: List of names of packages that unloaded successfully.
|
||||||
|
``notloaded_packages``: List of names of packages that weren't unloaded
|
||||||
|
because they weren't loaded.
|
||||||
"""
|
"""
|
||||||
failed_packages = []
|
notloaded_packages = []
|
||||||
unloaded_packages = []
|
unloaded_packages = []
|
||||||
|
|
||||||
bot = self.bot
|
bot = self.bot
|
||||||
@ -280,15 +279,13 @@ class CoreLogic:
|
|||||||
await bot.remove_loaded_package(name)
|
await bot.remove_loaded_package(name)
|
||||||
unloaded_packages.append(name)
|
unloaded_packages.append(name)
|
||||||
else:
|
else:
|
||||||
failed_packages.append(name)
|
notloaded_packages.append(name)
|
||||||
|
|
||||||
return unloaded_packages, failed_packages
|
return {"unloaded_packages": unloaded_packages, "notloaded_packages": notloaded_packages}
|
||||||
|
|
||||||
async def _reload(
|
async def _reload(
|
||||||
self, pkg_names: Sequence[str]
|
self, pkg_names: Sequence[str]
|
||||||
) -> Tuple[
|
) -> Dict[str, Union[List[str], Dict[str, str]]]:
|
||||||
List[str], List[str], List[str], List[str], List[str], List[Tuple[str, str]], Set[str]
|
|
||||||
]:
|
|
||||||
"""
|
"""
|
||||||
Reloads packages with the given names.
|
Reloads packages with the given names.
|
||||||
|
|
||||||
@ -299,30 +296,12 @@ class CoreLogic:
|
|||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
tuple
|
dict
|
||||||
Tuple as returned by `CoreLogic._load()`
|
Dictionary with keys as returned by `CoreLogic._load()`
|
||||||
"""
|
"""
|
||||||
await self._unload(pkg_names)
|
await self._unload(pkg_names)
|
||||||
|
|
||||||
(
|
return await self._load(pkg_names)
|
||||||
loaded,
|
|
||||||
load_failed,
|
|
||||||
invalid_pkg_names,
|
|
||||||
not_found,
|
|
||||||
already_loaded,
|
|
||||||
load_failed_with_reason,
|
|
||||||
repos_with_shared_libs,
|
|
||||||
) = await self._load(pkg_names)
|
|
||||||
|
|
||||||
return (
|
|
||||||
loaded,
|
|
||||||
load_failed,
|
|
||||||
invalid_pkg_names,
|
|
||||||
not_found,
|
|
||||||
already_loaded,
|
|
||||||
load_failed_with_reason,
|
|
||||||
repos_with_shared_libs,
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _name(self, name: Optional[str] = None) -> str:
|
async def _name(self, name: Optional[str] = None) -> str:
|
||||||
"""
|
"""
|
||||||
@ -1698,24 +1677,16 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
"""
|
"""
|
||||||
cogs = tuple(map(lambda cog: cog.rstrip(","), cogs))
|
cogs = tuple(map(lambda cog: cog.rstrip(","), cogs))
|
||||||
async with ctx.typing():
|
async with ctx.typing():
|
||||||
(
|
outcomes = await self._load(cogs)
|
||||||
loaded,
|
|
||||||
failed,
|
|
||||||
invalid_pkg_names,
|
|
||||||
not_found,
|
|
||||||
already_loaded,
|
|
||||||
failed_with_reason,
|
|
||||||
repos_with_shared_libs,
|
|
||||||
) = await self._load(cogs)
|
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
|
|
||||||
if loaded:
|
if loaded := outcomes["loaded_packages"]:
|
||||||
loaded_packages = humanize_list([inline(package) for package in loaded])
|
loaded_packages = humanize_list([inline(package) for package in loaded])
|
||||||
formed = _("Loaded {packs}.").format(packs=loaded_packages)
|
formed = _("Loaded {packs}.").format(packs=loaded_packages)
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if already_loaded:
|
if already_loaded := outcomes["alreadyloaded_packages"]:
|
||||||
if len(already_loaded) == 1:
|
if len(already_loaded) == 1:
|
||||||
formed = _("The following package is already loaded: {pack}").format(
|
formed = _("The following package is already loaded: {pack}").format(
|
||||||
pack=inline(already_loaded[0])
|
pack=inline(already_loaded[0])
|
||||||
@ -1726,7 +1697,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
)
|
)
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if failed:
|
if failed := outcomes["failed_packages"]:
|
||||||
if len(failed) == 1:
|
if len(failed) == 1:
|
||||||
formed = _(
|
formed = _(
|
||||||
"Failed to load the following package: {pack}."
|
"Failed to load the following package: {pack}."
|
||||||
@ -1739,7 +1710,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
).format(packs=humanize_list([inline(package) for package in failed]))
|
).format(packs=humanize_list([inline(package) for package in failed]))
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if invalid_pkg_names:
|
if invalid_pkg_names := outcomes["invalid_pkg_names"]:
|
||||||
if len(invalid_pkg_names) == 1:
|
if len(invalid_pkg_names) == 1:
|
||||||
formed = _(
|
formed = _(
|
||||||
"The following name is not a valid package name: {pack}\n"
|
"The following name is not a valid package name: {pack}\n"
|
||||||
@ -1754,7 +1725,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
).format(packs=humanize_list([inline(package) for package in invalid_pkg_names]))
|
).format(packs=humanize_list([inline(package) for package in invalid_pkg_names]))
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if not_found:
|
if not_found := outcomes["notfound_packages"]:
|
||||||
if len(not_found) == 1:
|
if len(not_found) == 1:
|
||||||
formed = _("The following package was not found in any cog path: {pack}.").format(
|
formed = _("The following package was not found in any cog path: {pack}.").format(
|
||||||
pack=inline(not_found[0])
|
pack=inline(not_found[0])
|
||||||
@ -1765,8 +1736,8 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
).format(packs=humanize_list([inline(package) for package in not_found]))
|
).format(packs=humanize_list([inline(package) for package in not_found]))
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if failed_with_reason:
|
if failed_with_reason := outcomes["failed_with_reason_packages"]:
|
||||||
reasons = "\n".join([f"`{x}`: {y}" for x, y in failed_with_reason])
|
reasons = "\n".join([f"`{x}`: {y}" for x, y in failed_with_reason.items()])
|
||||||
if len(failed_with_reason) == 1:
|
if len(failed_with_reason) == 1:
|
||||||
formed = _(
|
formed = _(
|
||||||
"This package could not be loaded for the following reason:\n\n{reason}"
|
"This package could not be loaded for the following reason:\n\n{reason}"
|
||||||
@ -1777,7 +1748,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
).format(reasons=reasons)
|
).format(reasons=reasons)
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if repos_with_shared_libs:
|
if repos_with_shared_libs := outcomes["repos_with_shared_libs"]:
|
||||||
if len(repos_with_shared_libs) == 1:
|
if len(repos_with_shared_libs) == 1:
|
||||||
formed = _(
|
formed = _(
|
||||||
"**WARNING**: The following repo is using shared libs"
|
"**WARNING**: The following repo is using shared libs"
|
||||||
@ -1816,11 +1787,11 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
- `<cogs...>` - The cog packages to unload.
|
- `<cogs...>` - The cog packages to unload.
|
||||||
"""
|
"""
|
||||||
cogs = tuple(map(lambda cog: cog.rstrip(","), cogs))
|
cogs = tuple(map(lambda cog: cog.rstrip(","), cogs))
|
||||||
unloaded, failed = await self._unload(cogs)
|
outcomes = await self._unload(cogs)
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
|
|
||||||
if unloaded:
|
if unloaded := outcomes["unloaded_packages"]:
|
||||||
if len(unloaded) == 1:
|
if len(unloaded) == 1:
|
||||||
formed = _("The following package was unloaded: {pack}.").format(
|
formed = _("The following package was unloaded: {pack}.").format(
|
||||||
pack=inline(unloaded[0])
|
pack=inline(unloaded[0])
|
||||||
@ -1831,7 +1802,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
)
|
)
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if failed:
|
if failed := outcomes["notloaded_packages"]:
|
||||||
if len(failed) == 1:
|
if len(failed) == 1:
|
||||||
formed = _("The following package was not loaded: {pack}.").format(
|
formed = _("The following package was not loaded: {pack}.").format(
|
||||||
pack=inline(failed[0])
|
pack=inline(failed[0])
|
||||||
@ -1865,24 +1836,16 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
"""
|
"""
|
||||||
cogs = tuple(map(lambda cog: cog.rstrip(","), cogs))
|
cogs = tuple(map(lambda cog: cog.rstrip(","), cogs))
|
||||||
async with ctx.typing():
|
async with ctx.typing():
|
||||||
(
|
outcomes = await self._reload(cogs)
|
||||||
loaded,
|
|
||||||
failed,
|
|
||||||
invalid_pkg_names,
|
|
||||||
not_found,
|
|
||||||
already_loaded,
|
|
||||||
failed_with_reason,
|
|
||||||
repos_with_shared_libs,
|
|
||||||
) = await self._reload(cogs)
|
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
|
|
||||||
if loaded:
|
if loaded := outcomes["loaded_packages"]:
|
||||||
loaded_packages = humanize_list([inline(package) for package in loaded])
|
loaded_packages = humanize_list([inline(package) for package in loaded])
|
||||||
formed = _("Reloaded {packs}.").format(packs=loaded_packages)
|
formed = _("Reloaded {packs}.").format(packs=loaded_packages)
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if failed:
|
if failed := outcomes["failed_packages"]:
|
||||||
if len(failed) == 1:
|
if len(failed) == 1:
|
||||||
formed = _(
|
formed = _(
|
||||||
"Failed to reload the following package: {pack}."
|
"Failed to reload the following package: {pack}."
|
||||||
@ -1895,7 +1858,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
).format(packs=humanize_list([inline(package) for package in failed]))
|
).format(packs=humanize_list([inline(package) for package in failed]))
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if invalid_pkg_names:
|
if invalid_pkg_names := outcomes["invalid_pkg_names"]:
|
||||||
if len(invalid_pkg_names) == 1:
|
if len(invalid_pkg_names) == 1:
|
||||||
formed = _(
|
formed = _(
|
||||||
"The following name is not a valid package name: {pack}\n"
|
"The following name is not a valid package name: {pack}\n"
|
||||||
@ -1910,7 +1873,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
).format(packs=humanize_list([inline(package) for package in invalid_pkg_names]))
|
).format(packs=humanize_list([inline(package) for package in invalid_pkg_names]))
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if not_found:
|
if not_found := outcomes["notfound_packages"]:
|
||||||
if len(not_found) == 1:
|
if len(not_found) == 1:
|
||||||
formed = _("The following package was not found in any cog path: {pack}.").format(
|
formed = _("The following package was not found in any cog path: {pack}.").format(
|
||||||
pack=inline(not_found[0])
|
pack=inline(not_found[0])
|
||||||
@ -1921,8 +1884,8 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
).format(packs=humanize_list([inline(package) for package in not_found]))
|
).format(packs=humanize_list([inline(package) for package in not_found]))
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if failed_with_reason:
|
if failed_with_reason := outcomes["failed_with_reason_packages"]:
|
||||||
reasons = "\n".join([f"`{x}`: {y}" for x, y in failed_with_reason])
|
reasons = "\n".join([f"`{x}`: {y}" for x, y in failed_with_reason.items()])
|
||||||
if len(failed_with_reason) == 1:
|
if len(failed_with_reason) == 1:
|
||||||
formed = _(
|
formed = _(
|
||||||
"This package could not be reloaded for the following reason:\n\n{reason}"
|
"This package could not be reloaded for the following reason:\n\n{reason}"
|
||||||
@ -1933,7 +1896,7 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
).format(reasons=reasons)
|
).format(reasons=reasons)
|
||||||
output.append(formed)
|
output.append(formed)
|
||||||
|
|
||||||
if repos_with_shared_libs:
|
if repos_with_shared_libs := outcomes["repos_with_shared_libs"]:
|
||||||
if len(repos_with_shared_libs) == 1:
|
if len(repos_with_shared_libs) == 1:
|
||||||
formed = _(
|
formed = _(
|
||||||
"**WARNING**: The following repo is using shared libs"
|
"**WARNING**: The following repo is using shared libs"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user