mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 11:18:54 -05:00
* PostgreSQL driver and general drivers cleanup Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Make tests pass Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Add black --target-version flag in make.bat Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Rewrite postgres driver Most of the logic is now in PL/pgSQL. This completely avoids the use of Python f-strings to format identifiers into queries. Although an SQL-injection attack would have been impossible anyway (only the owner would have ever had the ability to do that), using PostgreSQL's format() is more reliable for unusual identifiers. Performance-wise, I'm not sure whether this is an improvement, but I highly doubt that it's worse. Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Reformat Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Fix PostgresDriver.delete_all_data() Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Clean up PL/pgSQL code Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * More PL/pgSQL cleanup Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * PL/pgSQL function optimisations Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Ensure compatibility with PostgreSQL 10 and below Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * More/better docstrings for PG functions Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Fix typo in docstring Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Return correct value on toggle() Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Use composite type for PG function parameters Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Fix JSON driver's Config.clear_all() Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Correct description for Mongo tox recipe Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Fix linting errors Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Update dep specification after merging bumpdeps Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Add towncrier entries Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Update from merge Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Mention [postgres] extra in install docs Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Support more connection options and use better defaults Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Actually pass PG env vars in tox Signed-off-by: Toby Harradine <tobyharradine@gmail.com> * Replace event trigger with manual DELETE queries Signed-off-by: Toby Harradine <tobyharradine@gmail.com>
180 lines
3.9 KiB
Python
180 lines
3.9 KiB
Python
import random
|
|
from collections import namedtuple
|
|
from pathlib import Path
|
|
import weakref
|
|
|
|
import pytest
|
|
from _pytest.monkeypatch import MonkeyPatch
|
|
from redbot.core import Config
|
|
from redbot.core.bot import Red
|
|
from redbot.core import config as config_module, drivers
|
|
|
|
__all__ = [
|
|
"monkeysession",
|
|
"override_data_path",
|
|
"coroutine",
|
|
"driver",
|
|
"config",
|
|
"config_fr",
|
|
"red",
|
|
"guild_factory",
|
|
"empty_guild",
|
|
"empty_channel",
|
|
"empty_member",
|
|
"empty_message",
|
|
"empty_role",
|
|
"empty_user",
|
|
"member_factory",
|
|
"user_factory",
|
|
"ctx",
|
|
]
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def monkeysession(request):
|
|
mpatch = MonkeyPatch()
|
|
yield mpatch
|
|
mpatch.undo()
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def override_data_path(tmpdir):
|
|
from redbot.core import data_manager
|
|
|
|
data_manager.basic_config = data_manager.basic_config_default
|
|
data_manager.basic_config["DATA_PATH"] = str(tmpdir)
|
|
|
|
|
|
@pytest.fixture()
|
|
def coroutine():
|
|
async def some_coro(*args, **kwargs):
|
|
return args, kwargs
|
|
|
|
return some_coro
|
|
|
|
|
|
@pytest.fixture()
|
|
def driver(tmpdir_factory):
|
|
import uuid
|
|
|
|
rand = str(uuid.uuid4())
|
|
path = Path(str(tmpdir_factory.mktemp(rand)))
|
|
return drivers.get_driver("PyTest", str(random.randint(1, 999999)), data_path_override=path)
|
|
|
|
|
|
@pytest.fixture()
|
|
def config(driver):
|
|
config_module._config_cache = weakref.WeakValueDictionary()
|
|
conf = Config(cog_name="PyTest", unique_identifier=driver.unique_cog_identifier, driver=driver)
|
|
yield conf
|
|
|
|
|
|
@pytest.fixture()
|
|
def config_fr(driver):
|
|
"""
|
|
Mocked config object with force_register enabled.
|
|
"""
|
|
config_module._config_cache = weakref.WeakValueDictionary()
|
|
conf = Config(
|
|
cog_name="PyTest",
|
|
unique_identifier=driver.unique_cog_identifier,
|
|
driver=driver,
|
|
force_registration=True,
|
|
)
|
|
yield conf
|
|
|
|
|
|
# region Dpy Mocks
|
|
@pytest.fixture()
|
|
def guild_factory():
|
|
mock_guild = namedtuple("Guild", "id members")
|
|
|
|
class GuildFactory:
|
|
def get(self):
|
|
return mock_guild(random.randint(1, 999999999), [])
|
|
|
|
return GuildFactory()
|
|
|
|
|
|
@pytest.fixture()
|
|
def empty_guild(guild_factory):
|
|
return guild_factory.get()
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def empty_channel():
|
|
mock_channel = namedtuple("Channel", "id")
|
|
return mock_channel(random.randint(1, 999999999))
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def empty_role():
|
|
mock_role = namedtuple("Role", "id")
|
|
return mock_role(random.randint(1, 999999999))
|
|
|
|
|
|
@pytest.fixture()
|
|
def member_factory(guild_factory):
|
|
mock_member = namedtuple("Member", "id guild display_name")
|
|
|
|
class MemberFactory:
|
|
def get(self):
|
|
return mock_member(random.randint(1, 999999999), guild_factory.get(), "Testing_Name")
|
|
|
|
return MemberFactory()
|
|
|
|
|
|
@pytest.fixture()
|
|
def empty_member(member_factory):
|
|
return member_factory.get()
|
|
|
|
|
|
@pytest.fixture()
|
|
def user_factory():
|
|
mock_user = namedtuple("User", "id")
|
|
|
|
class UserFactory:
|
|
def get(self):
|
|
return mock_user(random.randint(1, 999999999))
|
|
|
|
return UserFactory()
|
|
|
|
|
|
@pytest.fixture()
|
|
def empty_user(user_factory):
|
|
return user_factory.get()
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def empty_message():
|
|
mock_msg = namedtuple("Message", "content")
|
|
return mock_msg("No content.")
|
|
|
|
|
|
@pytest.fixture()
|
|
def ctx(empty_member, empty_channel, red):
|
|
mock_ctx = namedtuple("Context", "author guild channel message bot")
|
|
return mock_ctx(empty_member, empty_member.guild, empty_channel, empty_message, red)
|
|
|
|
|
|
# endregion
|
|
|
|
|
|
# region Red Mock
|
|
@pytest.fixture()
|
|
def red(config_fr):
|
|
from redbot.core.cli import parse_cli_flags
|
|
|
|
cli_flags = parse_cli_flags(["ignore_me"])
|
|
|
|
description = "Red v3 - Alpha"
|
|
|
|
Config.get_core_conf = lambda *args, **kwargs: config_fr
|
|
|
|
red = Red(cli_flags=cli_flags, description=description, dm_help=None, owner_id=None)
|
|
|
|
yield red
|
|
|
|
|
|
# endregion
|