mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-07 11:48:55 -05:00
Make --debuginfo more like [p]debuginfo (#5662)
This commit is contained in:
parent
bc9f34c04b
commit
c9f1a45854
@ -18,7 +18,7 @@ import sys
|
|||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import NoReturn
|
from typing import Any, Awaitable, Callable, NoReturn, Union
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
import rich
|
import rich
|
||||||
@ -29,6 +29,7 @@ from redbot.core.bot import Red, ExitCodes, _NoOwnerSet
|
|||||||
from redbot.core.cli import interactive_config, confirm, parse_cli_flags
|
from redbot.core.cli import interactive_config, confirm, parse_cli_flags
|
||||||
from redbot.setup import get_data_dir, get_name, save_config
|
from redbot.setup import get_data_dir, get_name, save_config
|
||||||
from redbot.core import data_manager, drivers
|
from redbot.core import data_manager, drivers
|
||||||
|
from redbot.core._debuginfo import DebugInfo
|
||||||
from redbot.core._sharedlibdeprecation import SharedLibImportWarner
|
from redbot.core._sharedlibdeprecation import SharedLibImportWarner
|
||||||
|
|
||||||
|
|
||||||
@ -62,42 +63,9 @@ def list_instances():
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def debug_info():
|
async def debug_info(*args: Any) -> None:
|
||||||
"""Shows debug information useful for debugging."""
|
"""Shows debug information useful for debugging."""
|
||||||
if sys.platform == "linux":
|
print(await DebugInfo().get_text())
|
||||||
import distro # pylint: disable=import-error
|
|
||||||
|
|
||||||
IS_WINDOWS = os.name == "nt"
|
|
||||||
IS_MAC = sys.platform == "darwin"
|
|
||||||
IS_LINUX = sys.platform == "linux"
|
|
||||||
|
|
||||||
pyver = sys.version
|
|
||||||
pipver = pip.__version__
|
|
||||||
redver = __version__
|
|
||||||
dpy_version = discord.__version__
|
|
||||||
if IS_WINDOWS:
|
|
||||||
os_info = platform.uname()
|
|
||||||
osver = "{} {} (version {})".format(os_info.system, os_info.release, os_info.version)
|
|
||||||
elif IS_MAC:
|
|
||||||
os_info = platform.mac_ver()
|
|
||||||
osver = "Mac OSX {} {}".format(os_info[0], os_info[2])
|
|
||||||
else:
|
|
||||||
osver = f"{distro.name()} {distro.version()}".strip()
|
|
||||||
user_who_ran = getpass.getuser()
|
|
||||||
info = (
|
|
||||||
"Debug Info for Red\n\n"
|
|
||||||
+ "Red version: {}\n".format(redver)
|
|
||||||
+ "Python version: {}\n".format(pyver)
|
|
||||||
+ "Python executable: {}\n".format(sys.executable)
|
|
||||||
+ "Discord.py version: {}\n".format(dpy_version)
|
|
||||||
+ "Pip version: {}\n".format(pipver)
|
|
||||||
+ "OS version: {}\n".format(osver)
|
|
||||||
+ "System arch: {}\n".format(platform.machine())
|
|
||||||
+ "User: {}\n".format(user_who_ran)
|
|
||||||
+ "Metadata file: {}\n".format(data_manager.config_file)
|
|
||||||
)
|
|
||||||
print(info)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
async def edit_instance(red, cli_flags):
|
async def edit_instance(red, cli_flags):
|
||||||
@ -291,18 +259,25 @@ def _copy_data(data):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def handle_edit(cli_flags: Namespace):
|
def early_exit_runner(
|
||||||
|
cli_flags: Namespace,
|
||||||
|
func: Union[Callable[[], Awaitable[Any]], Callable[[Red, Namespace], Awaitable[Any]]],
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
This one exists to not log all the things like it's a full run of the bot.
|
This one exists to not log all the things like it's a full run of the bot.
|
||||||
"""
|
"""
|
||||||
loop = asyncio.new_event_loop()
|
loop = asyncio.new_event_loop()
|
||||||
asyncio.set_event_loop(loop)
|
asyncio.set_event_loop(loop)
|
||||||
|
try:
|
||||||
|
if not cli_flags.instance_name:
|
||||||
|
loop.run_until_complete(func())
|
||||||
|
return
|
||||||
|
|
||||||
data_manager.load_basic_configuration(cli_flags.instance_name)
|
data_manager.load_basic_configuration(cli_flags.instance_name)
|
||||||
red = Red(cli_flags=cli_flags, description="Red V3", dm_help=None)
|
red = Red(cli_flags=cli_flags, description="Red V3", dm_help=None)
|
||||||
try:
|
|
||||||
driver_cls = drivers.get_driver_class()
|
driver_cls = drivers.get_driver_class()
|
||||||
loop.run_until_complete(driver_cls.initialize(**data_manager.storage_details()))
|
loop.run_until_complete(driver_cls.initialize(**data_manager.storage_details()))
|
||||||
loop.run_until_complete(edit_instance(red, cli_flags))
|
loop.run_until_complete(func(red, cli_flags))
|
||||||
loop.run_until_complete(driver_cls.teardown())
|
loop.run_until_complete(driver_cls.teardown())
|
||||||
except (KeyboardInterrupt, EOFError):
|
except (KeyboardInterrupt, EOFError):
|
||||||
print("Aborted!")
|
print("Aborted!")
|
||||||
@ -430,7 +405,7 @@ def handle_early_exit_flags(cli_flags: Namespace):
|
|||||||
print("Current Version: {}".format(__version__))
|
print("Current Version: {}".format(__version__))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
elif cli_flags.debuginfo:
|
elif cli_flags.debuginfo:
|
||||||
debug_info()
|
early_exit_runner(cli_flags, debug_info)
|
||||||
elif not cli_flags.instance_name and (not cli_flags.no_instance or cli_flags.edit):
|
elif not cli_flags.instance_name and (not cli_flags.no_instance or cli_flags.edit):
|
||||||
print("Error: No instance name was provided!")
|
print("Error: No instance name was provided!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -502,7 +477,7 @@ def main():
|
|||||||
cli_flags = parse_cli_flags(sys.argv[1:])
|
cli_flags = parse_cli_flags(sys.argv[1:])
|
||||||
handle_early_exit_flags(cli_flags)
|
handle_early_exit_flags(cli_flags)
|
||||||
if cli_flags.edit:
|
if cli_flags.edit:
|
||||||
handle_edit(cli_flags)
|
early_exit_runner(cli_flags, edit_instance)
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
loop = asyncio.new_event_loop()
|
loop = asyncio.new_event_loop()
|
||||||
|
|||||||
170
redbot/core/_debuginfo.py
Normal file
170
redbot/core/_debuginfo.py
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import getpass
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
import sys
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import discord
|
||||||
|
import pip
|
||||||
|
import psutil
|
||||||
|
|
||||||
|
from redbot import __version__
|
||||||
|
from redbot.core import data_manager
|
||||||
|
from redbot.core.bot import Red
|
||||||
|
from redbot.core.utils.chat_formatting import box
|
||||||
|
|
||||||
|
|
||||||
|
def noop_box(text: str, **kwargs) -> str:
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def _datasize(num: int):
|
||||||
|
for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]:
|
||||||
|
if abs(num) < 1024.0:
|
||||||
|
return "{0:.1f}{1}".format(num, unit)
|
||||||
|
num /= 1024.0
|
||||||
|
return "{0:.1f}{1}".format(num, "YB")
|
||||||
|
|
||||||
|
|
||||||
|
class DebugInfoSection:
|
||||||
|
def __init__(self, section_name: str, *section_parts: str) -> None:
|
||||||
|
self.section_name = section_name
|
||||||
|
self.section_parts = section_parts
|
||||||
|
|
||||||
|
def get_command_text(self) -> str:
|
||||||
|
parts = [box(f"## {self.section_name}:", lang="md")]
|
||||||
|
for part in self.section_parts:
|
||||||
|
parts.append(box(part))
|
||||||
|
return "".join(parts)
|
||||||
|
|
||||||
|
def get_cli_text(self) -> str:
|
||||||
|
parts = [f"\x1b[32m## {self.section_name}:\x1b[0m"]
|
||||||
|
for part in self.section_parts:
|
||||||
|
parts.append(part)
|
||||||
|
return "\n".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
class DebugInfo:
|
||||||
|
def __init__(self, bot: Optional[Red] = None) -> None:
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
async def get_text(self) -> str:
|
||||||
|
if self.bot is None:
|
||||||
|
return await self.get_cli_text()
|
||||||
|
else:
|
||||||
|
return await self.get_command_text()
|
||||||
|
|
||||||
|
async def get_cli_text(self) -> str:
|
||||||
|
parts = ["\x1b[31m# Debug Info for Red:\x1b[0m"]
|
||||||
|
for section in (
|
||||||
|
self._get_system_metadata_section(),
|
||||||
|
self._get_os_variables_section(),
|
||||||
|
await self._get_red_vars_section(),
|
||||||
|
):
|
||||||
|
parts.append("")
|
||||||
|
parts.append(section.get_cli_text())
|
||||||
|
|
||||||
|
return "\n".join(parts)
|
||||||
|
|
||||||
|
async def get_command_text(self) -> str:
|
||||||
|
parts = [box("# Debug Info for Red:", lang="md")]
|
||||||
|
for section in (
|
||||||
|
self._get_system_metadata_section(),
|
||||||
|
self._get_os_variables_section(),
|
||||||
|
await self._get_red_vars_section(),
|
||||||
|
):
|
||||||
|
parts.append("\n")
|
||||||
|
parts.append(section.get_command_text())
|
||||||
|
|
||||||
|
return "".join(parts)
|
||||||
|
|
||||||
|
def _get_system_metadata_section(self) -> DebugInfoSection:
|
||||||
|
memory_ram = psutil.virtual_memory()
|
||||||
|
ram_string = "{used}/{total} ({percent}%)".format(
|
||||||
|
used=_datasize(memory_ram.used),
|
||||||
|
total=_datasize(memory_ram.total),
|
||||||
|
percent=memory_ram.percent,
|
||||||
|
)
|
||||||
|
return DebugInfoSection(
|
||||||
|
"System Metadata",
|
||||||
|
f"CPU Cores: {psutil.cpu_count()} ({platform.machine()})\nRAM: {ram_string}",
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_os_variables_section(self) -> DebugInfoSection:
|
||||||
|
IS_WINDOWS = os.name == "nt"
|
||||||
|
IS_MAC = sys.platform == "darwin"
|
||||||
|
IS_LINUX = sys.platform == "linux"
|
||||||
|
|
||||||
|
python_version = ".".join(map(str, sys.version_info[:3]))
|
||||||
|
pyver = f"{python_version} ({platform.architecture()[0]})"
|
||||||
|
pipver = pip.__version__
|
||||||
|
redver = __version__
|
||||||
|
dpy_version = discord.__version__
|
||||||
|
if IS_WINDOWS:
|
||||||
|
os_info = platform.uname()
|
||||||
|
osver = f"{os_info.system} {os_info.release} (version {os_info.version})"
|
||||||
|
elif IS_MAC:
|
||||||
|
os_info = platform.mac_ver()
|
||||||
|
osver = f"Mac OSX {os_info[0]} {os_info[2]}"
|
||||||
|
elif IS_LINUX:
|
||||||
|
import distro
|
||||||
|
|
||||||
|
osver = f"{distro.name()} {distro.version()}".strip()
|
||||||
|
else:
|
||||||
|
osver = "Could not parse OS, report this on Github."
|
||||||
|
user_who_ran = getpass.getuser()
|
||||||
|
|
||||||
|
resp_os = f"OS version: {osver}\nUser: {user_who_ran}\n" # Ran where off to?!
|
||||||
|
resp_py_metadata = (
|
||||||
|
f"Python executable: {sys.executable}\n"
|
||||||
|
f"Python version: {pyver}\n"
|
||||||
|
f"Pip version: {pipver}\n"
|
||||||
|
)
|
||||||
|
resp_red_metadata = f"Red version: {redver}\nDiscord.py version: {dpy_version}"
|
||||||
|
return DebugInfoSection(
|
||||||
|
"OS variables",
|
||||||
|
resp_os,
|
||||||
|
resp_py_metadata,
|
||||||
|
resp_red_metadata,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _get_red_vars_section(self) -> DebugInfoSection:
|
||||||
|
if data_manager.instance_name is None:
|
||||||
|
return DebugInfoSection(
|
||||||
|
"Red variables",
|
||||||
|
f"Metadata file: {data_manager.config_file}",
|
||||||
|
)
|
||||||
|
|
||||||
|
parts = [f"Instance name: {data_manager.instance_name}"]
|
||||||
|
if self.bot is not None:
|
||||||
|
owners = []
|
||||||
|
for uid in self.bot.owner_ids:
|
||||||
|
try:
|
||||||
|
u = await self.bot.get_or_fetch_user(uid)
|
||||||
|
owners.append(f"{u.id} ({u})")
|
||||||
|
except discord.HTTPException:
|
||||||
|
owners.append(f"{uid} (Unresolvable)")
|
||||||
|
owners_string = ", ".join(owners) or "None"
|
||||||
|
parts.append(f"Owner(s): {', '.join(owners) or 'None'}")
|
||||||
|
|
||||||
|
if self.bot is not None:
|
||||||
|
disabled_intents = (
|
||||||
|
", ".join(
|
||||||
|
intent_name.replace("_", " ").title()
|
||||||
|
for intent_name, enabled in self.bot.intents
|
||||||
|
if not enabled
|
||||||
|
)
|
||||||
|
or "None"
|
||||||
|
)
|
||||||
|
parts.append(f"Disabled intents: {disabled_intents}")
|
||||||
|
|
||||||
|
parts.append(f"Storage type: {data_manager.storage_type()}")
|
||||||
|
parts.append(f"Data path: {data_manager.basic_config['DATA_PATH']}")
|
||||||
|
parts.append(f"Metadata file: {data_manager.config_file}")
|
||||||
|
|
||||||
|
return DebugInfoSection(
|
||||||
|
"Red variables",
|
||||||
|
"\n".join(parts),
|
||||||
|
)
|
||||||
@ -4091,106 +4091,9 @@ class Core(commands.commands._RuleDropper, commands.Cog, CoreLogic):
|
|||||||
@checks.is_owner()
|
@checks.is_owner()
|
||||||
async def debuginfo(self, ctx: commands.Context):
|
async def debuginfo(self, ctx: commands.Context):
|
||||||
"""Shows debug information useful for debugging."""
|
"""Shows debug information useful for debugging."""
|
||||||
|
from redbot.core._debuginfo import DebugInfo
|
||||||
|
|
||||||
if sys.platform == "linux":
|
await ctx.send(await DebugInfo(self.bot).get_text())
|
||||||
import distro # pylint: disable=import-error
|
|
||||||
|
|
||||||
IS_WINDOWS = os.name == "nt"
|
|
||||||
IS_MAC = sys.platform == "darwin"
|
|
||||||
IS_LINUX = sys.platform == "linux"
|
|
||||||
|
|
||||||
python_version = ".".join(map(str, sys.version_info[:3]))
|
|
||||||
pyver = f"{python_version} ({platform.architecture()[0]})"
|
|
||||||
pipver = pip.__version__
|
|
||||||
redver = red_version_info
|
|
||||||
dpy_version = discord.__version__
|
|
||||||
if IS_WINDOWS:
|
|
||||||
os_info = platform.uname()
|
|
||||||
osver = f"{os_info.system} {os_info.release} (version {os_info.version})"
|
|
||||||
elif IS_MAC:
|
|
||||||
os_info = platform.mac_ver()
|
|
||||||
osver = f"Mac OSX {os_info[0]} {os_info[2]}"
|
|
||||||
elif IS_LINUX:
|
|
||||||
osver = f"{distro.name()} {distro.version()}".strip()
|
|
||||||
else:
|
|
||||||
osver = "Could not parse OS, report this on Github."
|
|
||||||
user_who_ran = getpass.getuser()
|
|
||||||
driver = storage_type()
|
|
||||||
|
|
||||||
from redbot.core.data_manager import basic_config, config_file
|
|
||||||
|
|
||||||
data_path = Path(basic_config["DATA_PATH"])
|
|
||||||
disabled_intents = (
|
|
||||||
", ".join(
|
|
||||||
intent_name.replace("_", " ").title()
|
|
||||||
for intent_name, enabled in self.bot.intents
|
|
||||||
if not enabled
|
|
||||||
)
|
|
||||||
or "None"
|
|
||||||
)
|
|
||||||
|
|
||||||
def _datasize(num: int):
|
|
||||||
for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]:
|
|
||||||
if abs(num) < 1024.0:
|
|
||||||
return "{0:.1f}{1}".format(num, unit)
|
|
||||||
num /= 1024.0
|
|
||||||
return "{0:.1f}{1}".format(num, "YB")
|
|
||||||
|
|
||||||
memory_ram = psutil.virtual_memory()
|
|
||||||
ram_string = "{used}/{total} ({percent}%)".format(
|
|
||||||
used=_datasize(memory_ram.used),
|
|
||||||
total=_datasize(memory_ram.total),
|
|
||||||
percent=memory_ram.percent,
|
|
||||||
)
|
|
||||||
|
|
||||||
owners = []
|
|
||||||
for uid in self.bot.owner_ids:
|
|
||||||
try:
|
|
||||||
u = await self.bot.get_or_fetch_user(uid)
|
|
||||||
owners.append(f"{u.id} ({u})")
|
|
||||||
except discord.HTTPException:
|
|
||||||
owners.append(f"{uid} (Unresolvable)")
|
|
||||||
owners_string = ", ".join(owners) or "None"
|
|
||||||
|
|
||||||
resp_intro = "# Debug Info for Red:"
|
|
||||||
resp_system_intro = "## System Metadata:"
|
|
||||||
resp_system = (
|
|
||||||
f"CPU Cores: {psutil.cpu_count()} ({platform.machine()})\nRAM: {ram_string}\n"
|
|
||||||
)
|
|
||||||
resp_os_intro = "## OS Variables:"
|
|
||||||
resp_os = f"OS version: {osver}\nUser: {user_who_ran}\n" # Ran where off to?!
|
|
||||||
resp_py_metadata = (
|
|
||||||
f"Python executable: {sys.executable}\n"
|
|
||||||
f"Python version: {pyver}\n"
|
|
||||||
f"Pip version: {pipver}\n"
|
|
||||||
)
|
|
||||||
resp_red_metadata = f"Red version: {redver}\nDiscord.py version: {dpy_version}\n"
|
|
||||||
resp_red_vars_intro = "## Red variables:"
|
|
||||||
resp_red_vars = (
|
|
||||||
f"Instance name: {data_manager.instance_name}\n"
|
|
||||||
f"Owner(s): {owners_string}\n"
|
|
||||||
f"Storage type: {driver}\n"
|
|
||||||
f"Disabled intents: {disabled_intents}\n"
|
|
||||||
f"Data path: {data_path}\n"
|
|
||||||
f"Metadata file: {config_file}"
|
|
||||||
)
|
|
||||||
|
|
||||||
response = (
|
|
||||||
box(resp_intro, lang="md"),
|
|
||||||
"\n",
|
|
||||||
box(resp_system_intro, lang="md"),
|
|
||||||
box(resp_system),
|
|
||||||
"\n",
|
|
||||||
box(resp_os_intro, lang="md"),
|
|
||||||
box(resp_os),
|
|
||||||
box(resp_py_metadata),
|
|
||||||
box(resp_red_metadata),
|
|
||||||
"\n",
|
|
||||||
box(resp_red_vars_intro, lang="md"),
|
|
||||||
box(resp_red_vars),
|
|
||||||
)
|
|
||||||
|
|
||||||
await ctx.send("".join(response))
|
|
||||||
|
|
||||||
# You may ask why this command is owner-only,
|
# You may ask why this command is owner-only,
|
||||||
# cause after all it could be quite useful to guild owners!
|
# cause after all it could be quite useful to guild owners!
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user