mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
[V3 Config] Redesign "all_from_XXX" and "clear_all" methods (#1033)
* Added alternative to all_from_kind * Returned dicts include default values Also added docstrings Also removed all_globals since it's kind of redundant and it wasn't working out for me * Refactored clear_all * Tests * Tests again.. * Make all new methods coroutines
This commit is contained in:
parent
13fef45e06
commit
815678584f
@ -63,7 +63,7 @@ class Bank:
|
||||
If the bank is global, it will become per-guild
|
||||
If the bank is per-guild, it will become global"""
|
||||
cur_setting = await bank.is_global()
|
||||
await bank.set_global(not cur_setting, ctx.author)
|
||||
await bank.set_global(not cur_setting)
|
||||
|
||||
word = _("per-guild") if cur_setting else _("global")
|
||||
|
||||
|
||||
@ -322,7 +322,7 @@ async def get_guild_accounts(guild: discord.Guild) -> List[Account]:
|
||||
raise RuntimeError("The bank is currently global.")
|
||||
|
||||
ret = []
|
||||
accs = await _conf.member(guild.owner).all_from_kind()
|
||||
accs = await _conf.all_members(guild)
|
||||
for user_id, acc in accs.items():
|
||||
acc_data = acc.copy() # There ya go kowlin
|
||||
acc_data['created_at'] = _decode_time(acc_data['created_at'])
|
||||
@ -353,7 +353,7 @@ async def get_global_accounts(user: discord.User) -> List[Account]:
|
||||
raise RuntimeError("The bank is not currently global.")
|
||||
|
||||
ret = []
|
||||
accs = await _conf.user(user).all_from_kind() # this is a dict of user -> acc
|
||||
accs = await _conf.all_users() # this is a dict of user -> acc
|
||||
for user_id, acc in accs.items():
|
||||
acc_data = acc.copy()
|
||||
acc_data['created_at'] = _decode_time(acc_data['created_at'])
|
||||
@ -412,8 +412,6 @@ async def is_global() -> bool:
|
||||
async def set_global(global_: bool, user: Union[discord.User, discord.Member]) -> bool:
|
||||
"""Set global status of the bank.
|
||||
|
||||
Requires the user parameter for technical reasons.
|
||||
|
||||
.. important::
|
||||
|
||||
All accounts are reset when you switch!
|
||||
@ -422,8 +420,6 @@ async def set_global(global_: bool, user: Union[discord.User, discord.Member]) -
|
||||
----------
|
||||
global_ : bool
|
||||
:code:`True` will set bank to global mode.
|
||||
user : `discord.User` or `discord.Member`
|
||||
Must be a Member object if changing TO global mode.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@ -440,12 +436,9 @@ async def set_global(global_: bool, user: Union[discord.User, discord.Member]) -
|
||||
return global_
|
||||
|
||||
if is_global():
|
||||
await _conf.user(user).clear_all()
|
||||
elif isinstance(user, discord.Member):
|
||||
await _conf.member(user).clear_all()
|
||||
await _conf.clear_all_users()
|
||||
else:
|
||||
raise RuntimeError("You must provide a member if you're changing to global"
|
||||
" bank mode.")
|
||||
await _conf.clear_all_members()
|
||||
|
||||
await _conf.is_global.set(global_)
|
||||
return global_
|
||||
|
||||
@ -292,36 +292,6 @@ class Group(Value):
|
||||
defaults.update(await self())
|
||||
return defaults
|
||||
|
||||
async def all_from_kind(self) -> dict:
|
||||
"""Get all data from this group and its siblings.
|
||||
|
||||
.. important::
|
||||
|
||||
This method is overridden in `MemberGroup.all_from_kind` and
|
||||
functions slightly differently.
|
||||
|
||||
Note
|
||||
----
|
||||
The return value of this method will include registered defaults
|
||||
for groups which have not had their values set.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
A dict of :code:`ID -> data`, with the data being a dict
|
||||
of the group's raw values.
|
||||
|
||||
"""
|
||||
# noinspection PyTypeChecker
|
||||
all_from_kind = await self._super_group()
|
||||
|
||||
for k, v in all_from_kind.items():
|
||||
defaults = self.defaults
|
||||
defaults.update(v)
|
||||
all_from_kind[k] = defaults
|
||||
|
||||
return all_from_kind
|
||||
|
||||
async def set(self, value):
|
||||
if not isinstance(value, dict):
|
||||
raise ValueError(
|
||||
@ -358,13 +328,6 @@ class Group(Value):
|
||||
"""
|
||||
await self.set({})
|
||||
|
||||
async def clear_all(self):
|
||||
"""Wipe all data from this group and its siblings.
|
||||
|
||||
If used on a global group, this method wipes all data from all groups.
|
||||
"""
|
||||
await self._super_group.set({})
|
||||
|
||||
|
||||
class MemberGroup(Group):
|
||||
"""A specific group class for use with member data only.
|
||||
@ -392,41 +355,6 @@ class MemberGroup(Group):
|
||||
)
|
||||
return group_obj
|
||||
|
||||
async def all_guilds(self) -> dict:
|
||||
"""Get a dict of :code:`GUILD_ID -> MEMBER_ID -> data`.
|
||||
|
||||
Note
|
||||
----
|
||||
The return value of this method will include registered defaults
|
||||
for groups which have not had their values set.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
A dict of data from all members from all guilds.
|
||||
|
||||
"""
|
||||
# noinspection PyTypeChecker
|
||||
return await super().all_from_kind()
|
||||
|
||||
async def all_from_kind(self) -> dict:
|
||||
"""Get a dict of all members from the same guild as the given one.
|
||||
|
||||
Note
|
||||
----
|
||||
The return value of this method will include registered defaults
|
||||
for groups which have not had their values set.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
A dict of :code:`MEMBER_ID -> data`.
|
||||
|
||||
"""
|
||||
guild_member = await super().all_from_kind()
|
||||
return guild_member.get(self.identifiers[-2], {})
|
||||
|
||||
|
||||
|
||||
class Config:
|
||||
"""Configuration manager for cogs and Red.
|
||||
@ -519,11 +447,13 @@ class Config:
|
||||
|
||||
@classmethod
|
||||
def get_core_conf(cls, force_registration: bool=False):
|
||||
"""All core modules that require a config instance should use this
|
||||
"""Get a Config instance for a core module.
|
||||
|
||||
All core modules that require a config instance should use this
|
||||
classmethod instead of `get_conf`.
|
||||
|
||||
identifier : int
|
||||
See `get_conf`.
|
||||
Parameters
|
||||
----------
|
||||
force_registration : `bool`, optional
|
||||
See `force_registration`.
|
||||
|
||||
@ -765,3 +695,226 @@ class Config:
|
||||
return self._get_base_group(self.MEMBER, member.guild.id, member.id,
|
||||
group_class=MemberGroup)
|
||||
|
||||
async def _all_from_scope(self, scope: str):
|
||||
"""Get a dict of all values from a particular scope of data.
|
||||
|
||||
:code:`scope` must be one of the constants attributed to
|
||||
this class, i.e. :code:`GUILD`, :code:`MEMBER` et cetera.
|
||||
|
||||
IDs as keys in the returned dict are casted to `int` for convenience.
|
||||
|
||||
Default values are also mixed into the data if they have not yet been
|
||||
overwritten.
|
||||
"""
|
||||
group = self._get_base_group(scope)
|
||||
dict_ = await group()
|
||||
ret = {}
|
||||
for k, v in dict_.items():
|
||||
data = group.defaults
|
||||
data.update(v)
|
||||
ret[int(k)] = data
|
||||
return ret
|
||||
|
||||
async def all_guilds(self) -> dict:
|
||||
"""Get all guild data as a dict.
|
||||
|
||||
Note
|
||||
----
|
||||
The return value of this method will include registered defaults for
|
||||
values which have not yet been set.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
A dictionary in the form {`int`: `dict`} mapping
|
||||
:code:`GUILD_ID -> data`.
|
||||
|
||||
"""
|
||||
return await self._all_from_scope(self.GUILD)
|
||||
|
||||
async def all_channels(self) -> dict:
|
||||
"""Get all channel data as a dict.
|
||||
|
||||
Note
|
||||
----
|
||||
The return value of this method will include registered defaults for
|
||||
values which have not yet been set.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
A dictionary in the form {`int`: `dict`} mapping
|
||||
:code:`CHANNEL_ID -> data`.
|
||||
|
||||
"""
|
||||
return await self._all_from_scope(self.CHANNEL)
|
||||
|
||||
async def all_roles(self) -> dict:
|
||||
"""Get all role data as a dict.
|
||||
|
||||
Note
|
||||
----
|
||||
The return value of this method will include registered defaults for
|
||||
values which have not yet been set.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
A dictionary in the form {`int`: `dict`} mapping
|
||||
:code:`ROLE_ID -> data`.
|
||||
|
||||
"""
|
||||
return await self._all_from_scope(self.ROLE)
|
||||
|
||||
async def all_users(self) -> dict:
|
||||
"""Get all user data as a dict.
|
||||
|
||||
Note
|
||||
----
|
||||
The return value of this method will include registered defaults for
|
||||
values which have not yet been set.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
A dictionary in the form {`int`: `dict`} mapping
|
||||
:code:`USER_ID -> data`.
|
||||
|
||||
"""
|
||||
return await self._all_from_scope(self.USER)
|
||||
|
||||
def _all_members_from_guild(self, group: Group, guild_data: dict) -> dict:
|
||||
ret = {}
|
||||
for member_id, member_data in guild_data.items():
|
||||
new_member_data = group.defaults
|
||||
new_member_data.update(member_data)
|
||||
ret[int(member_id)] = new_member_data
|
||||
return ret
|
||||
|
||||
async def all_members(self, guild: discord.Guild=None) -> dict:
|
||||
"""Get data for all members.
|
||||
|
||||
If :code:`guild` is specified, only the data for the members of that
|
||||
guild will be returned. As such, the dict will map
|
||||
:code:`MEMBER_ID -> data`. Otherwise, the dict maps
|
||||
:code:`GUILD_ID -> MEMBER_ID -> data`.
|
||||
|
||||
Note
|
||||
----
|
||||
The return value of this method will include registered defaults for
|
||||
values which have not yet been set.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
guild : `discord.Guild`, optional
|
||||
The guild to get the member data from. Can be omitted if data
|
||||
from every member of all guilds is desired.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
A dictionary of all specified member data.
|
||||
|
||||
"""
|
||||
ret = {}
|
||||
if guild is None:
|
||||
group = self._get_base_group(self.MEMBER)
|
||||
dict_ = await group()
|
||||
for guild_id, guild_data in dict_.items():
|
||||
ret[int(guild_id)] = self._all_members_from_guild(
|
||||
group, guild_data)
|
||||
else:
|
||||
group = self._get_base_group(self.MEMBER, guild.id)
|
||||
guild_data = await group()
|
||||
ret = self._all_members_from_guild(group, guild_data)
|
||||
return ret
|
||||
|
||||
async def _clear_scope(self, *scopes: str):
|
||||
"""Clear all data in a particular scope.
|
||||
|
||||
The only situation where a second scope should be passed in is if
|
||||
member data from a specific guild is being cleared.
|
||||
|
||||
If no scopes are passed, then all data is cleared from every scope.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
*scopes : str, optional
|
||||
The scope of the data. Generally only one scope needs to be
|
||||
provided, a second only necessary for clearing member data
|
||||
of a specific guild.
|
||||
|
||||
**Leaving blank removes all data from this Config instance.**
|
||||
|
||||
"""
|
||||
if not scopes:
|
||||
group = Group(identifiers=(self.unique_identifier),
|
||||
defaults={},
|
||||
spawner=self.spawner)
|
||||
else:
|
||||
group = self._get_base_group(*scopes)
|
||||
await group.set({})
|
||||
|
||||
async def clear_all(self):
|
||||
"""Clear all data from this Config instance.
|
||||
|
||||
This resets all data to its registered defaults.
|
||||
|
||||
.. important::
|
||||
|
||||
This cannot be undone.
|
||||
|
||||
"""
|
||||
await self._clear_scope()
|
||||
|
||||
async def clear_all_globals(self):
|
||||
"""Clear all global data.
|
||||
|
||||
This resets all global data to its registered defaults.
|
||||
"""
|
||||
await self._clear_scope(self.GLOBAL)
|
||||
|
||||
async def clear_all_guilds(self):
|
||||
"""Clear all guild data.
|
||||
|
||||
This resets all guild data to its registered defaults.
|
||||
"""
|
||||
await self._clear_scope(self.GUILD)
|
||||
|
||||
async def clear_all_channels(self):
|
||||
"""Clear all channel data.
|
||||
|
||||
This resets all channel data to its registered defaults.
|
||||
"""
|
||||
await self._clear_scope(self.CHANNEL)
|
||||
|
||||
async def clear_all_roles(self):
|
||||
"""Clear all role data.
|
||||
|
||||
This resets all role data to its registered defaults.
|
||||
"""
|
||||
await self._clear_scope(self.ROLE)
|
||||
|
||||
async def clear_all_users(self):
|
||||
"""Clear all user data.
|
||||
|
||||
This resets all user data to its registered defaults.
|
||||
"""
|
||||
await self._clear_scope(self.USER)
|
||||
|
||||
async def clear_all_members(self, guild: discord.Guild=None):
|
||||
"""Clear all member data.
|
||||
|
||||
This resets all specified member data to its registered defaults.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
guild : `discord.Guild`, optional
|
||||
The guild to clear member data from. Omit to clear member data from
|
||||
all guilds.
|
||||
|
||||
"""
|
||||
if guild is not None:
|
||||
await self._clear_scope(self.MEMBER, guild.id)
|
||||
return
|
||||
await self._clear_scope(self.MEMBER)
|
||||
|
||||
@ -234,16 +234,16 @@ async def test_get_dynamic_attr(config):
|
||||
async def test_membergroup_allguilds(config, empty_member):
|
||||
await config.member(empty_member).foo.set(False)
|
||||
|
||||
all_servers = await config.member(empty_member).all_guilds()
|
||||
assert str(empty_member.guild.id) in all_servers
|
||||
all_servers = await config.all_members()
|
||||
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)
|
||||
|
||||
all_members = await config.member(empty_member).all_from_kind()
|
||||
assert str(empty_member.id) in all_members
|
||||
all_members = await config.all_members(empty_member.guild)
|
||||
assert empty_member.id in all_members
|
||||
|
||||
|
||||
# Clearing testing
|
||||
@ -291,11 +291,11 @@ async def test_member_clear_all(config, member_factory):
|
||||
server_ids.append(member.guild.id)
|
||||
|
||||
member = member_factory.get()
|
||||
assert len(await config.member(member).all_guilds()) == len(server_ids)
|
||||
assert len(await config.all_members()) == len(server_ids)
|
||||
|
||||
await config.member(member).clear_all()
|
||||
await config.clear_all_members()
|
||||
|
||||
assert len(await config.member(member).all_guilds()) == 0
|
||||
assert len(await config.all_members()) == 0
|
||||
|
||||
|
||||
# Get All testing
|
||||
@ -309,8 +309,7 @@ async def test_user_get_all_from_kind(config, user_factory):
|
||||
user = user_factory.get()
|
||||
await config.user(user).foo.set(True)
|
||||
|
||||
user = user_factory.get()
|
||||
all_data = await config.user(user).all_from_kind()
|
||||
all_data = await config.all_users()
|
||||
|
||||
assert len(all_data) == 5
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user