diff --git a/redbot/cogs/downloader/downloader.py b/redbot/cogs/downloader/downloader.py index 39235674e..dfe93686d 100644 --- a/redbot/cogs/downloader/downloader.py +++ b/redbot/cogs/downloader/downloader.py @@ -499,13 +499,17 @@ class Downloader(commands.Cog): success = await repo.install_raw_requirements(deps, self.LIB_PATH) if success: - await ctx.send(_("Libraries installed.")) + await ctx.send(_("Libraries installed.") if len(deps) > 1 else _("Library installed.")) else: await ctx.send( _( "Some libraries failed to install. Please check" " your logs for a complete list." ) + if len(deps) > 1 + else _( + "The library failed to install. Please check your logs for a complete list." + ) ) @commands.group() @@ -602,9 +606,15 @@ class Downloader(commands.Cog): """List all installed repos.""" repos = self._repo_manager.repos sorted_repos = sorted(repos, key=lambda r: str.lower(r.name)) - joined = _("Installed Repos:\n\n") - for repo in sorted_repos: - joined += "+ {}: {}\n".format(repo.name, repo.short or "") + if len(repos) == 0: + joined = _("There are no repos installed.") + else: + if len(repos) > 1: + joined = _("Installed Repos:\n\n") + else: + joined = _("Installed Repo:\n\n") + for repo in sorted_repos: + joined += "+ {}: {}\n".format(repo.name, repo.short or "") for page in pagify(joined, ["\n"], shorten_by=16): await ctx.send(box(page.lstrip(" "), lang="diff")) @@ -709,14 +719,18 @@ class Downloader(commands.Cog): all_failed_libs += failed_libs message = "" if failed_reqs: - message += _("Failed to install requirements: ") + humanize_list( - tuple(map(inline, failed_reqs)) - ) + message += ( + _("Failed to install requirements: ") + if len(failed_reqs) > 1 + else _("Failed to install the requirement: ") + ) + humanize_list(tuple(map(inline, failed_reqs))) if all_failed_libs: libnames = [lib.name for lib in failed_libs] - message += _("\nFailed to install shared libraries: ") + humanize_list( - tuple(map(inline, libnames)) - ) + message += ( + _("\nFailed to install shared libraries: ") + if len(all_failed_libs) > 1 + else _("\nFailed to install shared library: ") + ) + humanize_list(tuple(map(inline, libnames))) if message: await self.send_pagified( ctx, @@ -808,9 +822,11 @@ class Downloader(commands.Cog): return failed_reqs = await self._install_requirements(cogs) if failed_reqs: - message += _("\nFailed to install requirements: ") + humanize_list( - tuple(map(inline, failed_reqs)) - ) + message += ( + _("\nFailed to install requirements: ") + if len(failed_reqs) > 1 + else _("\nFailed to install requirement: ") + ) + humanize_list(tuple(map(inline, failed_reqs))) await self.send_pagified(ctx, message) return @@ -829,19 +845,33 @@ class Downloader(commands.Cog): if failed_libs: libnames = [inline(lib.name) for lib in failed_libs] message = ( - _("\nFailed to install shared libraries for `{repo.name}` repo: ").format( - repo=repo - ) + ( + _("\nFailed to install shared libraries for `{repo.name}` repo: ") + if len(libnames) > 1 + else _("\nFailed to install shared library for `{repo.name}` repo: ") + ).format(repo=repo) + humanize_list(libnames) + message ) if failed_cogs: cognames = [inline(cog.name) for cog in failed_cogs] - message = _("\nFailed to install cogs: ") + humanize_list(cognames) + message + message = ( + ( + _("\nFailed to install cogs: ") + if len(failed_cogs) > 1 + else _("\nFailed to install the cog: ") + ) + + humanize_list(cognames) + + message + ) if installed_cogs: cognames = [inline(cog.name) for cog in installed_cogs] message = ( - _("Successfully installed cogs: ") + ( + _("Successfully installed cogs: ") + if len(installed_cogs) > 1 + else _("Successfully installed the cog:") + ) + humanize_list(cognames) + ( _( @@ -900,20 +930,44 @@ class Downloader(commands.Cog): message = "" if uninstalled_cogs: - message += _("Successfully uninstalled cogs: ") + humanize_list(uninstalled_cogs) - if failed_cogs: message += ( - _( - "\nDownloader has removed these cogs from the installed cogs list" - " but it wasn't able to find their files: " + _("Successfully uninstalled cogs: ") + if len(uninstalled_cogs) > 1 + else _("Successfully uninstalled the cog: ") + ) + humanize_list(uninstalled_cogs) + if failed_cogs: + if len(failed_cogs) > 1: + message += ( + _( + "\nDownloader has removed these cogs from the installed cogs list" + " but it wasn't able to find their files: " + ) + + humanize_list(tuple(map(inline, failed_cogs))) + + _( + "\nThey were most likely removed without using {command_1}.\n" + "You may need to remove those files manually if the cogs are still usable." + " If so, ensure the cogs have been unloaded with {command_2}." + ).format( + command_1=inline(f"{ctx.clean_prefix}cog uninstall"), + command_2=inline(f"{ctx.clean_prefix}unload {' '.join(failed_cogs)}"), + ) + ) + else: + message += ( + _( + "\nDownloader has removed this cog from the installed cogs list" + " but it wasn't able to find its files: " + ) + + inline(failed_cogs[0]) + + _( + "\nIt was most likely removed without using {command_1}.\n" + "You may need to remove those files manually if the cog is still usable." + " If so, ensure the cog has been unloaded with {command_2}." + ).format( + command_1=inline(f"{ctx.clean_prefix}cog uninstall"), + command_2=inline(f"{ctx.clean_prefix}unload {failed_cogs[0]}"), + ) ) - + humanize_list(tuple(map(inline, failed_cogs))) - + _( - "\nThey were most likely removed without using `{prefix}cog uninstall`.\n" - "You may need to remove those files manually if the cogs are still usable." - " If so, ensure the cogs have been unloaded with `{prefix}unload {cogs}`." - ).format(prefix=ctx.clean_prefix, cogs=" ".join(failed_cogs)) - ) await self.send_pagified(ctx, message) @cog.command(name="pin", require_var_positional=True) @@ -940,9 +994,15 @@ class Downloader(commands.Cog): if pinned: await self._save_to_installed(pinned) cognames = [inline(cog.name) for cog in pinned] - message += _("Pinned cogs: ") + humanize_list(cognames) + message += ( + _("Pinned cogs: ") if len(pinned) > 1 else _("Pinned cog: ") + ) + humanize_list(cognames) if already_pinned: - message += _("\nThese cogs were already pinned: ") + humanize_list(already_pinned) + message += ( + _("\nThese cogs were already pinned: ") + if len(already_pinned) > 1 + else _("\nThis cog was already pinned: ") + ) + humanize_list(already_pinned) await self.send_pagified(ctx, message) @cog.command(name="unpin", require_var_positional=True) @@ -968,9 +1028,15 @@ class Downloader(commands.Cog): if unpinned: await self._save_to_installed(unpinned) cognames = [inline(cog.name) for cog in unpinned] - message += _("Unpinned cogs: ") + humanize_list(cognames) + message += ( + _("Unpinned cogs: ") if len(unpinned) > 1 else _("Unpinned cog: ") + ) + humanize_list(cognames) if not_pinned: - message += _("\nThese cogs weren't pinned: ") + humanize_list(not_pinned) + message += ( + _("\nThese cogs weren't pinned: ") + if len(not_pinned) > 1 + else _("\nThis cog was already not pinned: ") + ) + humanize_list(not_pinned) await self.send_pagified(ctx, message) @cog.command(name="listpinned") @@ -1015,14 +1081,18 @@ class Downloader(commands.Cog): message = "" if cogs_to_update: cognames = [cog.name for cog in cogs_to_update] - message += _("These cogs can be updated: ") + humanize_list( - tuple(map(inline, cognames)) - ) + message += ( + _("These cogs can be updated: ") + if len(cognames) > 1 + else _("This cog can be updated: ") + ) + humanize_list(tuple(map(inline, cognames))) if libs_to_update: libnames = [cog.name for cog in libs_to_update] - message += _("\nThese shared libraries can be updated: ") + humanize_list( - tuple(map(inline, libnames)) - ) + message += ( + _("\nThese shared libraries can be updated: ") + if len(libnames) > 1 + else _("\nThis shared library can be updated: ") + ) + humanize_list(tuple(map(inline, libnames))) if not (cogs_to_update or libs_to_update) and filter_message: message += _("No cogs can be updated.") message += filter_message @@ -1148,8 +1218,10 @@ class Downloader(commands.Cog): message += _("There were no cogs to check.") if pinned_cogs: cognames = [cog.name for cog in pinned_cogs] - message += _( - "\nThese cogs are pinned and therefore weren't checked: " + message += ( + _("\nThese cogs are pinned and therefore weren't checked: ") + if len(cognames) > 1 + else _("\nThis cog is pinned and therefore wasn't checked: ") ) + humanize_list(tuple(map(inline, cognames))) else: cogs_to_update, libs_to_update = await self._available_updates(cogs_to_check) @@ -1182,8 +1254,10 @@ class Downloader(commands.Cog): await repo.checkout(repo.branch) if pinned_cogs: cognames = [cog.name for cog in pinned_cogs] - message += _( - "\nThese cogs are pinned and therefore weren't checked: " + message += ( + _("\nThese cogs are pinned and therefore weren't checked: ") + if len(cognames) > 1 + else _("\nThis cog is pinned and therefore wasn't checked: ") ) + humanize_list(tuple(map(inline, cognames))) message += filter_message @@ -1214,23 +1288,32 @@ class Downloader(commands.Cog): - `` The repo to list cogs from. """ - installed = await self.installed_cogs() - installed_str = "" - if installed: - installed_str = _("Installed Cogs:\n") + "\n".join( - [ - "- {}{}".format(i.name, ": {}".format(i.short) if i.short else "") - for i in installed - if i.repo_name == repo.name - ] - ) - cogs = _("Available Cogs:\n") + "\n".join( - [ - "+ {}: {}".format(cog.name, cog.short or "") - for cog in repo.available_cogs - if not (cog.hidden or cog in installed) - ] + all_installed_cogs = await self.installed_cogs() + installed_cogs_in_repo = [cog for cog in all_installed_cogs if cog.repo_name == repo.name] + installed_str = "\n".join( + "- {}{}".format(i.name, ": {}".format(i.short) if i.short else "") + for i in installed_cogs_in_repo ) + + if len(installed_cogs_in_repo) > 1: + installed_str = _("Installed Cogs:\n{text}").format(text=installed_str) + elif installed_cogs_in_repo: + installed_str = _("Installed Cog:\n{text}").format(text=installed_str) + + available_cogs = [ + cog for cog in repo.available_cogs if not (cog.hidden or cog in installed_cogs_in_repo) + ] + available_str = "\n".join( + "+ {}{}".format(cog.name, ": {}".format(cog.short) if cog.short else "") + for cog in available_cogs + ) + + if not available_str: + cogs = _("Available Cogs:\nNo cogs are available.") + elif len(available_cogs) > 1: + cogs = _("Available Cogs:\n{text}").format(text=available_str) + else: + cogs = _("Available Cog:\n{text}").format(text=available_str) cogs = cogs + "\n\n" + installed_str for page in pagify(cogs, ["\n"], shorten_by=16): await ctx.send(box(page.lstrip(" "), lang="diff")) @@ -1336,16 +1419,22 @@ class Downloader(commands.Cog): message = "" if unavailable_cogs: - message += _("\nCouldn't find these cogs in {repo.name}: ").format( - repo=repo + message = ( + _("\nCouldn't find these cogs in {repo.name}: ") + if len(unavailable_cogs) > 1 + else _("\nCouldn't find this cog in {repo.name}: ") ) + humanize_list(unavailable_cogs) if already_installed: - message += _("\nThese cogs were already installed: ") + humanize_list( - already_installed - ) + message += ( + _("\nThese cogs were already installed: ") + if len(already_installed) > 1 + else _("\nThis cog was already installed: ") + ) + humanize_list(already_installed) if name_already_used: - message += _( - "\nSome cogs with these names are already installed from different repos: " + message += ( + _("\nSome cogs with these names are already installed from different repos: ") + if len(name_already_used) > 1 + else _("Cog with this is already installed from a different repo.") ) + humanize_list(name_already_used) correct_cogs, add_to_message = self._filter_incorrect_cogs(cogs) if add_to_message: @@ -1387,13 +1476,22 @@ class Downloader(commands.Cog): correct_cogs.append(cog) message = "" if outdated_python_version: - message += _( - "\nThese cogs require higher python version than you have: " + message += ( + _("\nThese cogs require higher python version than you have: ") + if len(outdated_python_version) + else _("This cog requires higher python version than you have: ") ) + humanize_list(outdated_python_version) if outdated_bot_version: - message += _( - "\nThese cogs require different Red version" - " than you currently have ({current_version}): " + message += ( + _( + "\nThese cogs require different Red version" + " than you currently have ({current_version}): " + ) + if len(outdated_bot_version) > 1 + else _( + "This cog requires different Red version than you currently " + "have ({current_version}): " + ) ).format(current_version=red_version_info) + humanize_list(outdated_bot_version) return tuple(correct_cogs), message @@ -1451,7 +1549,11 @@ class Downloader(commands.Cog): if failed_reqs: return ( set(), - _("Failed to install requirements: ") + ( + _("Failed to install requirements: ") + if len(failed_reqs) > 1 + else _("Failed to install the requirement: ") + ) + humanize_list(tuple(map(inline, failed_reqs))), ) installed_cogs, failed_cogs = await self._install_cogs(cogs_to_update) @@ -1470,28 +1572,50 @@ class Downloader(commands.Cog): cogs_with_changed_eud_statement.add(cog.name) message += _("\nUpdated: ") + humanize_list(tuple(map(inline, updated_cognames))) if cogs_with_changed_eud_statement: - message += ( - _("\nEnd user data statements of these cogs have changed: ") - + humanize_list(tuple(map(inline, cogs_with_changed_eud_statement))) - + _("\nYou can use {command} to see the updated statements.\n").format( - command=inline(f"{ctx.clean_prefix}cog info ") + if len(cogs_with_changed_eud_statement) > 1: + message += ( + _("\nEnd user data statements of these cogs have changed: ") + + humanize_list(tuple(map(inline, cogs_with_changed_eud_statement))) + + _("\nYou can use {command} to see the updated statements.\n").format( + command=inline(f"{ctx.clean_prefix}cog info ") + ) + ) + else: + message += ( + _("End user data statement of this cog has changed:") + + inline(next(iter(cogs_with_changed_eud_statement))) + + _("\nYou can use {command} to see the updated statement.\n").format( + command=inline(f"{ctx.clean_prefix}cog info ") + ) ) - ) if failed_cogs: cognames = [cog.name for cog in failed_cogs] - message += _("\nFailed to update cogs: ") + humanize_list(tuple(map(inline, cognames))) + message += ( + _("\nFailed to update cogs: ") + if len(failed_cogs) > 1 + else _("\nFailed to update cog: ") + ) + humanize_list(tuple(map(inline, cognames))) if not cogs_to_update: message = _("No cogs were updated.") if installed_libs: - message += _( - "\nSome shared libraries were updated, you should restart the bot " - "to bring the changes into effect." + message += ( + _( + "\nSome shared libraries were updated, you should restart the bot " + "to bring the changes into effect." + ) + if len(installed_libs) > 1 + else _( + "\nA shared library was updated, you should restart the " + "bot to bring the changes into effect." + ) ) if failed_libs: libnames = [lib.name for lib in failed_libs] - message += _("\nFailed to install shared libraries: ") + humanize_list( - tuple(map(inline, libnames)) - ) + message += ( + _("\nFailed to install shared libraries: ") + if len(failed_cogs) > 1 + else _("\nFailed to install shared library: ") + ) + humanize_list(tuple(map(inline, libnames))) return (updated_cognames, message) async def _ask_for_cog_reload(self, ctx: commands.Context, updated_cognames: Set[str]) -> None: @@ -1501,7 +1625,11 @@ class Downloader(commands.Cog): return if not ctx.assume_yes: - message = _("Would you like to reload the updated cogs?") + message = ( + _("Would you like to reload the updated cogs?") + if len(updated_cognames) > 1 + else _("Would you like to reload the updated cog?") + ) can_react = ctx.channel.permissions_for(ctx.me).add_reactions if not can_react: message += " (y/n)"