mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-12-05 17:02:32 -05:00
Make some dependency changes, support Python 3.10 and 3.11 (#5611)
Co-authored-by: jack1142 <6032823+jack1142@users.noreply.github.com>
This commit is contained in:
@@ -269,8 +269,12 @@ def _ensure_no_colorama():
|
||||
from rich.console import detect_legacy_windows
|
||||
|
||||
if not detect_legacy_windows():
|
||||
import colorama
|
||||
import colorama.initialise
|
||||
try:
|
||||
import colorama
|
||||
import colorama.initialise
|
||||
except ModuleNotFoundError:
|
||||
# colorama is not Red's primary dependency so it might not be present
|
||||
return
|
||||
|
||||
colorama.deinit()
|
||||
|
||||
@@ -300,8 +304,6 @@ _VERSION = "3.5.0.dev1"
|
||||
|
||||
__version__, version_info = VersionInfo._get_version()
|
||||
|
||||
# Filter fuzzywuzzy slow sequence matcher warning
|
||||
_warnings.filterwarnings("ignore", module=r"fuzzywuzzy.*")
|
||||
# Show DeprecationWarning
|
||||
_warnings.filterwarnings("default", category=DeprecationWarning)
|
||||
|
||||
@@ -320,3 +322,13 @@ if not any(_re.match("^-(-debug|d+|-verbose|v+)$", i) for i in _sys.argv):
|
||||
module="asyncio",
|
||||
message="The loop argument is deprecated since Python 3.8",
|
||||
)
|
||||
# DEP-WARN - d.py currently uses audioop module, Danny is aware of the deprecation
|
||||
#
|
||||
# DeprecationWarning: 'audioop' is deprecated and slated for removal in Python 3.13
|
||||
# import audioop
|
||||
_warnings.filterwarnings(
|
||||
"ignore",
|
||||
category=DeprecationWarning,
|
||||
module="discord",
|
||||
message="'audioop' is deprecated and slated for removal",
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ import discord
|
||||
import lavalink
|
||||
from red_commons.logging import getLogger
|
||||
|
||||
from fuzzywuzzy import process
|
||||
from rapidfuzz import process
|
||||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator
|
||||
from redbot.core.utils import AsyncIter
|
||||
@@ -118,7 +118,7 @@ class LocalTrackUtilities(MixinMeta, metaclass=CompositeMetaClass):
|
||||
}
|
||||
search_results = process.extract(search_words, to_search_string, limit=50)
|
||||
search_list = []
|
||||
async for track_match, percent_match in AsyncIter(search_results):
|
||||
async for track_match, percent_match, __ in AsyncIter(search_results):
|
||||
if percent_match > 85:
|
||||
search_list.extend(
|
||||
[
|
||||
|
||||
@@ -7,7 +7,7 @@ import discord
|
||||
import lavalink
|
||||
from red_commons.logging import getLogger
|
||||
|
||||
from fuzzywuzzy import process
|
||||
from rapidfuzz import process
|
||||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator
|
||||
from redbot.core.utils import AsyncIter
|
||||
@@ -116,7 +116,7 @@ class QueueUtilities(MixinMeta, metaclass=CompositeMetaClass):
|
||||
async def _build_queue_search_list(
|
||||
self, queue_list: List[lavalink.Track], search_words: str
|
||||
) -> List[Tuple[int, str]]:
|
||||
track_list = []
|
||||
tracks = {}
|
||||
async for queue_idx, track in AsyncIter(queue_list).enumerate(start=1):
|
||||
if not self.match_url(track.uri):
|
||||
query = Query.process_input(track, self.local_folder_current_path)
|
||||
@@ -131,14 +131,12 @@ class QueueUtilities(MixinMeta, metaclass=CompositeMetaClass):
|
||||
else:
|
||||
track_title = track.title
|
||||
|
||||
song_info = {str(queue_idx): track_title}
|
||||
track_list.append(song_info)
|
||||
search_results = process.extract(search_words, track_list, limit=50)
|
||||
tracks[queue_idx] = track_title
|
||||
search_results = process.extract(search_words, tracks, limit=50)
|
||||
search_list = []
|
||||
async for search, percent_match in AsyncIter(search_results):
|
||||
async for queue_position, title in AsyncIter(search.items()):
|
||||
if percent_match > 89:
|
||||
search_list.append((queue_position, title))
|
||||
async for title, percent_match, queue_position in AsyncIter(search_results):
|
||||
if percent_match > 89:
|
||||
search_list.append((queue_position, title))
|
||||
return search_list
|
||||
|
||||
async def _build_queue_search_page(
|
||||
|
||||
@@ -7,7 +7,7 @@ from typing import Iterable, List, Mapping, Tuple, Dict, Set, Literal, Union
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
import discord
|
||||
from fuzzywuzzy import process
|
||||
from rapidfuzz import process
|
||||
|
||||
from redbot.core import Config, checks, commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
@@ -317,7 +317,7 @@ class CustomCommands(commands.Cog):
|
||||
"""
|
||||
Searches through custom commands, according to the query.
|
||||
|
||||
Uses fuzzywuzzy searching to find close matches.
|
||||
Uses fuzzy searching to find close matches.
|
||||
|
||||
**Arguments:**
|
||||
|
||||
@@ -326,10 +326,10 @@ class CustomCommands(commands.Cog):
|
||||
cc_commands = await CommandObj.get_commands(self.config.guild(ctx.guild))
|
||||
extracted = process.extract(query, list(cc_commands.keys()))
|
||||
accepted = []
|
||||
for entry in extracted:
|
||||
if entry[1] > 60:
|
||||
for key, score, __ in extracted:
|
||||
if score > 60:
|
||||
# Match was decently strong
|
||||
accepted.append((entry[0], cc_commands[entry[0]]))
|
||||
accepted.append((key, cc_commands[key]))
|
||||
else:
|
||||
# Match wasn't strong enough
|
||||
pass
|
||||
|
||||
@@ -1098,6 +1098,8 @@ class Red(
|
||||
"""
|
||||
This should only be run once, prior to logging in to Discord REST API.
|
||||
"""
|
||||
await super()._pre_login()
|
||||
|
||||
await self._maybe_update_config()
|
||||
self.description = await self._config.description()
|
||||
self._color = discord.Colour(await self._config.color())
|
||||
|
||||
@@ -8,7 +8,7 @@ from copy import deepcopy
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
|
||||
import appdirs
|
||||
import platformdirs
|
||||
from discord.utils import deprecated
|
||||
|
||||
from . import commands
|
||||
@@ -37,22 +37,30 @@ basic_config_default: Dict[str, Any] = {
|
||||
"CORE_PATH_APPEND": "core",
|
||||
}
|
||||
|
||||
appdir = appdirs.AppDirs("Red-DiscordBot")
|
||||
config_dir = Path(appdir.user_config_dir)
|
||||
appdir = platformdirs.PlatformDirs("Red-DiscordBot")
|
||||
config_dir = appdir.user_config_path
|
||||
_system_user = sys.platform == "linux" and 0 < os.getuid() < 1000
|
||||
if _system_user:
|
||||
if Path.home().exists():
|
||||
# We don't want to break someone just because they created home dir
|
||||
# but were already using the site_data_dir.
|
||||
# but were already using the site_data_path.
|
||||
#
|
||||
# But otherwise, we do want Red to use user_config_dir if home dir exists.
|
||||
_maybe_config_file = Path(appdir.site_data_dir) / "config.json"
|
||||
# But otherwise, we do want Red to use user_config_path if home dir exists.
|
||||
_maybe_config_file = appdir.site_data_path / "config.json"
|
||||
if _maybe_config_file.exists():
|
||||
config_dir = _maybe_config_file.parent
|
||||
else:
|
||||
config_dir = Path(appdir.site_data_dir)
|
||||
config_dir = appdir.site_data_path
|
||||
|
||||
config_file = config_dir / "config.json"
|
||||
if not config_file.exists() and sys.platform == "darwin":
|
||||
# backwards compatibility with the location given by appdirs 1.4.4 (replaced by platformdirs 2)
|
||||
# which was the same as user_data_path
|
||||
# https://platformdirs.readthedocs.io/en/stable/changelog.html#platformdirs-2-0-0
|
||||
_old_config_location = appdir.user_data_path / "config.json"
|
||||
if _old_config_location.exists():
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
_old_config_location.rename(config_file)
|
||||
|
||||
|
||||
def load_existing_config():
|
||||
|
||||
@@ -64,14 +64,20 @@ class RPC:
|
||||
RPC server manager.
|
||||
"""
|
||||
|
||||
app: web.Application
|
||||
_rpc: RedRpc
|
||||
_runner: web.AppRunner
|
||||
|
||||
def __init__(self):
|
||||
self._site: Optional[web.TCPSite] = None
|
||||
self._started = False
|
||||
|
||||
async def _pre_login(self) -> None:
|
||||
self.app = web.Application()
|
||||
self._rpc = RedRpc()
|
||||
self.app.router.add_route("*", "/", self._rpc.handle_request)
|
||||
|
||||
self._runner = web.AppRunner(self.app)
|
||||
self._site: Optional[web.TCPSite] = None
|
||||
self._started = False
|
||||
|
||||
async def initialize(self, port: int):
|
||||
"""
|
||||
@@ -134,6 +140,9 @@ class RPCMixin:
|
||||
|
||||
self.rpc_handlers = {} # Uppercase cog name to method
|
||||
|
||||
async def _pre_login(self) -> None:
|
||||
await self.rpc._pre_login()
|
||||
|
||||
def register_rpc_handler(self, method):
|
||||
"""
|
||||
Registers a method to act as an RPC handler if the internal RPC server is active.
|
||||
|
||||
@@ -32,7 +32,7 @@ from typing import (
|
||||
import aiohttp
|
||||
import discord
|
||||
from packaging.requirements import Requirement
|
||||
from fuzzywuzzy import fuzz, process
|
||||
from rapidfuzz import fuzz, process
|
||||
from rich.progress import ProgressColumn
|
||||
from rich.progress_bar import ProgressBar
|
||||
from red_commons.logging import VERBOSE, TRACE
|
||||
@@ -147,20 +147,20 @@ async def fuzzy_command_search(
|
||||
return None
|
||||
|
||||
if commands is None:
|
||||
choices = set(ctx.bot.walk_commands())
|
||||
choices = {c: c.qualified_name for c in ctx.bot.walk_commands()}
|
||||
elif isinstance(commands, collections.abc.AsyncIterator):
|
||||
choices = {c async for c in commands}
|
||||
choices = {c: c.qualified_name async for c in commands}
|
||||
else:
|
||||
choices = set(commands)
|
||||
choices = {c: c.qualified_name for c in commands}
|
||||
|
||||
# Do the scoring. `extracted` is a list of tuples in the form `(command, score)`
|
||||
# Do the scoring. `extracted` is a list of tuples in the form `(cmd_name, score, cmd)`
|
||||
extracted = process.extract(term, choices, limit=5, scorer=fuzz.QRatio)
|
||||
if not extracted:
|
||||
return None
|
||||
|
||||
# Filter through the fuzzy-matched commands.
|
||||
matched_commands = []
|
||||
for command, score in extracted:
|
||||
for __, score, command in extracted:
|
||||
if score < min_score:
|
||||
# Since the list is in decreasing order of score, we can exit early.
|
||||
break
|
||||
|
||||
@@ -10,7 +10,7 @@ from datetime import datetime # This clearly never leads to confusion...
|
||||
from os import isatty
|
||||
|
||||
import rich
|
||||
from pygments.styles.monokai import MonokaiStyle
|
||||
from pygments.styles.monokai import MonokaiStyle # DEP-WARN
|
||||
from pygments.token import (
|
||||
Comment,
|
||||
Error,
|
||||
@@ -22,16 +22,14 @@ from pygments.token import (
|
||||
Token,
|
||||
)
|
||||
from rich._log_render import LogRender # DEP-WARN
|
||||
from rich.console import render_group
|
||||
from rich.containers import Renderables
|
||||
from rich.console import group
|
||||
from rich.highlighter import NullHighlighter
|
||||
from rich.logging import RichHandler
|
||||
from rich.style import Style
|
||||
from rich.syntax import ANSISyntaxTheme, PygmentsSyntaxTheme
|
||||
from rich.table import Table
|
||||
from rich.syntax import ANSISyntaxTheme, PygmentsSyntaxTheme # DEP-WARN
|
||||
from rich.text import Text
|
||||
from rich.theme import Theme
|
||||
from rich.traceback import PathHighlighter, Traceback
|
||||
from rich.traceback import PathHighlighter, Traceback # DEP-WARN
|
||||
|
||||
|
||||
MAX_OLD_LOGS = 8
|
||||
@@ -151,7 +149,8 @@ class FixedMonokaiStyle(MonokaiStyle):
|
||||
|
||||
|
||||
class RedTraceback(Traceback):
|
||||
@render_group()
|
||||
# DEP-WARN
|
||||
@group()
|
||||
def _render_stack(self, stack):
|
||||
for obj in super()._render_stack.__wrapped__(self, stack):
|
||||
if obj != "":
|
||||
|
||||
@@ -7,8 +7,10 @@ __all__ = ["rpc", "rpcmixin", "cog", "existing_func", "existing_multi_func"]
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def rpc():
|
||||
return RPC()
|
||||
async def rpc():
|
||||
rpc = RPC()
|
||||
await rpc._pre_login()
|
||||
return rpc
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
|
||||
Reference in New Issue
Block a user