[CogManager] Correctly separate core, install and other cog paths (#1983)

* [CogManager] Correctly manage core and install paths

This keeps the core and install paths separate from those set in the
config.

It also displays the core path separately in `[p]paths`

Resolves #1982.

* [CogManager] Fix old reference to method removed in previous commit

Also did a bit of a general cleanup of cog_manager.py's code

* Make the core path a class attribute

* [CogManager] Paths should default to a list
This commit is contained in:
Toby Harradine 2018-08-11 13:31:26 +10:00 committed by GitHub
parent 75ed749cb3
commit 47350328e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -35,12 +35,13 @@ class CogManager:
bot directory.
"""
CORE_PATH = Path(redbot.cogs.__path__[0])
def __init__(self, paths: Tuple[str] = ()):
self.conf = Config.get_conf(self, 2938473984732, True)
tmp_cog_install_path = cog_data_path(self) / "cogs"
tmp_cog_install_path.mkdir(parents=True, exist_ok=True)
self.conf.register_global(paths=(), install_path=str(tmp_cog_install_path))
self.conf.register_global(paths=[], install_path=str(tmp_cog_install_path))
self._paths = [Path(p) for p in paths]
async def paths(self) -> Tuple[Path, ...]:
@ -54,18 +55,13 @@ class CogManager:
"""
conf_paths = [Path(p) for p in await self.conf.paths()]
other_paths = self._paths
core_paths = await self.core_paths()
all_paths = _deduplicate(list(conf_paths) + list(other_paths) + core_paths)
all_paths = _deduplicate(list(conf_paths) + list(other_paths) + [self.CORE_PATH])
if self.install_path not in all_paths:
all_paths.insert(0, await self.install_path())
return tuple(p.resolve() for p in all_paths if p.is_dir())
async def core_paths(self) -> List[Path]:
core_paths = [Path(p) for p in redbot.cogs.__path__]
return core_paths
async def install_path(self) -> Path:
"""Get the install path for 3rd party cogs.
@ -155,10 +151,12 @@ class CogManager:
if path == await self.install_path():
raise ValueError("Cannot add the install path as an additional path.")
if path == self.CORE_PATH:
raise ValueError("Cannot add the core path as an additional path.")
all_paths = _deduplicate(await self.paths() + (path,))
# noinspection PyTypeChecker
await self.set_paths(all_paths)
async with self.conf.paths() as paths:
if not any(Path(p) == path for p in paths):
paths.append(str(path))
async def remove_path(self, path: Union[Path, str]) -> Tuple[Path, ...]:
"""Remove a path from the current paths list.
@ -174,12 +172,14 @@ class CogManager:
Tuple of new valid paths.
"""
path = self._ensure_path_obj(path)
all_paths = list(await self.paths())
if path in all_paths:
all_paths.remove(path) # Modifies in place
await self.set_paths(all_paths)
return tuple(all_paths)
path = self._ensure_path_obj(path).resolve()
paths = [Path(p) for p in await self.conf.paths()]
if path in paths:
paths.remove(path)
await self.set_paths(paths)
return tuple(paths)
async def set_paths(self, paths_: List[Path]):
"""Set the current paths list.
@ -213,9 +213,8 @@ class CogManager:
When no matching spec can be found.
"""
resolved_paths = _deduplicate(await self.paths())
core_paths = _deduplicate(await self.core_paths())
real_paths = [str(p) for p in resolved_paths if p not in core_paths]
real_paths = [str(p) for p in resolved_paths if p != self.CORE_PATH]
for finder, module_name, _ in pkgutil.iter_modules(real_paths):
if name == module_name:
@ -228,7 +227,8 @@ class CogManager:
" in any available path.".format(name)
)
async def _find_core_cog(self, name: str) -> ModuleSpec:
@staticmethod
async def _find_core_cog(name: str) -> ModuleSpec:
"""
Attempts to find a spec for a core cog.
@ -310,7 +310,8 @@ _ = Translator("CogManagerUI", __file__)
class CogManagerUI:
"""Commands to interface with Red's cog manager."""
async def visible_paths(self, ctx):
@staticmethod
async def visible_paths(ctx):
install_path = await ctx.bot.cog_mgr.install_path()
cog_paths = await ctx.bot.cog_mgr.paths()
cog_paths = [p for p in cog_paths if p != install_path]
@ -322,11 +323,15 @@ class CogManagerUI:
"""
Lists current cog paths in order of priority.
"""
install_path = await ctx.bot.cog_mgr.install_path()
cog_paths = await ctx.bot.cog_mgr.paths()
cog_paths = [p for p in cog_paths if p != install_path]
cog_mgr = ctx.bot.cog_mgr
install_path = await cog_mgr.install_path()
core_path = cog_mgr.CORE_PATH
cog_paths = await cog_mgr.paths()
cog_paths = [p for p in cog_paths if p not in (install_path, core_path)]
msg = _("Install Path: {}\n\n").format(install_path)
msg = _("Install Path: {install_path}\nCore Path: {core_path}\n\n").format(
install_path=install_path, core_path=core_path
)
partial = []
for i, p in enumerate(cog_paths, start=1):
@ -428,16 +433,16 @@ class CogManagerUI:
"""
loaded = set(ctx.bot.extensions.keys())
all = set(await ctx.bot.cog_mgr.available_modules())
all_cogs = set(await ctx.bot.cog_mgr.available_modules())
unloaded = all - loaded
unloaded = all_cogs - loaded
loaded = sorted(list(loaded), key=str.lower)
unloaded = sorted(list(unloaded), key=str.lower)
if await ctx.embed_requested():
loaded = ("**{} loaded:**\n").format(len(loaded)) + ", ".join(loaded)
unloaded = ("**{} unloaded:**\n").format(len(unloaded)) + ", ".join(unloaded)
loaded = _("**{} loaded:**\n").format(len(loaded)) + ", ".join(loaded)
unloaded = _("**{} unloaded:**\n").format(len(unloaded)) + ", ".join(unloaded)
for page in pagify(loaded, delims=[", ", "\n"], page_length=1800):
e = discord.Embed(description=page, colour=discord.Colour.dark_green())
@ -447,9 +452,9 @@ class CogManagerUI:
e = discord.Embed(description=page, colour=discord.Colour.dark_red())
await ctx.send(embed=e)
else:
loaded_count = "**{} loaded:**\n".format(len(loaded))
loaded_count = _("**{} loaded:**\n").format(len(loaded))
loaded = ", ".join(loaded)
unloaded_count = "**{} unloaded:**\n".format(len(unloaded))
unloaded_count = _("**{} unloaded:**\n").format(len(unloaded))
unloaded = ", ".join(unloaded)
loaded_count_sent = False
unloaded_count_sent = False