mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
[Config] Modify config's all methods to provide default values (#916)
* Add in functionality for Tobotimus * Cover all_guilds * Make it obvious * Fix auto rename of docstrings * Fix downloader docs warning
This commit is contained in:
parent
248d2baa2a
commit
da28630644
@ -108,12 +108,16 @@ class Group(Value):
|
||||
defaults: dict,
|
||||
spawner,
|
||||
force_registration: bool=False):
|
||||
self.defaults = defaults
|
||||
self._defaults = defaults
|
||||
self.force_registration = force_registration
|
||||
self.spawner = spawner
|
||||
|
||||
super().__init__(identifiers, {}, self.spawner)
|
||||
|
||||
@property
|
||||
def defaults(self):
|
||||
return self._defaults.copy()
|
||||
|
||||
# noinspection PyTypeChecker
|
||||
def __getattr__(self, item: str) -> Union["Group", Value]:
|
||||
"""
|
||||
@ -135,14 +139,14 @@ class Group(Value):
|
||||
if is_group:
|
||||
return Group(
|
||||
identifiers=new_identifiers,
|
||||
defaults=self.defaults[item],
|
||||
defaults=self._defaults[item],
|
||||
spawner=self.spawner,
|
||||
force_registration=self.force_registration
|
||||
)
|
||||
elif is_value:
|
||||
return Value(
|
||||
identifiers=new_identifiers,
|
||||
default_value=self.defaults[item],
|
||||
default_value=self._defaults[item],
|
||||
spawner=self.spawner
|
||||
)
|
||||
elif self.force_registration:
|
||||
@ -174,7 +178,7 @@ class Group(Value):
|
||||
:param str item:
|
||||
See :py:meth:`__getattr__`.
|
||||
"""
|
||||
default = self.defaults.get(item)
|
||||
default = self._defaults.get(item)
|
||||
return isinstance(default, dict)
|
||||
|
||||
def is_value(self, item: str) -> bool:
|
||||
@ -185,7 +189,7 @@ class Group(Value):
|
||||
See :py:meth:`__getattr__`.
|
||||
"""
|
||||
try:
|
||||
default = self.defaults[item]
|
||||
default = self._defaults[item]
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
@ -231,19 +235,42 @@ class Group(Value):
|
||||
This method allows you to get "all" of a particular group of data. It will return the dictionary of all data
|
||||
for a particular Guild/Channel/Role/User/Member etc.
|
||||
|
||||
.. note::
|
||||
|
||||
Any values that have not been set from the registered defaults will have their default values
|
||||
added to the dictionary that this method returns.
|
||||
|
||||
:rtype: dict
|
||||
"""
|
||||
return await self()
|
||||
defaults = self.defaults
|
||||
defaults.update(await self())
|
||||
return defaults
|
||||
|
||||
async def all_from_kind(self) -> dict:
|
||||
"""
|
||||
This method allows you to get all data from all entries in a given Kind. It will return a dictionary of Kind
|
||||
ID's -> data.
|
||||
|
||||
.. note::
|
||||
|
||||
Any values that have not been set from the registered defaults will have their default values
|
||||
added to the dictionary that this method returns.
|
||||
|
||||
.. important::
|
||||
|
||||
This method is overridden in :py:meth:`.MemberGroup.all_from_kind` and functions slightly differently.
|
||||
|
||||
:rtype: dict
|
||||
"""
|
||||
# noinspection PyTypeChecker
|
||||
return await self._super_group()
|
||||
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):
|
||||
@ -307,14 +334,29 @@ class MemberGroup(Group):
|
||||
"""
|
||||
Returns a dict of :code:`GUILD_ID -> MEMBER_ID -> data`.
|
||||
|
||||
.. note::
|
||||
|
||||
Any values that have not been set from the registered defaults will have their default values
|
||||
added to the dictionary that this method returns.
|
||||
|
||||
:rtype: dict
|
||||
"""
|
||||
# noinspection PyTypeChecker
|
||||
return await self._super_group()
|
||||
return await super().all_from_kind()
|
||||
|
||||
async def all(self) -> dict:
|
||||
# noinspection PyTypeChecker
|
||||
return await self._guild_group()
|
||||
async def all_from_kind(self) -> dict:
|
||||
"""
|
||||
Returns a dict of all members from the same guild as the given one.
|
||||
|
||||
.. note::
|
||||
|
||||
Any values that have not been set from the registered defaults will have their default values
|
||||
added to the dictionary that this method returns.
|
||||
|
||||
:rtype: dict
|
||||
"""
|
||||
guild_member = await super().all_from_kind()
|
||||
return guild_member.get(self.identifiers[-2], {})
|
||||
|
||||
|
||||
class Config:
|
||||
@ -366,7 +408,11 @@ class Config:
|
||||
|
||||
self.spawner = driver_spawn
|
||||
self.force_registration = force_registration
|
||||
self.defaults = defaults or {}
|
||||
self._defaults = defaults or {}
|
||||
|
||||
@property
|
||||
def defaults(self):
|
||||
return self._defaults.copy()
|
||||
|
||||
@classmethod
|
||||
def get_conf(cls, cog_instance, identifier: int,
|
||||
@ -425,7 +471,7 @@ class Config:
|
||||
def _get_defaults_dict(key: str, value) -> dict:
|
||||
"""
|
||||
Since we're allowing nested config stuff now, not storing the
|
||||
defaults as a flat dict sounds like a good idea. May turn
|
||||
_defaults as a flat dict sounds like a good idea. May turn
|
||||
out to be an awful one but we'll see.
|
||||
:param key:
|
||||
:param value:
|
||||
@ -447,7 +493,7 @@ class Config:
|
||||
@staticmethod
|
||||
def _update_defaults(to_add: dict, _partial: dict):
|
||||
"""
|
||||
This tries to update the defaults dictionary with the nested
|
||||
This tries to update the _defaults dictionary with the nested
|
||||
partial dict generated by _get_defaults_dict. This WILL
|
||||
throw an error if you try to have both a value and a group
|
||||
registered under the same name.
|
||||
@ -471,14 +517,14 @@ class Config:
|
||||
_partial[k] = v
|
||||
|
||||
def _register_default(self, key: str, **kwargs):
|
||||
if key not in self.defaults:
|
||||
self.defaults[key] = {}
|
||||
if key not in self._defaults:
|
||||
self._defaults[key] = {}
|
||||
|
||||
data = deepcopy(kwargs)
|
||||
|
||||
for k, v in data.items():
|
||||
to_add = self._get_defaults_dict(k, v)
|
||||
self._update_defaults(to_add, self.defaults[key])
|
||||
self._update_defaults(to_add, self._defaults[key])
|
||||
|
||||
def register_global(self, **kwargs):
|
||||
"""
|
||||
@ -497,7 +543,7 @@ class Config:
|
||||
|
||||
You can also now register nested values::
|
||||
|
||||
defaults = {
|
||||
_defaults = {
|
||||
"foo": {
|
||||
"bar": True,
|
||||
"baz": False
|
||||
@ -506,10 +552,10 @@ class Config:
|
||||
|
||||
# Will register `foo.bar` == True and `foo.baz` == False
|
||||
conf.register_global(
|
||||
**defaults
|
||||
**_defaults
|
||||
)
|
||||
|
||||
You can do the same thing without a :python:`defaults` dict by using double underscore as a variable
|
||||
You can do the same thing without a :python:`_defaults` dict by using double underscore as a variable
|
||||
name separator::
|
||||
|
||||
# This is equivalent to the previous example
|
||||
@ -556,7 +602,7 @@ class Config:
|
||||
# noinspection PyTypeChecker
|
||||
return group_class(
|
||||
identifiers=(self.unique_identifier, key) + identifiers,
|
||||
defaults=self.defaults.get(key, {}),
|
||||
defaults=self._defaults.get(key, {}),
|
||||
spawner=self.spawner,
|
||||
force_registration=self.force_registration
|
||||
)
|
||||
|
||||
@ -43,16 +43,28 @@ API Reference
|
||||
|
||||
.. automodule:: core.config
|
||||
|
||||
Config
|
||||
^^^^^^
|
||||
|
||||
.. autoclass:: Config
|
||||
:members:
|
||||
|
||||
Group
|
||||
^^^^^
|
||||
|
||||
.. autoclass:: Group
|
||||
:members:
|
||||
:special-members:
|
||||
|
||||
MemberGroup
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: MemberGroup
|
||||
:members:
|
||||
|
||||
Value
|
||||
^^^^^
|
||||
|
||||
.. autoclass:: Value
|
||||
:members:
|
||||
:special-members: __call__
|
||||
|
||||
@ -69,7 +69,7 @@ Repo Manager
|
||||
:members:
|
||||
|
||||
Exceptions
|
||||
^^^^^^
|
||||
^^^^^^^^^^
|
||||
|
||||
.. automodule:: cogs.downloader.errors
|
||||
:members:
|
||||
|
||||
@ -37,7 +37,7 @@ def config(json_driver):
|
||||
unique_identifier=str(uuid.uuid4()),
|
||||
driver_spawn=json_driver)
|
||||
yield conf
|
||||
conf.defaults = {}
|
||||
conf._defaults = {}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@ -53,7 +53,7 @@ def config_fr(json_driver):
|
||||
force_registration=True
|
||||
)
|
||||
yield conf
|
||||
conf.defaults = {}
|
||||
conf._defaults = {}
|
||||
|
||||
|
||||
#region Dpy Mocks
|
||||
|
||||
@ -242,7 +242,7 @@ async def test_membergroup_allguilds(config, empty_member):
|
||||
async def test_membergroup_allmembers(config, empty_member):
|
||||
await config.member(empty_member).foo.set(False)
|
||||
|
||||
all_members = await config.member(empty_member).all()
|
||||
all_members = await config.member(empty_member).all_from_kind()
|
||||
assert str(empty_member.id) in all_members
|
||||
|
||||
|
||||
@ -301,6 +301,10 @@ async def test_member_clear_all(config, member_factory):
|
||||
# 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):
|
||||
user = user_factory.get()
|
||||
await config.user(user).foo.set(True)
|
||||
@ -310,10 +314,23 @@ async def test_user_get_all_from_kind(config, user_factory):
|
||||
|
||||
assert len(all_data) == 5
|
||||
|
||||
for _, v in all_data.items():
|
||||
assert v['foo'] is True
|
||||
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
|
||||
)
|
||||
await config.user(user).foo.set(False)
|
||||
|
||||
assert "foo" in await config.user(user).all()
|
||||
all_data = await config.user(user).all()
|
||||
|
||||
assert "foo" in all_data
|
||||
assert "bar" in all_data
|
||||
|
||||
assert config.user(user).defaults['foo'] is True
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user