misc(repository): black reformat
Some checks failed
Actions / Lint Code (Pylint) (push) Failing after 18s
Actions / Build Documentation (MkDocs) (push) Successful in 13s

This commit is contained in:
SeaswimmerTheFsh 2024-02-02 11:22:08 -05:00
parent 519e3056ab
commit fa3b353704
Signed by: cswimr
GPG key ID: B8953EC01E5C4063
5 changed files with 186 additions and 86 deletions

View file

@ -6,16 +6,17 @@
# |_____/ \___|\__,_|___/ \_/\_/ |_|_| |_| |_|_| |_| |_|\___|_|
import contextlib
import logging
import json
import logging
import re
from redbot.core import commands
from redbot.core.bot import Red
from redbot.cogs.downloader import errors
from redbot.cogs.downloader.converters import InstalledCog
from redbot.core import commands
from redbot.core.bot import Red
from redbot.core.utils.chat_formatting import error, text_to_file
class Backup(commands.Cog):
"""A utility to make reinstalling repositories and cogs after migrating the bot far easier."""
@ -32,16 +33,22 @@ class Backup(commands.Cog):
async def backup(self, ctx: commands.Context):
"""Backup your installed cogs."""
@backup.command(name='export')
@backup.command(name="export")
@commands.is_owner()
async def backup_export(self, ctx: commands.Context):
"""Export your installed repositories and cogs to a file."""
downloader = ctx.bot.get_cog("Downloader")
if downloader is None:
await ctx.send(error(f"You do not have the `Downloader` cog loaded. Please run `{ctx.prefix}load downloader` and try again."))
await ctx.send(
error(
f"You do not have the `Downloader` cog loaded. Please run `{ctx.prefix}load downloader` and try again."
)
)
return
all_repos = list(downloader._repo_manager.repos) # pylint: disable=protected-access
all_repos = list(
downloader._repo_manager.repos
) # pylint: disable=protected-access
export_data = []
@ -50,7 +57,7 @@ class Backup(commands.Cog):
"name": repo.name,
"url": repo.url,
"branch": repo.branch,
"cogs": []
"cogs": [],
}
cogs = await downloader.installed_cogs()
@ -59,19 +66,21 @@ class Backup(commands.Cog):
if cog.repo_name == repo.name:
cog_dict = {
"name": cog.name,
# "loaded": cog.name in ctx.bot.extensions.keys(),
# this functionality was planned but never implemented due to Red limitations
# and the possibility of restoration functionality being added to Core
# "loaded": cog.name in ctx.bot.extensions.keys(),
# this functionality was planned but never implemented due to Red limitations
# and the possibility of restoration functionality being added to Core
"pinned": cog.pinned,
"commit": cog.commit
"commit": cog.commit,
}
repo_dict["cogs"].append(cog_dict)
export_data.append(repo_dict)
await ctx.send(file=text_to_file(json.dumps(export_data, indent=4), 'backup.json'))
await ctx.send(
file=text_to_file(json.dumps(export_data, indent=4), "backup.json")
)
@backup.command(name='import')
@backup.command(name="import")
@commands.is_owner()
async def backup_import(self, ctx: commands.Context):
"""Import your installed repositories and cogs from an export file."""
@ -83,7 +92,11 @@ class Backup(commands.Cog):
downloader = ctx.bot.get_cog("Downloader")
if downloader is None:
await ctx.send(error(f"You do not have the `Downloader` cog loaded. Please run `{ctx.prefix}load downloader` and try again."))
await ctx.send(
error(
f"You do not have the `Downloader` cog loaded. Please run `{ctx.prefix}load downloader` and try again."
)
)
return
repo_s = []
@ -96,29 +109,41 @@ class Backup(commands.Cog):
async with ctx.typing():
for repo in export:
# Most of this code is from the Downloader cog.
name = repo['name']
branch = repo['branch']
url = repo['url']
cogs = repo['cogs']
name = repo["name"]
branch = repo["branch"]
url = repo["url"]
cogs = repo["cogs"]
if 'PyLav/Red-Cogs' in url:
if "PyLav/Red-Cogs" in url:
repo_e.append("PyLav cogs are not supported.")
continue
if name.startswith('.') or name.endswith('.'):
repo_e.append(f"Invalid repository name: {name}\nRepository names cannot start or end with a dot.")
if name.startswith(".") or name.endswith("."):
repo_e.append(
f"Invalid repository name: {name}\nRepository names cannot start or end with a dot."
)
continue
if re.match(r"^[a-zA-Z0-9_\-\.]+$", name) is None:
repo_e.append(f"Invalid repository name: {name}\nRepository names may only contain letters, numbers, underscores, hyphens, and dots.")
repo_e.append(
f"Invalid repository name: {name}\nRepository names may only contain letters, numbers, underscores, hyphens, and dots."
)
continue
try:
repository = await downloader._repo_manager.add_repo(url, name, branch) # pylint: disable=protected-access
repo_s.append(f"Added repository {name} from {url} on branch {branch}.")
self.logger.debug("Added repository %s from %s on branch %s", name, url, branch)
repository = await downloader._repo_manager.add_repo(
url, name, branch
) # pylint: disable=protected-access
repo_s.append(
f"Added repository {name} from {url} on branch {branch}."
)
self.logger.debug(
"Added repository %s from %s on branch %s", name, url, branch
)
except errors.ExistingGitRepo:
repo_e.append(f"Repository {name} already exists.")
repository = downloader._repo_manager.get_repo(name) # pylint: disable=protected-access
repository = downloader._repo_manager.get_repo(
name
) # pylint: disable=protected-access
self.logger.debug("Repository %s already exists", name)
# This is commented out because errors.AuthenticationError is not yet implemented in Red 3.5.5's Downloader cog.
@ -134,7 +159,9 @@ class Backup(commands.Cog):
# continue
except errors.CloningError as err:
repo_e.append(f"Cloning error while adding repository {name}. See logs for more information.")
repo_e.append(
f"Cloning error while adding repository {name}. See logs for more information."
)
self.logger.exception(
"Something went wrong whilst cloning %s (to revision %s)",
url,
@ -144,21 +171,23 @@ class Backup(commands.Cog):
continue
except OSError:
repo_e.append(f"OS error while adding repository {name}. See logs for more information.")
repo_e.append(
f"OS error while adding repository {name}. See logs for more information."
)
self.logger.exception(
"Something went wrong trying to add repo %s under name %s",
url,
name
name,
)
continue
cog_modules = []
for cog in cogs:
# If you're forking this cog, make sure to change these strings!
if cog['name'] == "backup" and 'SeaswimmerTheFsh/SeaCogs' in url:
if cog["name"] == "backup" and "SeaswimmerTheFsh/SeaCogs" in url:
continue
try:
cog_module = await InstalledCog.convert(ctx, cog['name'])
cog_module = await InstalledCog.convert(ctx, cog["name"])
except commands.BadArgument:
uninstall_e.append(f"Failed to uninstall {cog['name']}")
continue
@ -170,42 +199,67 @@ class Backup(commands.Cog):
with contextlib.suppress(commands.ExtensionNotLoaded):
await ctx.bot.unload_extension(cog)
await ctx.bot.remove_loaded_package(cog)
await downloader._delete_cog(poss_installed_path) # pylint: disable=protected-access
await downloader._delete_cog(
poss_installed_path
) # pylint: disable=protected-access
uninstall_s.append(f"Uninstalled {cog}")
self.logger.debug("Uninstalled %s", cog)
else:
uninstall_e.append(f"Failed to uninstall {cog}")
self.logger.warning("Failed to uninstall %s", cog)
await downloader._remove_from_installed(cog_modules) # pylint: disable=protected-access
await downloader._remove_from_installed(
cog_modules
) # pylint: disable=protected-access
for cog in cogs:
cog_name = cog['name']
cog_pinned = cog['pinned']
cog_name = cog["name"]
cog_pinned = cog["pinned"]
if cog_pinned:
commit = cog['commit']
commit = cog["commit"]
else:
commit = None
# If you're forking this cog, make sure to change these strings!
if cog_name == 'backup' and 'SeaswimmerTheFsh/SeaCogs' in url:
if cog_name == "backup" and "SeaswimmerTheFsh/SeaCogs" in url:
continue
async with repository.checkout(commit, exit_to_rev=repository.branch):
cogs_c, message = await downloader._filter_incorrect_cogs_by_names(repository, [cog_name]) # pylint: disable=protected-access
async with repository.checkout(
commit, exit_to_rev=repository.branch
):
cogs_c, message = (
await downloader._filter_incorrect_cogs_by_names(
repository, [cog_name]
)
) # pylint: disable=protected-access
if not cogs_c:
install_e.append(message)
self.logger.error(message)
continue
failed_reqs = await downloader._install_requirements(cogs_c) # pylint: disable=protected-access
failed_reqs = await downloader._install_requirements(
cogs_c
) # pylint: disable=protected-access
if failed_reqs:
install_e.append(f"Failed to install {cog_name} due to missing requirements: {failed_reqs}")
self.logger.error("Failed to install %s due to missing requirements: %s", cog_name, failed_reqs)
install_e.append(
f"Failed to install {cog_name} due to missing requirements: {failed_reqs}"
)
self.logger.error(
"Failed to install %s due to missing requirements: %s",
cog_name,
failed_reqs,
)
continue
installed_cogs, failed_cogs = await downloader._install_cogs(cogs_c) # pylint: disable=protected-access
installed_cogs, failed_cogs = await downloader._install_cogs(
cogs_c
) # pylint: disable=protected-access
if repository.available_libraries:
installed_libs, failed_libs = await repository.install_libraries(target_dir=downloader.SHAREDLIB_PATH, req_target_dir=downloader.LIB_PATH)
installed_libs, failed_libs = (
await repository.install_libraries(
target_dir=downloader.SHAREDLIB_PATH,
req_target_dir=downloader.LIB_PATH,
)
)
else:
installed_libs = None
failed_libs = None
@ -214,21 +268,41 @@ class Backup(commands.Cog):
for cog in installed_cogs:
cog.pinned = True
await downloader._save_to_installed(installed_cogs + installed_libs if installed_libs else installed_cogs) # pylint: disable=protected-access
await downloader._save_to_installed(
installed_cogs + installed_libs
if installed_libs
else installed_cogs
) # pylint: disable=protected-access
if installed_cogs:
installed_cog_name = installed_cogs[0].name
install_s.append(f"Installed {installed_cog_name}")
self.logger.debug("Installed %s", installed_cog_name)
if installed_libs:
for lib in installed_libs:
install_s.append(f"Installed {lib.name} required for {cog_name}")
self.logger.debug("Installed %s required for %s", lib.name, cog_name)
install_s.append(
f"Installed {lib.name} required for {cog_name}"
)
self.logger.debug(
"Installed %s required for %s", lib.name, cog_name
)
if failed_cogs:
failed_cog_name = failed_cogs[0].name
install_e.append(f"Failed to install {failed_cog_name}")
self.logger.error("Failed to install %s", failed_cog_name)
if failed_libs:
for lib in failed_libs:
install_e.append(f"Failed to install {lib.name} required for {cog_name}")
self.logger.error("Failed to install %s required for %s", lib.name, cog_name)
await ctx.send("Import complete!", file=text_to_file(f"Repositories:\n{repo_s}\n\nRepository Errors:\n{repo_e}\n\nUninstalled Cogs:\n{uninstall_s}\n\nUninstalled Cogs Errors:\n{uninstall_e}\n\nInstalled Cogs:\n{install_s}\n\nInstalled Cogs Errors:\n{install_e}", 'backup.log'))
install_e.append(
f"Failed to install {lib.name} required for {cog_name}"
)
self.logger.error(
"Failed to install %s required for %s",
lib.name,
cog_name,
)
await ctx.send(
"Import complete!",
file=text_to_file(
f"Repositories:\n{repo_s}\n\nRepository Errors:\n{repo_e}\n\nUninstalled Cogs:\n{uninstall_s}\n\nUninstalled Cogs Errors:\n{uninstall_e}\n\nInstalled Cogs:\n{install_s}\n\nInstalled Cogs Errors:\n{install_e}",
"backup.log",
),
)