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:
Jakub Kuczys 2022-12-30 03:21:57 +01:00 committed by GitHub
parent d3308af0e2
commit 519acedf46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 324 additions and 373 deletions

View File

@ -27,8 +27,11 @@ jobs:
python_version: "3.9"
friendly_name: Python 3.9 - Tests
- tox_env: py310
python_version: "3.10-dev"
friendly_name: Python 3.10-dev - Tests
python_version: "3.10"
friendly_name: Python 3.10 - Tests
- tox_env: py311
python_version: "3.11"
friendly_name: Python 3.11 - Tests
- tox_env: style
friendly_name: Style
- tox_env: docs
@ -46,7 +49,7 @@ jobs:
- name: Install tox
run: |
python -m pip install --upgrade pip
pip install 'tox<4'
pip install tox
- name: Tox test
env:
TOXENV: ${{ matrix.tox_env }}
@ -59,7 +62,8 @@ jobs:
python_version:
- "3.8"
- "3.9"
- "3.10-dev"
- "3.10"
- "3.11"
fail-fast: false
name: Tox - Postgres
services:
@ -82,7 +86,7 @@ jobs:
- name: Install tox
run: |
python -m pip install --upgrade pip
pip install 'tox<4'
pip install tox
- name: Tox test
env:
TOXENV: postgres

View File

@ -267,7 +267,7 @@ customcom search
Searches through custom commands, according to the query.
Uses fuzzywuzzy searching to find close matches.
Uses fuzzy searching to find close matches.
**Arguments:**

View File

@ -82,7 +82,7 @@ release = __version__
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = "en"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@ -246,8 +246,8 @@ intersphinx_mapping = {
# :dpy_docs:`link text <site_name.html>`
extlinks = {
"dpy_docs": (f"{dpy_docs_url}/%s", None),
"issue": ("https://github.com/Cog-Creators/Red-DiscordBot/issues/%s", "#"),
"ghuser": ("https://github.com/%s", "@"),
"issue": ("https://github.com/Cog-Creators/Red-DiscordBot/issues/%s", "#%s"),
"ghuser": ("https://github.com/%s", "@%s"),
}
# Doctest

View File

@ -21,18 +21,3 @@ to keep it in a location which is easy to type out the path to. From now, we'll
``redenv`` and it will be located in your home directory.
Create your virtual environment with the following command:
.. prompt:: bash
python3.9 -m venv ~/redenv
And activate it with the following command:
.. prompt:: bash
source ~/redenv/bin/activate
.. important::
You must activate the virtual environment with the above command every time you open a new
shell to run, install or update Red.

View File

@ -0,0 +1,10 @@
And activate it with the following command:
.. prompt:: bash
source ~/redenv/bin/activate
.. important::
You must activate the virtual environment with the above command every time you open a new
shell to run, install or update Red.

View File

@ -0,0 +1,7 @@
.. include:: _includes/_create-env-with-venv-intro.rst
.. prompt:: bash
python3.10 -m venv ~/redenv
.. include:: _includes/_create-env-with-venv-outro.rst

View File

@ -0,0 +1,7 @@
.. include:: _includes/_create-env-with-venv-intro.rst
.. prompt:: bash
python3.11 -m venv ~/redenv
.. include:: _includes/_create-env-with-venv-outro.rst

View File

@ -0,0 +1,7 @@
.. include:: _includes/_create-env-with-venv-intro.rst
.. prompt:: bash
python3.9 -m venv ~/redenv
.. include:: _includes/_create-env-with-venv-outro.rst

View File

@ -13,7 +13,7 @@ Install them with dnf:
sudo dnf -y update
sudo dnf -y group install development
sudo dnf -y install python39 python39-pip python39-devel java-11-openjdk-headless nano git
sudo dnf -y install python39 python39-devel java-11-openjdk-headless nano git
Set ``java`` executable to point to Java 11:
@ -23,6 +23,6 @@ Set ``java`` executable to point to Java 11:
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.9.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -11,10 +11,10 @@ Install them with dnf:
.. prompt:: bash
sudo dnf -y install python39 git java-11-openjdk-headless @development nano
sudo dnf -y install python39 python3-devel git java-11-openjdk-headless @development nano
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.9.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -2,7 +2,7 @@
Installing Python with pyenv
----------------------------
On distributions where Python 3.9 needs to be compiled from source, we recommend the use of pyenv.
On distributions where Python 3.11 needs to be compiled from source, we recommend the use of pyenv.
This simplifies the compilation process and has the added bonus of simplifying setting up Red in a
virtual environment.
@ -10,7 +10,7 @@ virtual environment.
.. prompt:: bash
CONFIGURE_OPTS=--enable-optimizations pyenv install 3.9.9 -v
CONFIGURE_OPTS=--enable-optimizations pyenv install 3.11.1 -v
This may take a long time to complete, depending on your hardware. For some machines (such as
Raspberry Pis and micro-tier VPSes), it may take over an hour; in this case, you may wish to remove
@ -22,6 +22,6 @@ After that is finished, run:
.. prompt:: bash
pyenv global 3.9.9
pyenv global 3.11.1
Pyenv is now installed and your system should be configured to run Python 3.9.
Pyenv is now installed and your system should be configured to run Python 3.11.

View File

@ -0,0 +1,27 @@
----------------------------
Installing Python with pyenv
----------------------------
On distributions where Python 3.10 needs to be compiled from source, we recommend the use of pyenv.
This simplifies the compilation process and has the added bonus of simplifying setting up Red in a
virtual environment.
.. include:: _includes/_install-pyenv-and-setup-path.rst
.. prompt:: bash
CONFIGURE_OPTS=--enable-optimizations pyenv install 3.10.9 -v
This may take a long time to complete, depending on your hardware. For some machines (such as
Raspberry Pis and micro-tier VPSes), it may take over an hour; in this case, you may wish to remove
the ``CONFIGURE_OPTS=--enable-optimizations`` part from the front of the command, which will
drastically reduce the install time. However, be aware that this will make Python run about 10%
slower.
After that is finished, run:
.. prompt:: bash
pyenv global 3.10.9
Pyenv is now installed and your system should be configured to run Python 3.10.

View File

@ -2,7 +2,7 @@
Installing Python with pyenv
----------------------------
On distributions where Python 3.8 needs to be compiled from source, we recommend the use of pyenv.
On distributions where Python 3.9 needs to be compiled from source, we recommend the use of pyenv.
This simplifies the compilation process and has the added bonus of simplifying setting up Red in a
virtual environment.
@ -10,7 +10,7 @@ virtual environment.
.. prompt:: bash
CONFIGURE_OPTS=--enable-optimizations pyenv install 3.8.12 -v
CONFIGURE_OPTS=--enable-optimizations pyenv install 3.9.16 -v
This may take a long time to complete, depending on your hardware. For some machines (such as
Raspberry Pis and micro-tier VPSes), it may take over an hour; in this case, you may wish to remove
@ -22,6 +22,6 @@ After that is finished, run:
.. prompt:: bash
pyenv global 3.8.12
pyenv global 3.9.16
Pyenv is now installed and your system should be configured to run Python 3.8.
Pyenv is now installed and your system should be configured to run Python 3.9.

View File

@ -16,10 +16,22 @@ Install the pre-requirements with pacman:
.. prompt:: bash
sudo pacman -Syu python python-pip git jre11-openjdk-headless base-devel nano
sudo pacman -Syu git jre11-openjdk-headless base-devel nano
On Arch Linux, Python 3.9 can be installed from the Arch User Repository (AUR) from the ``python39`` package.
The manual build process is the Arch-supported install method for AUR packages. You can install ``python39`` package with the following commands:
.. prompt:: bash
git clone https://aur.archlinux.org/python39.git /tmp/python39
cd /tmp/python39
makepkg -sicL
cd -
rm -rf /tmp/python39
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.9.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -37,7 +37,9 @@ In order to install Git 2.11 or greater, we recommend adding the IUS repository:
.. Include common instructions:
.. include:: _includes/install-python-pyenv.rst
.. Python 3.10 requires OpenSSL 1.1.1 which CentOS 7 doesn't provide in base repository.
.. include:: _includes/install-python39-pyenv.rst
.. include:: _includes/create-env-with-pyenv-virtualenv.rst

View File

@ -18,7 +18,7 @@ Debian Buster. This guide will tell you how. First, run the following commands:
.. prompt:: bash
sudo apt update
sudo apt -y install make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev libgdbm-dev uuid-dev python3-openssl git openjdk-11-jre-headless nano
sudo apt -y install make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev libgdbm-dev uuid-dev python3-openssl git openjdk-11-jre-headless nano
CXX=/usr/bin/g++
.. Include common instructions:

View File

@ -18,10 +18,10 @@ with apt:
.. prompt:: bash
sudo apt update
sudo apt -y install python3 python3-dev python3-venv python3-pip git openjdk-11-jre-headless build-essential nano
sudo apt -y install python3 python3-dev python3-venv git openjdk-11-jre-headless build-essential nano
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.9.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -17,10 +17,10 @@ them with dnf:
.. prompt:: bash
sudo dnf -y install python39 git java-11-openjdk-headless @development-tools nano
sudo dnf -y install python3.10 python3.10-devel git java-11-openjdk-headless @development-tools nano
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.10.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -23,7 +23,7 @@ one-by-one:
.. prompt:: bash
brew install python@3.9
brew install python@3.11
brew install git
brew tap homebrew/cask-versions
brew install --cask temurin11
@ -34,11 +34,11 @@ To fix this, you should run these commands:
.. prompt:: bash
profile=$([ -n "$ZSH_VERSION" ] && echo ~/.zprofile || ([ -f ~/.bash_profile ] && echo ~/.bash_profile || echo ~/.profile))
echo 'export PATH="$(brew --prefix)/opt/python@3.9/bin:$PATH"' >> "$profile"
echo 'export PATH="$(brew --prefix)/opt/python@3.11/bin:$PATH"' >> "$profile"
source "$profile"
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.11.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -1,7 +1,7 @@
.. _install-opensuse-leap-15:
=====================================
Installing Red on openSUSE Leap 15.3+
Installing Red on openSUSE Leap 15.4+
=====================================
.. include:: _includes/supported-arch-x64+aarch64.rst
@ -12,16 +12,16 @@ Installing Red on openSUSE Leap 15.3+
Installing the pre-requirements
-------------------------------
openSUSE Leap 15.3+ has all required dependencies available in official repositories. Install them
openSUSE Leap 15.4+ has all required dependencies available in official repositories. Install them
with zypper:
.. prompt:: bash
sudo zypper -n install python39-base python39-pip git-core java-11-openjdk-headless nano
sudo zypper -n install python310 python310-devel git-core java-11-openjdk-headless nano
sudo zypper -n install -t pattern devel_basis
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.10.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -17,11 +17,11 @@ with zypper:
.. prompt:: bash
sudo zypper -n install python39-base python39-pip git-core java-11-openjdk-headless nano
sudo zypper -n install python311 python311-devel git-core java-11-openjdk-headless nano
sudo zypper -n install -t pattern devel_basis
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.11.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -35,15 +35,20 @@ Installing the pre-requirements
We recommend installing pyenv as a method of installing non-native versions of Python on
Raspberry Pi OS. This guide will tell you how. First, run the following commands:
.. cmake is necessary to be able to successfuly build rapidfuzz.
.. prompt:: bash
sudo apt update
sudo apt -y install make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev libgdbm-dev uuid-dev python3-openssl git openjdk-11-jre-headless nano
sudo apt -y install cmake make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev libgdbm-dev uuid-dev python3-openssl git openjdk-11-jre-headless nano
CXX=/usr/bin/g++
.. Include common instructions:
.. include:: _includes/install-python38-pyenv.rst
.. We should only build and install even versions of Python on Raspberry Pi OS as odd
.. versions are part of piwheels and can cause installs of pip packages that won't work.
.. include:: _includes/install-python310-pyenv.rst
.. include:: _includes/create-env-with-pyenv-virtualenv.rst

View File

@ -33,10 +33,10 @@ with apt:
.. prompt:: bash
sudo apt update
sudo apt -y install python3 python3-dev python3-venv python3-pip git openjdk-11-jre-headless build-essential nano
sudo apt -y install python3 python3-dev python3-venv git openjdk-11-jre-headless build-essential nano
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.9.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -12,6 +12,10 @@ Installing Red on Ubuntu 18.04 LTS
Installing the pre-requirements
-------------------------------
.. Git 2.17.0-2.22.0 have an issue with partial clone which is used in pip for git installs.
.. Not incredibly important perhaps but this ppa is recommended by git-scm.com/download/linux
.. so it should be fine.
We recommend adding the ``git-core`` ppa to install Git 2.11 or greater:
.. prompt:: bash
@ -20,7 +24,7 @@ We recommend adding the ``git-core`` ppa to install Git 2.11 or greater:
sudo apt -y install software-properties-common
sudo add-apt-repository -y ppa:git-core/ppa
We recommend adding the ``deadsnakes`` ppa to install Python 3.9:
We recommend adding the ``deadsnakes`` ppa to install Python 3.11:
.. prompt:: bash
@ -30,10 +34,10 @@ Now install the pre-requirements with apt:
.. prompt:: bash
sudo apt -y install python3.9 python3.9-dev python3.9-venv python3-pip git openjdk-11-jre-headless build-essential nano
sudo apt -y install python3.11 python3.11-dev python3.11-venv git openjdk-11-jre-headless build-essential nano
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.11.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -12,22 +12,16 @@ Installing Red on Ubuntu 20.04 LTS
Installing the pre-requirements
-------------------------------
We recommend adding the ``git-core`` ppa to install Git 2.11 or greater:
Ubuntu 20.04 LTS has all required packages available in official repositories. Install them
with apt:
.. prompt:: bash
sudo apt update
sudo apt -y install software-properties-common
sudo add-apt-repository -y ppa:git-core/ppa
Now install the pre-requirements with apt:
.. prompt:: bash
sudo apt -y install python3.9 python3.9-dev python3.9-venv python3-pip git openjdk-11-jre-headless build-essential nano
sudo apt -y install python3.9 python3.9-dev python3.9-venv git openjdk-11-jre-headless build-essential nano
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.9.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -12,22 +12,16 @@ Installing Red on Ubuntu 22.04 LTS
Installing the pre-requirements
-------------------------------
We recommend adding the ``deadsnakes`` ppa to install Python 3.9:
Ubuntu 22.04 LTS has all required packages available in official repositories. Install them
with apt:
.. prompt:: bash
sudo apt update
sudo apt -y install software-properties-common
sudo add-apt-repository -y ppa:deadsnakes/ppa
Now install the pre-requirements with apt:
.. prompt:: bash
sudo apt -y install python3.9 python3.9-dev python3.9-venv python3-pip git openjdk-11-jre-headless build-essential nano
sudo apt -y install python3.10 python3.10-dev python3.10-venv git openjdk-11-jre-headless build-essential nano
.. Include common instructions:
.. include:: _includes/create-env-with-venv.rst
.. include:: _includes/create-env-with-venv3.10.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -12,26 +12,15 @@ Installing Red on Ubuntu non-LTS versions
Installing the pre-requirements
-------------------------------
We recommend adding the ``git-core`` ppa to install Git 2.11 or greater:
Now install the pre-requirements with apt:
.. prompt:: bash
sudo apt update
sudo apt -y install software-properties-common
sudo add-apt-repository -yu ppa:git-core/ppa
Now, to install non-native version of python on non-LTS versions of Ubuntu, we recommend
installing pyenv. To do this, first run the following commands:
.. prompt:: bash
sudo apt -y install make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev libgdbm-dev uuid-dev python3-openssl git openjdk-11-jre-headless nano
CXX=/usr/bin/g++
sudo apt -y install python3.11 python3.11-dev python3.11-venv git openjdk-11-jre-headless build-essential nano
.. Include common instructions:
.. include:: _includes/install-python-pyenv.rst
.. include:: _includes/create-env-with-pyenv-virtualenv.rst
.. include:: _includes/create-env-with-venv3.11.rst
.. include:: _includes/install-and-setup-red-unix.rst

View File

@ -33,7 +33,7 @@ Then run each of the following commands:
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
choco upgrade git --params "/GitOnlyOnPath /WindowsTerminal" -y
choco upgrade visualstudio2022-workload-vctools -y
choco upgrade python3 -y --version 3.9.9
choco upgrade python311 -y
For Audio support, you should also run the following command before exiting:
@ -57,7 +57,7 @@ Manually installing dependencies
* `MSVC Build tools <https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2019>`_
* `Python 3.8.1 - 3.9.x <https://www.python.org/downloads/windows/>`_
* `Python 3.8.1 - 3.11.x <https://www.python.org/downloads/windows/>`_
.. attention:: Please make sure that the box to add Python to PATH is CHECKED, otherwise
you may run into issues when trying to run Red.
@ -104,7 +104,7 @@ Then create your virtual environment with the following command
.. prompt:: batch
py -3.9 -m venv "%userprofile%\redenv"
py -3.11 -m venv "%userprofile%\redenv"
And activate it with the following command

View File

@ -64,7 +64,6 @@ Debian 10 Buster x86-64, aarch64, armv7l 2022-08-14 (`End of
Debian 11 Bullseye x86-64, aarch64, armv7l ~2024-09 (`End of life <https://wiki.debian.org/DebianReleases#Production_Releases>`__)
Fedora Linux 35 x86-64, aarch64 2022-11-15 (`End of Life <https://docs.fedoraproject.org/en-US/releases/lifecycle/#_maintenance_schedule>`__)
Fedora Linux 36 x86-64, aarch64 2023-05-16 (`End of Life <https://docs.fedoraproject.org/en-US/releases/lifecycle/#_maintenance_schedule>`__)
openSUSE Leap 15.3 x86-64, aarch64 2022-11-30 (`end of maintenance life cycle <https://en.opensuse.org/Lifetime#openSUSE_Leap>`__)
openSUSE Leap 15.4 x86-64, aarch64 2023-11-30 (`end of maintenance life cycle <https://en.opensuse.org/Lifetime#openSUSE_Leap>`__)
openSUSE Tumbleweed x86-64, aarch64 forever (support is only provided for an up-to-date system)
Oracle Linux 8 x86-64, aarch64 2029-07-31 (`End of Premier Support <https://www.oracle.com/us/support/library/elsp-lifetime-069338.pdf>`__)

View File

@ -20,6 +20,8 @@ classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Topic :: Communications :: Chat",
]
dynamic = ["version", "requires-python", "dependencies", "optional-dependencies"]
@ -42,7 +44,7 @@ red-discordbot = "redbot.pytest"
[tool.black]
line-length = 99
required-version = '22.1.0'
required-version = '22'
target-version = ['py38']
include = '\.py$'
force-exclude = '''
@ -50,3 +52,6 @@ force-exclude = '''
redbot\/vendored
)/
'''
[tool.pytest.ini_options]
asyncio_mode = 'auto'

View File

@ -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",
)

View File

@ -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(
[

View File

@ -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(

View File

@ -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

View File

@ -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())

View File

@ -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():

View File

@ -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.

View File

@ -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

View File

@ -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 != "":

View File

@ -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()

View File

@ -1,23 +1,24 @@
aiodns
aiohttp
aiohttp-json-rpc
aiosqlite
appdirs
apsw-wheels
apsw
babel
Brotli
click
colorama
discord.py
fuzzywuzzy
markdown
orjson
packaging
platformdirs
psutil
python-dateutil
python-Levenshtein-wheels
PyNaCl
PyYAML
rapidfuzz
Red-Commons
Red-Lavalink>=0.11.0rc1
rich
schema
typing_extensions
yarl
distro; sys_platform == "linux"
uvloop; sys_platform != "win32" and platform_python_implementation == "CPython"

View File

@ -1,4 +1,6 @@
aiohttp==3.7.4.post0
aiodns==3.0.0
# via -r base.in
aiohttp==3.8.3
# via
# -r base.in
# aiohttp-json-rpc
@ -6,28 +8,24 @@ aiohttp==3.7.4.post0
# red-lavalink
aiohttp-json-rpc==0.13.3
# via -r base.in
aiosqlite==0.17.0
# via -r base.in
appdirs==1.4.4
# via -r base.in
apsw-wheels==3.36.0.post1
# via -r base.in
async-timeout==3.0.1
aiosignal==1.3.1
# via aiohttp
attrs==21.2.0
# via aiohttp
babel==2.9.1
apsw==3.40.0.0
# via -r base.in
cffi==1.14.6
# via pynacl
chardet==4.0.0
async-timeout==4.0.2
# via aiohttp
click==8.0.1
attrs==22.2.0
# via aiohttp
babel==2.11.0
# via -r base.in
brotli==1.0.9
# via -r base.in
cffi==1.15.1
# via pycares
charset-normalizer==2.1.1
# via aiohttp
click==8.1.3
# via -r base.in
colorama==0.4.4
# via
# -r base.in
# click
commonmark==0.9.1
# via rich
contextlib2==21.6.0
@ -36,33 +34,41 @@ discord-py==2.1.0
# via
# -r base.in
# red-lavalink
fuzzywuzzy==0.18.0
# via -r base.in
idna==3.2
frozenlist==1.3.3
# via
# aiohttp
# aiosignal
idna==3.4
# via yarl
markdown==3.3.4
importlib-metadata==5.2.0
# via markdown
markdown==3.4.1
# via -r base.in
multidict==5.1.0
multidict==6.0.4
# via
# aiohttp
# yarl
orjson==3.8.3
# via -r base.in
packaging==22.0
# via -r base.in
psutil==5.8.0
platformdirs==2.6.0
# via -r base.in
pycparser==2.20
psutil==5.9.4
# via -r base.in
pycares==4.3.0
# via aiodns
pycparser==2.21
# via cffi
pygments==2.10.0
pygments==2.13.0
# via rich
pynacl==1.4.0
# via -r base.in
python-dateutil==2.8.2
# via -r base.in
python-levenshtein-wheels==0.13.2
# via -r base.in
pytz==2021.1
pytz==2022.7
# via babel
pyyaml==5.4.1
pyyaml==6.0
# via -r base.in
rapidfuzz==2.13.7
# via -r base.in
red-commons==1.0.0
# via
@ -70,19 +76,25 @@ red-commons==1.0.0
# red-lavalink
red-lavalink==0.11.0rc1
# via -r base.in
rich==10.9.0
rich==12.6.0
# via -r base.in
schema==0.7.4
schema==0.7.5
# via -r base.in
six==1.16.0
# via python-dateutil
typing-extensions==3.10.0.2
# via rich
yarl==1.6.3
typing-extensions==4.4.0
# via
# -r base.in
# rich
yarl==1.8.2
# via
# -r base.in
# aiohttp
distro==1.6.0; sys_platform == "linux"
zipp==3.11.0
# via importlib-metadata
colorama==0.4.6; sys_platform == "win32"
# via click
distro==1.8.0; sys_platform == "linux" and sys_platform == "linux"
# via -r base.in
uvloop==0.16.0; sys_platform != "win32" and platform_python_implementation == "CPython"
uvloop==0.17.0; (sys_platform != "win32" and platform_python_implementation == "CPython") and sys_platform != "win32"
# via -r base.in

View File

@ -1,24 +1,22 @@
alabaster==0.7.12
# via sphinx
certifi==2021.5.30
certifi==2022.12.7
# via requests
charset-normalizer==2.0.4
# via requests
docutils==0.16
docutils==0.17.1
# via
# sphinx
# sphinx-rtd-theme
imagesize==1.2.0
imagesize==1.4.1
# via sphinx
jinja2==3.0.1
jinja2==3.1.2
# via sphinx
markupsafe==2.0.1
markupsafe==2.1.1
# via jinja2
requests==2.26.0
requests==2.28.1
# via sphinx
snowballstemmer==2.1.0
snowballstemmer==2.2.0
# via sphinx
sphinx==4.1.2
sphinx==5.3.0
# via
# -r extra-doc.in
# sphinx-prompt
@ -26,7 +24,7 @@ sphinx==4.1.2
# sphinxcontrib-trio
sphinx-prompt==1.5.0
# via -r extra-doc.in
sphinx-rtd-theme==0.5.2
sphinx-rtd-theme==1.1.1
# via -r extra-doc.in
sphinxcontrib-applehelp==1.0.2
# via sphinx
@ -42,5 +40,5 @@ sphinxcontrib-serializinghtml==1.1.5
# via sphinx
sphinxcontrib-trio==1.1.2
# via -r extra-doc.in
urllib3==1.26.6
urllib3==1.26.13
# via requests

View File

@ -1,2 +1,2 @@
asyncpg==0.24.0
asyncpg==0.27.0
# via -r extra-postgres.in

View File

@ -1,12 +1,8 @@
black==22.1.0
black==22.12.0
# via -r extra-style.in
mypy-extensions==0.4.3
# via black
pathspec==0.9.0
pathspec==0.10.3
# via black
regex==2021.8.28
# via black
toml==0.10.2
# via black
typed-ast==1.4.3
tomli==2.0.1
# via black

View File

@ -1,33 +1,35 @@
astroid==2.7.3
astroid==2.12.13
# via pylint
dill==0.3.6
# via pylint
exceptiongroup==1.1.0
# via pytest
iniconfig==1.1.1
# via pytest
isort==5.9.3
isort==5.11.4
# via pylint
lazy-object-proxy==1.6.0
lazy-object-proxy==1.8.0
# via astroid
mccabe==0.6.1
# via pylint
platformdirs==2.3.0
mccabe==0.7.0
# via pylint
pluggy==1.0.0
# via pytest
py==1.10.0
# via pytest
pylint==2.10.2
pylint==2.15.9
# via -r extra-test.in
pytest==6.2.5
pytest==7.2.0
# via
# -r extra-test.in
# pytest-asyncio
# pytest-mock
pytest-asyncio==0.15.1
pytest-asyncio==0.20.3
# via -r extra-test.in
pytest-mock==3.6.1
pytest-mock==3.10.0
# via -r extra-test.in
toml==0.10.2
tomli==2.0.1
# via
# pylint
# pytest
wrapt==1.12.1
tomlkit==0.11.6
# via pylint
wrapt==1.14.1
# via astroid

View File

@ -47,8 +47,8 @@ extras_require["all"] = extras_combined("postgres")
python_requires = ">=3.8.1"
if not os.getenv("TOX_RED", False) or sys.version_info < (3, 10):
python_requires += ",<3.10"
if not os.getenv("TOX_RED", False) or sys.version_info < (3, 12):
python_requires += ",<3.12"
# Metadata and options defined in pyproject.toml
setup(

View File

@ -65,7 +65,6 @@ ancestor_rev = "c950fc05a540dd76b944719c2a3302da2e2f3090"
descendant_rev = "fb99eb7d2d5bed514efc98fe6686b368f8425745"
@pytest.mark.asyncio
@pytest.mark.parametrize(
"maybe_ancestor_rev,descendant_rev,returncode,expected",
[(ancestor_rev, descendant_rev, 0, True), (descendant_rev, ancestor_rev, 1, False)],
@ -86,7 +85,6 @@ async def test_is_ancestor(mocker, repo, maybe_ancestor_rev, descendant_rev, ret
assert ret is expected
@pytest.mark.asyncio
async def test_is_ancestor_object_raise(mocker, repo):
m = _mock_run(mocker, repo, 128, b"", b"fatal: Not a valid object name invalid1")
with pytest.raises(UnknownRevision):
@ -104,7 +102,6 @@ async def test_is_ancestor_object_raise(mocker, repo):
)
@pytest.mark.asyncio
async def test_is_ancestor_commit_raise(mocker, repo):
m = _mock_run(
mocker,
@ -130,7 +127,6 @@ async def test_is_ancestor_commit_raise(mocker, repo):
)
@pytest.mark.asyncio
async def test_get_file_update_statuses(mocker, repo):
old_rev = "c950fc05a540dd76b944719c2a3302da2e2f3090"
new_rev = "fb99eb7d2d5bed514efc98fe6686b368f8425745"
@ -160,7 +156,6 @@ async def test_get_file_update_statuses(mocker, repo):
}
@pytest.mark.asyncio
async def test_is_module_modified(mocker, repo):
old_rev = "c950fc05a540dd76b944719c2a3302da2e2f3090"
new_rev = "fb99eb7d2d5bed514efc98fe6686b368f8425745"
@ -184,7 +179,6 @@ async def test_is_module_modified(mocker, repo):
assert ret is True
@pytest.mark.asyncio
async def test_get_full_sha1_success(mocker, repo):
commit = "c950fc05a540dd76b944719c2a3302da2e2f3090"
m = _mock_run(mocker, repo, 0, commit.encode())
@ -196,7 +190,6 @@ async def test_get_full_sha1_success(mocker, repo):
assert ret == commit
@pytest.mark.asyncio
async def test_get_full_sha1_notfound(mocker, repo):
m = _mock_run(mocker, repo, 128, b"", b"fatal: Needed a single revision")
with pytest.raises(UnknownRevision):
@ -206,7 +199,6 @@ async def test_get_full_sha1_notfound(mocker, repo):
)
@pytest.mark.asyncio
async def test_get_full_sha1_ambiguous(mocker, repo):
m = _mock_run(
mocker,
@ -246,7 +238,6 @@ def test_update_available_modules(repo):
)
@pytest.mark.asyncio
async def test_checkout(mocker, repo):
commit = "c950fc05a540dd76b944719c2a3302da2e2f3090"
m = _mock_run(mocker, repo, 0)
@ -261,7 +252,6 @@ async def test_checkout(mocker, repo):
)
@pytest.mark.asyncio
async def test_checkout_ctx_manager(mocker, repo):
commit = "c950fc05a540dd76b944719c2a3302da2e2f3090"
m = mocker.patch.object(repo, "_checkout", autospec=True, return_value=None)
@ -273,7 +263,6 @@ async def test_checkout_ctx_manager(mocker, repo):
m.assert_called_with(old_commit, force_checkout=False)
@pytest.mark.asyncio
async def test_checkout_await(mocker, repo):
commit = "c950fc05a540dd76b944719c2a3302da2e2f3090"
m = mocker.patch.object(repo, "_checkout", autospec=True, return_value=None)
@ -282,7 +271,6 @@ async def test_checkout_await(mocker, repo):
m.assert_called_once_with(commit, force_checkout=False)
@pytest.mark.asyncio
async def test_clone_with_branch(mocker, repo):
branch = repo.branch = "dont_add_commits"
commit = "a0ccc2390883c85a361f5a90c72e1b07958939fa"
@ -300,7 +288,6 @@ async def test_clone_with_branch(mocker, repo):
)
@pytest.mark.asyncio
async def test_clone_without_branch(mocker, repo):
branch = "dont_add_commits"
commit = "a0ccc2390883c85a361f5a90c72e1b07958939fa"
@ -318,7 +305,6 @@ async def test_clone_without_branch(mocker, repo):
)
@pytest.mark.asyncio
async def test_update(mocker, repo):
old_commit = repo.commit
new_commit = "a0ccc2390883c85a361f5a90c72e1b07958939fa"
@ -335,7 +321,6 @@ async def test_update(mocker, repo):
# old tests
@pytest.mark.asyncio
async def test_add_repo(monkeypatch, repo_manager):
monkeypatch.setattr("redbot.cogs.downloader.repo_manager.Repo._run", fake_run_noprint)
monkeypatch.setattr(
@ -349,7 +334,6 @@ async def test_add_repo(monkeypatch, repo_manager):
assert squid.available_modules == ()
@pytest.mark.asyncio
async def test_lib_install_requirements(monkeypatch, library_installable, repo, tmpdir):
monkeypatch.setattr("redbot.cogs.downloader.repo_manager.Repo._run", fake_run_noprint)
monkeypatch.setattr(
@ -368,7 +352,6 @@ async def test_lib_install_requirements(monkeypatch, library_installable, repo,
assert len(failed) == 0
@pytest.mark.asyncio
async def test_remove_repo(monkeypatch, repo_manager):
monkeypatch.setattr("redbot.cogs.downloader.repo_manager.Repo._run", fake_run_noprint)
monkeypatch.setattr(
@ -383,7 +366,6 @@ async def test_remove_repo(monkeypatch, repo_manager):
assert repo_manager.get_repo("squid") is None
@pytest.mark.asyncio
async def test_existing_repo(mocker, repo_manager):
repo_manager.does_repo_exist = mocker.MagicMock(return_value=True)

View File

@ -13,7 +13,6 @@ from redbot.pytest.downloader import (
)
@pytest.mark.asyncio
async def test_git_clone_nobranch(git_repo, tmp_path):
p = await git_repo._run(
ProcessFormatter().format(
@ -25,7 +24,6 @@ async def test_git_clone_nobranch(git_repo, tmp_path):
assert p.returncode == 0
@pytest.mark.asyncio
async def test_git_clone_branch(git_repo, tmp_path):
p = await git_repo._run(
ProcessFormatter().format(
@ -38,7 +36,6 @@ async def test_git_clone_branch(git_repo, tmp_path):
assert p.returncode == 0
@pytest.mark.asyncio
async def test_git_clone_non_existent_branch(git_repo, tmp_path):
p = await git_repo._run(
ProcessFormatter().format(
@ -51,7 +48,6 @@ async def test_git_clone_non_existent_branch(git_repo, tmp_path):
assert p.returncode == 128
@pytest.mark.asyncio
async def test_git_clone_notgit_repo(git_repo, tmp_path):
notgit_repo = tmp_path / "test_clone_folder"
p = await git_repo._run(
@ -62,7 +58,6 @@ async def test_git_clone_notgit_repo(git_repo, tmp_path):
assert p.returncode == 128
@pytest.mark.asyncio
async def test_git_current_branch_master(git_repo):
p = await git_repo._run(
ProcessFormatter().format(git_repo.GIT_CURRENT_BRANCH, path=git_repo.folder_path)
@ -71,7 +66,6 @@ async def test_git_current_branch_master(git_repo):
assert p.stdout.decode().strip() == "master"
@pytest.mark.asyncio
async def test_git_current_branch_detached(git_repo):
await git_repo._run(
ProcessFormatter().format(
@ -87,7 +81,6 @@ async def test_git_current_branch_detached(git_repo):
assert p.stderr.decode().strip() == "fatal: ref HEAD is not a symbolic ref"
@pytest.mark.asyncio
async def test_git_current_commit_on_branch(git_repo):
# HEAD on dont_add_commits (a0ccc2390883c85a361f5a90c72e1b07958939fa)
# setup
@ -105,7 +98,6 @@ async def test_git_current_commit_on_branch(git_repo):
assert p.stdout.decode().strip() == "a0ccc2390883c85a361f5a90c72e1b07958939fa"
@pytest.mark.asyncio
async def test_git_current_commit_detached(git_repo):
# detached HEAD state (c950fc05a540dd76b944719c2a3302da2e2f3090)
await git_repo._run(
@ -122,7 +114,6 @@ async def test_git_current_commit_detached(git_repo):
assert p.stdout.decode().strip() == "c950fc05a540dd76b944719c2a3302da2e2f3090"
@pytest.mark.asyncio
async def test_git_latest_commit(git_repo):
# HEAD on dont_add_commits (a0ccc2390883c85a361f5a90c72e1b07958939fa)
p = await git_repo._run(
@ -134,7 +125,6 @@ async def test_git_latest_commit(git_repo):
assert p.stdout.decode().strip() == "a0ccc2390883c85a361f5a90c72e1b07958939fa"
@pytest.mark.asyncio
async def test_git_hard_reset(cloned_git_repo, tmp_path):
staged_file = cloned_git_repo.folder_path / "staged_file.txt"
staged_file.touch()
@ -150,7 +140,6 @@ async def test_git_hard_reset(cloned_git_repo, tmp_path):
assert staged_file.exists() is False
@pytest.mark.asyncio
async def test_git_pull(git_repo_with_remote, tmp_path):
# setup
staged_file = Path(git_repo_with_remote.url) / "staged_file.txt"
@ -171,7 +160,6 @@ async def test_git_pull(git_repo_with_remote, tmp_path):
assert (git_repo_with_remote.folder_path / "staged_file.txt").exists()
@pytest.mark.asyncio
async def test_git_diff_file_status(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -195,7 +183,6 @@ async def test_git_diff_file_status(git_repo):
# might need to add test for test_git_log, but it's unused method currently
@pytest.mark.asyncio
async def test_git_discover_remote_url(cloned_git_repo, tmp_path):
p = await cloned_git_repo._run(
ProcessFormatter().format(
@ -206,7 +193,6 @@ async def test_git_discover_remote_url(cloned_git_repo, tmp_path):
assert p.stdout.decode().strip() == cloned_git_repo.url
@pytest.mark.asyncio
async def test_git_checkout_detached_head(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -218,7 +204,6 @@ async def test_git_checkout_detached_head(git_repo):
assert p.returncode == 0
@pytest.mark.asyncio
async def test_git_checkout_branch(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -228,7 +213,6 @@ async def test_git_checkout_branch(git_repo):
assert p.returncode == 0
@pytest.mark.asyncio
async def test_git_checkout_non_existent_branch(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -238,7 +222,6 @@ async def test_git_checkout_non_existent_branch(git_repo):
assert p.returncode == 1
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_branch_name(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -249,7 +232,6 @@ async def test_git_get_full_sha1_from_branch_name(git_repo):
assert p.stdout.decode().strip() == "a0ccc2390883c85a361f5a90c72e1b07958939fa"
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_full_hash(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -262,7 +244,6 @@ async def test_git_get_full_sha1_from_full_hash(git_repo):
assert p.stdout.decode().strip() == "c950fc05a540dd76b944719c2a3302da2e2f3090"
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_short_hash(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -273,7 +254,6 @@ async def test_git_get_full_sha1_from_short_hash(git_repo):
assert p.stdout.decode().strip() == "c950fc05a540dd76b944719c2a3302da2e2f3090"
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_too_short_hash(git_repo):
p = await git_repo._run(
ProcessFormatter().format(git_repo.GIT_GET_FULL_SHA1, path=git_repo.folder_path, rev="c95")
@ -282,7 +262,6 @@ async def test_git_get_full_sha1_from_too_short_hash(git_repo):
assert p.stderr.decode().strip() == "fatal: Needed a single revision"
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_lightweight_tag(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -293,7 +272,6 @@ async def test_git_get_full_sha1_from_lightweight_tag(git_repo):
assert p.stdout.decode().strip() == "fb99eb7d2d5bed514efc98fe6686b368f8425745"
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_annotated_tag(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -304,7 +282,6 @@ async def test_git_get_full_sha1_from_annotated_tag(git_repo):
assert p.stdout.decode().strip() == "a7120330cc179396914e0d6af80cfa282adc124b"
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_invalid_ref(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -318,7 +295,6 @@ async def test_git_get_full_sha1_from_invalid_ref(git_repo):
@pytest.mark.skipif(
GIT_VERSION < (2, 31), reason="This is test for output from Git 2.31 and newer."
)
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_ambiguous_commits(git_repo):
# 2 ambiguous refs:
# branch ambiguous_1 - 95da0b576271cb5bee5f3e075074c03ee05fed05
@ -341,7 +317,6 @@ async def test_git_get_full_sha1_from_ambiguous_commits(git_repo):
@pytest.mark.skipif(
GIT_VERSION < (2, 36), reason="This is test for output from Git 2.36 and newer."
)
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_ambiguous_tag_and_commit(git_repo):
# 2 ambiguous refs:
# branch ambiguous_with_tag - c6f0e5ec04d99bdf8c6c78ff20d66d286eecb3ea
@ -364,7 +339,6 @@ async def test_git_get_full_sha1_from_ambiguous_tag_and_commit(git_repo):
@pytest.mark.skipif(
not ((2, 31) <= GIT_VERSION < (2, 36)), reason="This is test for output from Git >=2.31,<2.36."
)
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_ambiguous_tag_and_commit_pre_2_36(git_repo):
# 2 ambiguous refs:
# branch ambiguous_with_tag - c6f0e5ec04d99bdf8c6c78ff20d66d286eecb3ea
@ -387,7 +361,6 @@ async def test_git_get_full_sha1_from_ambiguous_tag_and_commit_pre_2_36(git_repo
@pytest.mark.skipif(
GIT_VERSION >= (2, 31), reason="This is test for output from Git older than 2.31."
)
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_ambiguous_commits_pre_2_31(git_repo):
# 2 ambiguous refs:
# branch ambiguous_1 - 95da0b576271cb5bee5f3e075074c03ee05fed05
@ -410,7 +383,6 @@ async def test_git_get_full_sha1_from_ambiguous_commits_pre_2_31(git_repo):
@pytest.mark.skipif(
GIT_VERSION >= (2, 31), reason="This is test for output from Git older than 2.31."
)
@pytest.mark.asyncio
async def test_git_get_full_sha1_from_ambiguous_tag_and_commit_pre_2_31(git_repo):
# 2 ambiguous refs:
# branch ambiguous_with_tag - c6f0e5ec04d99bdf8c6c78ff20d66d286eecb3ea
@ -430,7 +402,6 @@ async def test_git_get_full_sha1_from_ambiguous_tag_and_commit_pre_2_31(git_repo
)
@pytest.mark.asyncio
async def test_git_is_ancestor_true(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -443,7 +414,6 @@ async def test_git_is_ancestor_true(git_repo):
assert p.returncode == 0
@pytest.mark.asyncio
async def test_git_is_ancestor_false(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -456,7 +426,6 @@ async def test_git_is_ancestor_false(git_repo):
assert p.returncode == 1
@pytest.mark.asyncio
async def test_git_is_ancestor_invalid_object(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -470,7 +439,6 @@ async def test_git_is_ancestor_invalid_object(git_repo):
assert p.stderr.decode().strip() == "fatal: Not a valid object name invalid1"
@pytest.mark.asyncio
async def test_git_is_ancestor_invalid_commit(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -486,7 +454,6 @@ async def test_git_is_ancestor_invalid_commit(git_repo):
)
@pytest.mark.asyncio
async def test_git_check_if_module_exists_true(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -502,7 +469,6 @@ async def test_git_check_if_module_exists_true(git_repo):
@pytest.mark.skipif(
GIT_VERSION < (2, 36), reason="This is test for output from Git 2.36 and newer."
)
@pytest.mark.asyncio
async def test_git_check_if_module_exists_false(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -521,7 +487,6 @@ async def test_git_check_if_module_exists_false(git_repo):
@pytest.mark.skipif(
GIT_VERSION >= (2, 36), reason="This is test for output from Git older than 2.31."
)
@pytest.mark.asyncio
async def test_git_check_if_module_exists_false_pre_2_36(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -537,7 +502,6 @@ async def test_git_check_if_module_exists_false_pre_2_36(git_repo):
)
@pytest.mark.asyncio
async def test_git_find_last_occurrence_existent(git_repo):
p = await git_repo._run(
ProcessFormatter().format(
@ -552,7 +516,6 @@ async def test_git_find_last_occurrence_existent(git_repo):
assert p.stdout.decode().strip() == "a7120330cc179396914e0d6af80cfa282adc124b"
@pytest.mark.asyncio
async def test_git_find_last_occurrence_non_existent(git_repo):
p = await git_repo._run(
ProcessFormatter().format(

View File

@ -7,12 +7,10 @@ def test_is_valid_alias_name(alias):
assert alias.is_valid_alias_name("not valid name") is False
@pytest.mark.asyncio
async def test_empty_guild_aliases(alias, empty_guild):
assert list(await alias._aliases.get_guild_aliases(empty_guild)) == []
@pytest.mark.asyncio
async def test_empty_global_aliases(alias):
assert list(await alias._aliases.get_global_aliases()) == []
@ -25,7 +23,6 @@ async def create_test_global_alias(alias, ctx):
await alias._aliases.add_alias(ctx, "test_global", "ping", global_=True)
@pytest.mark.asyncio
async def test_add_guild_alias(alias, ctx):
await create_test_guild_alias(alias, ctx)
@ -33,7 +30,6 @@ async def test_add_guild_alias(alias, ctx):
assert alias_obj.name == "test"
@pytest.mark.asyncio
async def test_delete_guild_alias(alias, ctx):
await create_test_guild_alias(alias, ctx)
alias_obj = await alias._aliases.get_alias(ctx.guild, "test")
@ -46,7 +42,6 @@ async def test_delete_guild_alias(alias, ctx):
assert alias_obj is None
@pytest.mark.asyncio
async def test_add_global_alias(alias, ctx):
await create_test_global_alias(alias, ctx)
alias_obj = await alias._aliases.get_alias(ctx.guild, "test_global")
@ -54,7 +49,6 @@ async def test_add_global_alias(alias, ctx):
assert alias_obj.name == "test_global"
@pytest.mark.asyncio
async def test_delete_global_alias(alias, ctx):
await create_test_global_alias(alias, ctx)
alias_obj = await alias._aliases.get_alias(ctx.guild, "test_global")

View File

@ -2,7 +2,6 @@ import pytest
from redbot.pytest.economy import *
@pytest.mark.asyncio
async def test_bank_register(bank, ctx):
default_bal = await bank.get_default_balance(ctx.guild)
assert default_bal == (await bank.get_account(ctx.author)).balance
@ -15,7 +14,6 @@ async def has_account(member, bank):
await bank.set_balance(member, balance)
@pytest.mark.asyncio
async def test_bank_transfer(bank, member_factory):
mbr1 = member_factory.get()
mbr2 = member_factory.get()
@ -28,7 +26,6 @@ async def test_bank_transfer(bank, member_factory):
assert bal2 + 50 == newbal2
@pytest.mark.asyncio
async def test_bank_set(bank, member_factory):
mbr = member_factory.get()
await bank.set_balance(mbr, 250)
@ -36,7 +33,6 @@ async def test_bank_set(bank, member_factory):
assert acc.balance == 250
@pytest.mark.asyncio
async def test_bank_can_spend(bank, member_factory):
mbr = member_factory.get()
canspend = await bank.can_spend(mbr, 50)
@ -47,7 +43,6 @@ async def test_bank_can_spend(bank, member_factory):
assert canspendnow
@pytest.mark.asyncio
async def test_set_bank_name(bank, guild_factory):
guild = guild_factory.get()
await bank.set_bank_name("Test Bank", guild)
@ -55,7 +50,6 @@ async def test_set_bank_name(bank, guild_factory):
assert name == "Test Bank"
@pytest.mark.asyncio
async def test_set_currency_name(bank, guild_factory):
guild = guild_factory.get()
await bank.set_currency_name("Coins", guild)
@ -63,7 +57,6 @@ async def test_set_currency_name(bank, guild_factory):
assert name == "Coins"
@pytest.mark.asyncio
async def test_set_default_balance(bank, guild_factory):
guild = guild_factory.get()
await bank.set_default_balance(500, guild)
@ -71,7 +64,6 @@ async def test_set_default_balance(bank, guild_factory):
assert default_bal == 500
@pytest.mark.asyncio
async def test_nonint_transaction_amount(bank, member_factory):
mbr1 = member_factory.get()
mbr2 = member_factory.get()

View File

@ -3,14 +3,12 @@ import pytest
from redbot.pytest.mod import *
@pytest.mark.asyncio
async def test_modlog_register_casetype(mod):
ct = {"name": "ban", "default_setting": True, "image": ":hammer:", "case_str": "Ban"}
casetype = await mod.register_casetype(**ct)
assert casetype is not None
@pytest.mark.asyncio
async def test_modlog_case_create(mod, ctx, member_factory):
from datetime import datetime, timezone
@ -33,7 +31,6 @@ async def test_modlog_case_create(mod, ctx, member_factory):
assert case.created_at == int(created_at.timestamp())
@pytest.mark.asyncio
async def test_modlog_set_modlog_channel(mod, ctx):
await mod.set_modlog_channel(ctx.guild, ctx.channel)
assert await mod.get_modlog_channel(ctx.guild) == ctx.channel.id

View File

@ -7,20 +7,17 @@ from redbot.core import cog_manager
@pytest.mark.skip
@pytest.mark.asyncio
async def test_ensure_cogs_in_paths(cog_mgr, default_dir):
cogs_dir = default_dir / "redbot" / "cogs"
assert cogs_dir in await cog_mgr.paths()
@pytest.mark.asyncio
async def test_install_path_set(cog_mgr: cog_manager.CogManager, tmpdir):
path = Path(str(tmpdir))
await cog_mgr.set_install_path(path)
assert await cog_mgr.install_path() == path
@pytest.mark.asyncio
async def test_install_path_set_bad(cog_mgr):
path = Path("something")
@ -28,14 +25,12 @@ async def test_install_path_set_bad(cog_mgr):
await cog_mgr.set_install_path(path)
@pytest.mark.asyncio
async def test_add_path(cog_mgr, tmpdir):
path = Path(str(tmpdir))
await cog_mgr.add_path(path)
assert path in await cog_mgr.paths()
@pytest.mark.asyncio
async def test_add_path_already_install_path(cog_mgr, tmpdir):
path = Path(str(tmpdir))
await cog_mgr.set_install_path(path)
@ -43,7 +38,6 @@ async def test_add_path_already_install_path(cog_mgr, tmpdir):
await cog_mgr.add_path(path)
@pytest.mark.asyncio
async def test_remove_path(cog_mgr, tmpdir):
path = Path(str(tmpdir))
await cog_mgr.add_path(path)

View File

@ -5,7 +5,6 @@ from collections import Counter
# region Register Tests
@pytest.mark.asyncio
async def test_config_register_global(config):
config.register_global(enabled=False)
assert config.defaults["GLOBAL"]["enabled"] is False
@ -17,7 +16,6 @@ def test_config_register_global_badvalues(config):
config.register_global(**{"invalid var name": True})
@pytest.mark.asyncio
async def test_config_register_guild(config, empty_guild):
config.register_guild(enabled=False, some_list=[], some_dict={})
assert config.defaults[config.GUILD]["enabled"] is False
@ -29,35 +27,30 @@ async def test_config_register_guild(config, empty_guild):
assert await config.guild(empty_guild).some_dict() == {}
@pytest.mark.asyncio
async def test_config_register_channel(config, empty_channel):
config.register_channel(enabled=False)
assert config.defaults[config.CHANNEL]["enabled"] is False
assert await config.channel(empty_channel).enabled() is False
@pytest.mark.asyncio
async def test_config_register_role(config, empty_role):
config.register_role(enabled=False)
assert config.defaults[config.ROLE]["enabled"] is False
assert await config.role(empty_role).enabled() is False
@pytest.mark.asyncio
async def test_config_register_member(config, empty_member):
config.register_member(some_number=-1)
assert config.defaults[config.MEMBER]["some_number"] == -1
assert await config.member(empty_member).some_number() == -1
@pytest.mark.asyncio
async def test_config_register_user(config, empty_user):
config.register_user(some_value=None)
assert config.defaults[config.USER]["some_value"] is None
assert await config.user(empty_user).some_value() is None
@pytest.mark.asyncio
async def test_config_force_register_global(config_fr):
with pytest.raises(AttributeError):
await config_fr.enabled()
@ -70,13 +63,11 @@ async def test_config_force_register_global(config_fr):
# Test nested registration
@pytest.mark.asyncio
async def test_nested_registration(config):
config.register_global(foo__bar__baz=False)
assert await config.foo.bar.baz() is False
@pytest.mark.asyncio
async def test_nested_registration_asdict(config):
defaults = {"bar": {"baz": False}}
config.register_global(foo=defaults)
@ -84,7 +75,6 @@ async def test_nested_registration_asdict(config):
assert await config.foo.bar.baz() is False
@pytest.mark.asyncio
async def test_nested_registration_and_changing(config):
defaults = {"bar": {"baz": False}}
config.register_global(foo=defaults)
@ -95,7 +85,6 @@ async def test_nested_registration_and_changing(config):
await config.foo.set(True)
@pytest.mark.asyncio
async def test_doubleset_default(config):
config.register_global(foo=True)
config.register_global(foo=False)
@ -103,7 +92,6 @@ async def test_doubleset_default(config):
assert await config.foo() is False
@pytest.mark.asyncio
async def test_nested_registration_multidict(config):
defaults = {"foo": {"bar": {"baz": True}}, "blah": True}
config.register_global(**defaults)
@ -118,7 +106,6 @@ def test_nested_group_value_badreg(config):
config.register_global(foo__bar=False)
@pytest.mark.asyncio
async def test_nested_toplevel_reg(config):
defaults = {"bar": True, "baz": False}
config.register_global(foo=defaults)
@ -127,7 +114,6 @@ async def test_nested_toplevel_reg(config):
assert await config.foo.baz() is False
@pytest.mark.asyncio
async def test_nested_overlapping(config):
config.register_global(foo__bar=True)
config.register_global(foo__baz=False)
@ -136,7 +122,6 @@ async def test_nested_overlapping(config):
assert await config.foo.baz() is False
@pytest.mark.asyncio
async def test_nesting_nofr(config):
config.register_global(foo={})
assert await config.foo.bar() is None
@ -144,38 +129,31 @@ async def test_nesting_nofr(config):
# region Default Value Overrides
@pytest.mark.asyncio
async def test_global_default_override(config):
assert await config.enabled(True) is True
@pytest.mark.asyncio
async def test_global_default_nofr(config):
assert await config.nofr() is None
assert await config.nofr(True) is True
@pytest.mark.asyncio
async def test_guild_default_override(config, empty_guild):
assert await config.guild(empty_guild).enabled(True) is True
@pytest.mark.asyncio
async def test_channel_default_override(config, empty_channel):
assert await config.channel(empty_channel).enabled(True) is True
@pytest.mark.asyncio
async def test_role_default_override(config, empty_role):
assert await config.role(empty_role).enabled(True) is True
@pytest.mark.asyncio
async def test_member_default_override(config, empty_member):
assert await config.member(empty_member).enabled(True) is True
@pytest.mark.asyncio
async def test_user_default_override(config, empty_user):
assert await config.user(empty_user).some_value(True) is True
@ -184,13 +162,11 @@ async def test_user_default_override(config, empty_user):
# region Setting Values
@pytest.mark.asyncio
async def test_set_global(config):
await config.enabled.set(True)
assert await config.enabled() is True
@pytest.mark.asyncio
async def test_set_guild(config, empty_guild):
await config.guild(empty_guild).enabled.set(True)
assert await config.guild(empty_guild).enabled() is True
@ -203,13 +179,11 @@ async def test_set_guild(config, empty_guild):
assert await config.guild(empty_guild).some_list() == curr_list
@pytest.mark.asyncio
async def test_set_channel(config, empty_channel):
await config.channel(empty_channel).enabled.set(True)
assert await config.channel(empty_channel).enabled() is True
@pytest.mark.asyncio
async def test_set_channel_no_register(config, empty_channel):
await config.channel(empty_channel).no_register.set(True)
assert await config.channel(empty_channel).no_register() is True
@ -219,14 +193,12 @@ async def test_set_channel_no_register(config, empty_channel):
# Dynamic attribute testing
@pytest.mark.asyncio
async def test_set_dynamic_attr(config):
await config.set_raw("foobar", value=True)
assert await config.foobar() is True
@pytest.mark.asyncio
async def test_clear_dynamic_attr(config):
await config.foo.set(True)
await config.clear_raw("foo")
@ -235,13 +207,11 @@ async def test_clear_dynamic_attr(config):
await config.get_raw("foo")
@pytest.mark.asyncio
async def test_get_dynamic_attr(config):
assert await config.get_raw("foobaz", default=True) is True
# Member Group testing
@pytest.mark.asyncio
async def test_membergroup_allguilds(config, empty_member):
await config.member(empty_member).foo.set(False)
@ -249,7 +219,6 @@ async def test_membergroup_allguilds(config, empty_member):
assert empty_member.guild.id in all_servers
@pytest.mark.asyncio
async def test_membergroup_allmembers(config, empty_member):
await config.member(empty_member).foo.set(False)
@ -258,7 +227,6 @@ async def test_membergroup_allmembers(config, empty_member):
# Clearing testing
@pytest.mark.asyncio
async def test_global_clear(config):
config.register_global(foo=True, bar=False)
@ -274,7 +242,6 @@ async def test_global_clear(config):
assert await config.bar() is False
@pytest.mark.asyncio
async def test_member_clear(config, member_factory):
config.register_member(foo=True)
@ -293,7 +260,6 @@ async def test_member_clear(config, member_factory):
assert await config.member(m2).foo() is False
@pytest.mark.asyncio
async def test_member_clear_all(config, member_factory):
server_ids = []
for _ in range(5):
@ -309,7 +275,6 @@ async def test_member_clear_all(config, member_factory):
assert len(await config.all_members()) == 0
@pytest.mark.asyncio
async def test_clear_all(config):
await config.foo.set(True)
assert await config.foo() is True
@ -319,7 +284,6 @@ async def test_clear_all(config):
await config.get_raw("foo")
@pytest.mark.asyncio
async def test_clear_value(config):
await config.foo.set(True)
await config.foo.clear()
@ -329,7 +293,6 @@ async def test_clear_value(config):
# Get All testing
@pytest.mark.asyncio
async def test_user_get_all_from_kind(config, user_factory):
config.register_user(foo=False, bar=True)
for _ in range(5):
@ -345,7 +308,6 @@ async def test_user_get_all_from_kind(config, user_factory):
assert v["bar"] is True
@pytest.mark.asyncio
async def test_user_getalldata(config, user_factory):
user = user_factory.get()
config.register_user(foo=True, bar=False)
@ -359,7 +321,6 @@ async def test_user_getalldata(config, user_factory):
assert config.user(user).defaults["foo"] is True
@pytest.mark.asyncio
async def test_value_ctxmgr(config):
config.register_global(foo_list=[])
@ -371,7 +332,6 @@ async def test_value_ctxmgr(config):
assert "foo" in foo_list
@pytest.mark.asyncio
async def test_value_ctxmgr_saves(config):
config.register_global(bar_list=[])
@ -387,7 +347,6 @@ async def test_value_ctxmgr_saves(config):
assert "bar" in bar_list
@pytest.mark.asyncio
async def test_value_ctxmgr_immutable(config):
config.register_global(foo=True)
@ -399,7 +358,6 @@ async def test_value_ctxmgr_immutable(config):
assert foo is True
@pytest.mark.asyncio
async def test_ctxmgr_no_shared_default(config, member_factory):
config.register_member(foo=[])
m1 = member_factory.get()
@ -411,7 +369,6 @@ async def test_ctxmgr_no_shared_default(config, member_factory):
assert 1 not in await config.member(m2).foo()
@pytest.mark.asyncio
async def test_ctxmgr_no_unnecessary_write(config):
config.register_global(foo=[])
foo_value_obj = config.foo
@ -421,7 +378,6 @@ async def test_ctxmgr_no_unnecessary_write(config):
set_method.assert_not_called()
@pytest.mark.asyncio
async def test_get_then_mutate(config):
"""Tests that mutating an object after getting it as a value doesn't mutate the data store."""
config.register_global(list1=[])
@ -432,7 +388,6 @@ async def test_get_then_mutate(config):
assert "foo" not in list1
@pytest.mark.asyncio
async def test_set_then_mutate(config):
"""Tests that mutating an object after setting it as a value doesn't mutate the data store."""
config.register_global(list1=[])
@ -443,14 +398,12 @@ async def test_set_then_mutate(config):
assert "foo" not in list1
@pytest.mark.asyncio
async def test_call_group_fills_defaults(config):
config.register_global(subgroup={"foo": True})
subgroup = await config.subgroup()
assert "foo" in subgroup
@pytest.mark.asyncio
async def test_group_call_ctxmgr_writes(config):
config.register_global(subgroup={"foo": True})
async with config.subgroup() as subgroup:
@ -460,7 +413,6 @@ async def test_group_call_ctxmgr_writes(config):
assert subgroup == {"foo": True, "bar": False}
@pytest.mark.asyncio
async def test_all_works_as_ctxmgr(config):
config.register_global(subgroup={"foo": True})
async with config.subgroup.all() as subgroup:
@ -470,7 +422,6 @@ async def test_all_works_as_ctxmgr(config):
assert subgroup == {"foo": True, "bar": False}
@pytest.mark.asyncio
async def test_get_raw_mixes_defaults(config):
config.register_global(subgroup={"foo": True})
await config.subgroup.set_raw("bar", value=False)
@ -479,7 +430,6 @@ async def test_get_raw_mixes_defaults(config):
assert subgroup == {"foo": True, "bar": False}
@pytest.mark.asyncio
async def test_cast_str_raw(config):
await config.set_raw(123, 456, value=True)
assert await config.get_raw(123, 456) is True
@ -487,7 +437,6 @@ async def test_cast_str_raw(config):
await config.clear_raw("123", 456)
@pytest.mark.asyncio
async def test_cast_str_nested(config):
config.register_global(foo={})
await config.foo.set({123: True, 456: {789: False}})
@ -510,7 +459,6 @@ def test_config_custom_doubleinit(config):
config.init_custom("TEST", 2)
@pytest.mark.asyncio
async def test_config_locks_cache(config, empty_guild):
lock1 = config.foo.get_lock()
assert lock1 is config.foo.get_lock()
@ -519,7 +467,6 @@ async def test_config_locks_cache(config, empty_guild):
assert lock1 is not lock2
@pytest.mark.asyncio
async def test_config_value_atomicity(config):
config.register_global(foo=[])
tasks = []
@ -539,7 +486,6 @@ async def test_config_value_atomicity(config):
assert len(await config.foo()) == 15
@pytest.mark.asyncio
async def test_config_ctxmgr_atomicity(config):
config.register_global(foo=[])
tasks = []
@ -557,7 +503,6 @@ async def test_config_ctxmgr_atomicity(config):
assert len(await config.foo()) == 15
@pytest.mark.asyncio
async def test_set_with_partial_primary_keys(config):
config.init_custom("CUSTOM", 3)
await config.custom("CUSTOM", "1").set({"11": {"111": {"foo": "bar"}}})
@ -585,7 +530,6 @@ async def test_set_with_partial_primary_keys(config):
assert await config.custom("CUSTOM", "2", "33", "222").foo() == "biz"
@pytest.mark.asyncio
async def test_raw_with_partial_primary_keys(config):
config.init_custom("CUSTOM", 1)
await config.custom("CUSTOM").set_raw("primary_key", "identifier", value=True)
@ -654,7 +598,6 @@ PARAMS = [
@pytest.mark.parametrize("pkeys, raw_args, result", PARAMS)
@pytest.mark.asyncio
async def test_config_custom_partial_pkeys_get(config, pkeys, raw_args, result):
# setup
config.init_custom("TEST", 3)
@ -666,7 +609,6 @@ async def test_config_custom_partial_pkeys_get(config, pkeys, raw_args, result):
@pytest.mark.parametrize("pkeys, raw_args, result", PARAMS)
@pytest.mark.asyncio
async def test_config_custom_partial_pkeys_set(config, pkeys, raw_args, result):
# setup
config.init_custom("TEST", 3)

View File

@ -1,6 +1,5 @@
import pytest
@pytest.mark.asyncio
async def test_can_init_bot(red):
assert red is not None

View File

@ -15,7 +15,6 @@ def test_deduplicate_iterables():
assert deduplicate_iterables(*inputs) == expected
@pytest.mark.asyncio
async def test_bounded_gather():
status = [0, 0] # num_running, max_running
@ -52,7 +51,6 @@ async def test_bounded_gather():
assert num_fail == num_failed
@pytest.mark.asyncio
async def test_bounded_gather_iter():
status = [0, 0] # num_running, max_running
@ -91,7 +89,6 @@ async def test_bounded_gather_iter():
@pytest.mark.skip(reason="spams logs with pending task warnings")
@pytest.mark.asyncio
async def test_bounded_gather_iter_cancel():
status = [0, 0, 0] # num_running, max_running, num_ran

View File

@ -73,7 +73,7 @@ def test_python_version_has_lower_bound():
@pytest.mark.skipif(
os.getenv("TOX_RED", False) and sys.version_info >= (3, 10),
os.getenv("TOX_RED", False) and sys.version_info >= (3, 12),
reason="Testing on yet to be supported Python version.",
)
def test_python_version_has_upper_bound():

View File

@ -1,2 +1,2 @@
tox<4
tox
-e .[dev]

11
tox.ini
View File

@ -7,14 +7,15 @@
envlist =
py38
py39
py310
py311
docs
style
skip_missing_interpreters = True
isolated_build = True
[testenv]
description = Run tests and basic automatic issue checking.
whitelist_externals =
allowlist_externals =
pytest
pylint
extras = test
@ -27,7 +28,7 @@ commands =
[testenv:postgres]
description = Run pytest with PostgreSQL backend
whitelist_externals =
allowlist_externals =
pytest
extras = test, postgres
setenv =
@ -46,7 +47,7 @@ commands =
[testenv:docs]
description = Attempt to build docs with sphinx-build
whitelist_externals =
allowlist_externals =
sphinx-build
make
setenv =
@ -61,7 +62,7 @@ commands =
[testenv:style]
description = Stylecheck the code with black to see if anything needs changes.
whitelist_externals =
allowlist_externals =
make
setenv =
# This is just for Windows