Config

Config was introduced in V3 as a way to make data storage easier and safer for all developers regardless of skill level. It will take some getting used to as the syntax is entirely different from what Red has used before, but we believe Config will be extremely beneficial to both cog developers and end users in the long run.

Note

While config is great for storing data safely, there are some caveats to writing performant code which uses it. Make sure to read the section on best practices for more of these details.

Basic Usage

from redbot.core import Config

class MyCog:
    def __init__(self):
        self.config = Config.get_conf(self, identifier=1234567890)

        self.config.register_global(
            foo=True
        )

    @commands.command()
    async def return_some_data(self, ctx):
        await ctx.send(await self.config.foo())

Tutorial

This tutorial will walk you through how to use Config.

First, you need to import Config:

from redbot.core import Config

Then, in the class’s __init__ function, you need to get a config instance:

class MyCog:
    def __init__(self):
        self.config = Config.get_conf(self, identifier=1234567890)

The identifier in Config.get_conf() is used to keep your cog’s data separate from that of another cog, and thus should be unique to your cog. For example: if we have two cogs named MyCog and their identifier is different, each will have its own data without overwriting the other’s data. Note that it is also possible to force registration of a data key before allowing you to get and set data for that key by adding force_registration=True after identifier (that defaults to False though)

After we’ve gotten that, we need to register default values:

class MyCog:
    def __init__(self):
        self.config = Config.get_conf(self, identifier=1234567890)
        default_global = {
            "foobar": True,
            "foo": {
                "bar": True,
                "baz": False
            }
        }
        default_guild = {
            "blah": [],
            "baz": 1234567890
        }
        self.config.register_global(**default_global)
        self.config.register_guild(**default_guild)

As seen in the example above, we can set up our defaults in dicts and then use those in the appropriate register function. As seen above, there’s Config.register_global() and Config.register_guild(), but there’s also Config.register_member(), Config.register_role(), Config.register_user(), and Config.register_channel(). Note that member stores based on guild id AND the user’s id.

Once we have our defaults registered and we have the object, we can now use those values in various ways:

@commands.command()
@checks.admin_or_permissions(manage_guild=True)
async def setbaz(self, ctx, new_value):
    await self.config.guild(ctx.guild).baz.set(new_value)
    await ctx.send("Value of baz has been changed!")

@commands.command()
@checks.is_owner()
async def setfoobar(self, ctx, new_value):
    await self.config.foobar.set(new_value)

@commands.command()
async def checkbaz(self, ctx):
    baz_val = await self.config.guild(ctx.guild).baz()
    await ctx.send("The value of baz is {}".format("True" if baz_val else "False"))

Notice a few things in the above examples:

  1. Global doesn’t have anything in between self.config and the variable.

  2. Both the getters and setters need to be awaited because they’re coroutines.

  3. If you’re getting the value, the syntax is:

    self.config.<insert scope here, or nothing if global>.variable_name()
    
  4. If setting, it’s:

    self.config.<insert scope here, or nothing if global>.variable_name.set(new_value)
    

It is also possible to use async with syntax to get and set config values. When entering the statement, the config value is retreived, and on exit, it is saved. This puts a safeguard on any code within the async with block such that if it breaks from the block in any way (whether it be from return, break, continue or an exception), the value will still be saved.

Important

Only mutable config values can be used in the async with statement (namely lists or dicts), and they must be modified in place for their changes to be saved.

Here is an example of the async with syntax:

@commands.command()
async def addblah(self, ctx, new_blah):
    guild_group = self.config.guild(ctx.guild)
    async with guild_group.blah() as blah:
        blah.append(new_blah)
    await ctx.send("The new blah value has been added!")

Important

Please note that while you have nothing between config and the variable name for global data, you also have the following commands to get data specific to each category.

If you need to wipe data from the config, you want to look at Group.clear(), or Config.clear_all() and similar methods, such as Config.clear_all_guilds().

Which one you should use depends on what you want to do.

If you’re looking to clear data for a single guild/member/channel/role/user, you want to use Group.clear() as that will clear the data only for the specified thing.

If using Config.clear_all(), it will reset all data everywhere.

There are other methods provided to reset data from a particular scope. For example, Config.clear_all_guilds() resets all guild data. For member data, you can clear on both a per-guild and guild-independent basis, see Config.clear_all_members() for more info.

Advanced Usage

Config makes it extremely easy to organize data that can easily fit into one of the standard categories (global, guild, user etc.) but there may come a time when your data does not work with the existing categories. There are now features within Config to enable developers to work with data how they wish.

This usage guide will cover the following features:

For this example let’s suppose that we’re creating a cog that allows users to buy and own multiple pets using the built-in Economy credits:

from redbot.core import bank
from redbot.core import Config
from discord.ext import commands


class Pets:
    def __init__(self):
        self.config = Config.get_conf(self, 1234567890)

        # Here we'll assign some default costs for the pets
        self.config.register_global(
            dog=100,
            cat=100,
            bird=50
        )
        self.config.register_user(
            pets={}
        )

And now that the cog is set up we’ll need to create some commands that allow users to purchase these pets:

# continued
    @commands.command()
    async def get_pet(self, ctx, pet_type: str, pet_name: str):
        """
        Purchase a pet.

        Pet type must be one of: dog, cat, bird
        """
        # Now we need to determine what the cost of the pet is and
        # if the user has enough credits to purchase it.

        # We will need to use "get_raw"
        try:
            cost = await self.config.get_raw(pet_type)
        except KeyError:
            # KeyError is thrown whenever the data you try to access does not
            # exist in the registered defaults or in the saved data.
            await ctx.send("Bad pet type, try again.")
            return

After we’ve determined the cost of the pet we need to check if the user has enough credits and then we’ll need to assign a new pet to the user. This is very easily done using the V3 bank API and Group.set_raw():

# continued
        if await bank.can_spend(ctx.author, cost):
            await self.config.user(ctx.author).pets.set_raw(
                pet_name, value={'cost': cost, 'hunger': 0}
            )

            # this is equivalent to doing the following

            pets = await self.config.user(ctx.author).pets()
            pets[pet_name] = {'cost': cost, 'hunger': 0}
            await self.config.user(ctx.author).pets.set(pets)

Since the pets can get hungry we’re gonna need a command that let’s pet owners check how hungry their pets are:

# continued
    @commands.command()
    async def hunger(self, ctx, pet_name: str):
        try:
            hunger = await self.config.user(ctx.author).pets.get_raw(pet_name, 'hunger')
        except KeyError:
            # Remember, this is thrown if something in the provided identifiers
            # is not found in the saved data or the defaults.
            await ctx.send("You don't own that pet!")
            return

        await ctx.send("Your pet has {}/100 hunger".format(hunger))

We’re responsible pet owners here, so we’ve also got to have a way to feed our pets:

# continued
    @commands.command()
    async def feed(self, ctx, pet_name: str, food: int):
        # This is a bit more complicated because we need to check if the pet is
        # owned first.
        try:
            pet = await self.config.user(ctx.author).pets.get_raw(pet_name)
        except KeyError:
            # If the given pet name doesn't exist in our data
            await ctx.send("You don't own that pet!")
            return

        hunger = pet.get("hunger")

        # Determine the new hunger and make sure it doesn't go negative
        new_hunger = max(hunger - food, 0)

        await self.config.user(ctx.author).pets.set_raw(
            pet_name, 'hunger', value=new_hunger
        )

        # We could accomplish the same thing a slightly different way
        await self.config.user(ctx.author).pets.get_attr(pet_name).hunger.set(new_hunger)

        await ctx.send("Your pet is now at {}/100 hunger!".format(new_hunger)

Of course, if we’re less than responsible pet owners, there are consequences:

#continued
    @commands.command()
    async def adopt(self, ctx, pet_name: str, *, member: discord.Member):
        try:
            pet = await self.config.user(member).pets.get_raw(pet_name)
        except KeyError:
            await ctx.send("That person doesn't own that pet!")
            return

        hunger = pet.get("hunger")
        if hunger < 80:
            await ctx.send("That pet is too well taken care of to be adopted.")
            return

        await self.config.user(member).pets.clear_raw(pet_name)

        # this is equivalent to doing the following

        pets = await self.config.user(member).pets()
        del pets[pet_name]
        await self.config.user(member).pets.set(pets)

        await self.config.user(ctx.author).pets.set_raw(pet_name, value=pet)
        await ctx.send(
            "Your request to adopt this pet has been granted due to "
            "how poorly it was taken care of."
        )

V2 Data Usage

There has been much conversation on how to bring V2 data into V3 and, officially, we recommend that cog developers make use of the public interface in Config (using the categories as described in these docs) rather than simply copying and pasting your V2 data into V3. Using Config as recommended will result in a much better experience for you in the long run and will simplify cog creation and maintenance.

However.

We realize that many of our cog creators have expressed disinterest in writing converters for V2 to V3 style data. As a result we have opened up config to take standard V2 data and allow cog developers to manipulate it in V3 in much the same way they would in V2. The following examples will demonstrate how to accomplish this.

Warning

By following this method to use V2 data in V3 you may be at risk of data corruption if your cog is used on a bot with multiple shards. USE AT YOUR OWN RISK.

from redbot.core import Config


class ExampleCog:
    def __init__(self):
        self.config = Config.get_conf(self, 1234567890)

        self.data = {}

    async def load_data(self):
        self.data = await self.config.custom("V2", "V2").all()

    async def save_data(self):
        await self.config.custom("V2", "V2").set(self.data)


async def setup(bot):
    cog = ExampleCog()
    await cog.load_data()
    bot.add_cog(cog)

Best practices and performance notes

Config prioritizes being a safe data store without developers needing to know how end users have configured their bot.

This does come with some performance costs, so keep the following in mind when choosing to develop using config

  • Config use in events should be kept minimal and should only occur after confirming the event needs to interact with config
  • Caching frequently used things, especially things used by events, results in faster and less event loop blocking code.
  • Only use config’s context managers when you intend to modify data.
  • While config is a great general use option, it may not always be the right one for you. As a cog developer, even though config doesn’t require one, you can choose to require a database or store to something such as an sqlite database stored within your cog’s datapath.

API Reference

Important

Before we begin with the nitty gritty API Reference, you should know that there are tons of working code examples inside the bot itself! Simply take a peek inside of the tests/core/test_config.py file for examples of using Config in all kinds of ways.

Important

When getting, setting or clearing values in Config, all keys are casted to str for you. This includes keys within a dict when one is being set, as well as keys in nested dictionaries within that dict. For example:

>>> config = Config.get_conf(self, identifier=999)
>>> config.register_global(foo={})
>>> await config.foo.set_raw(123, value=True)
>>> await config.foo()
{'123': True}
>>> await config.foo.set({123: True, 456: {789: False}}
>>> await config.foo()
{'123': True, '456': {'789': False}}

Config

class redbot.core.config.Config(cog_name, unique_identifier, driver, force_registration=False, defaults=None)[source]

Bases: object

Configuration manager for cogs and Red.

You should always use get_conf to instantiate a Config object. Use get_core_conf for Config used in the core package.

Important

Most config data should be accessed through its respective group method (e.g. guild()) however the process for accessing global data is a bit different. There is no global method because global data is accessed by normal attribute access:

await config.foo()
cog_name

The name of the cog that has requested a Config object.

Type:str
unique_identifier

Unique identifier provided to differentiate cog data when name conflicts occur.

Type:int
driver

An instance of a driver that implements redbot.core.drivers.BaseDriver.

force_registration

Determines if Config should throw an error if a cog attempts to access an attribute which has not been previously registered.

Note

You should use this. By enabling force registration you give Config the ability to alert you instantly if you’ve made a typo when attempting to access data.

Type:bool
await all_channels()[source]

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:A dictionary in the form {int: dict} mapping CHANNEL_ID -> data.
Return type:dict
await all_guilds()[source]

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:A dictionary in the form {int: dict} mapping GUILD_ID -> data.
Return type:dict
await all_members(guild=None)[source]

Get data for all members.

If guild is specified, only the data for the members of that guild will be returned. As such, the dict will map MEMBER_ID -> data. Otherwise, the dict maps 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:A dictionary of all specified member data.
Return type:dict
await all_roles()[source]

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:A dictionary in the form {int: dict} mapping ROLE_ID -> data.
Return type:dict
await all_users()[source]

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:A dictionary in the form {int: dict} mapping USER_ID -> data.
Return type:dict
channel(channel)[source]

Returns a Group for the given channel.

This does not discriminate between text and voice channels.

Parameters:channel (discord.abc.GuildChannel) – A channel object.
Returns:The channel’s Group object.
Return type:Group
channel_from_id(channel_id)[source]

Returns a Group for the given channel id.

This does not discriminate between text and voice channels.

Parameters:channel_id (int) – A channel id.
Returns:The channel’s Group object.
Return type:Group
await clear_all()[source]

Clear all data from this Config instance.

This resets all data to its registered defaults.

Important

This cannot be undone.

await clear_all_channels()[source]

Clear all channel data.

This resets all channel data to its registered defaults.

await clear_all_custom(group_identifier)[source]

Clear all custom group data.

This resets all custom group data to its registered defaults.

Parameters:group_identifier (str) – The identifier for the custom group. This is casted to str for you.
await clear_all_globals()[source]

Clear all global data.

This resets all global data to its registered defaults.

await clear_all_guilds()[source]

Clear all guild data.

This resets all guild data to its registered defaults.

await clear_all_members(guild=None)[source]

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.
await clear_all_roles()[source]

Clear all role data.

This resets all role data to its registered defaults.

await clear_all_users()[source]

Clear all user data.

This resets all user data to its registered defaults.

custom(group_identifier, *identifiers)[source]

Returns a Group for the given custom group.

Parameters:
  • group_identifier (str) – Used to identify the custom group.
  • identifiers (str) – The attributes necessary to uniquely identify an entry in the custom group. These are casted to str for you.
Returns:

The custom group’s Group object.

Return type:

Group

get_channels_lock()[source]

Get a lock for all channel data.

Returns:A lock for all channels data.
Return type:asyncio.Lock
classmethod get_conf(cog_instance, identifier, force_registration=False, cog_name=None, allow_old=False)[source]

Get a Config instance for your cog.

Warning

If you are using this classmethod to get a second instance of an existing Config object for a particular cog, you MUST provide the correct identifier. If you do not, you will screw up all other Config instances for that cog.

Parameters:
  • cog_instance – This is an instance of your cog after it has been instantiated. If you’re calling this method from within your cog’s __init__, this is just self.
  • identifier (int) – A (hard-coded) random integer, used to keep your data distinct from any other cog with the same name.
  • force_registration (bool, optional) – Should config require registration of data keys before allowing you to get/set values? See force_registration.
  • cog_name (str, optional) – Config normally uses cog_instance to determine tha name of your cog. If you wish you may pass None to cog_instance and directly specify the name of your cog here.
Returns:

A new Config object.

Return type:

Config

classmethod get_core_conf(force_registration=False, allow_old=False)[source]

Get a Config instance for the core bot.

All core modules that require a config instance should use this classmethod instead of get_conf.

Parameters:force_registration (bool, optional) – See force_registration.
get_custom_lock(group_identifier)[source]

Get a lock for all data in a custom scope.

Parameters:group_identifier (str) – The group identifier for the custom scope you want to lock.
Returns:A lock for all data in a custom scope with given group identifier.
Return type:asyncio.Lock
get_guilds_lock()[source]

Get a lock for all guild data.

Returns:A lock for all guild data.
Return type:asyncio.Lock
get_members_lock(guild=None)[source]

Get a lock for all member data.

Parameters:guild (Optional[discord.Guild]) – The guild containing the members whose data you want to lock. Omit to lock all data for all members in all guilds.
Returns:A lock for all member data for the given guild. If guild is omitted this will give a lock for all data for all members in all guilds.
Return type:asyncio.Lock
get_roles_lock()[source]

Get a lock for all role data.

Returns:A lock for all roles data.
Return type:asyncio.Lock
get_users_lock()[source]

Get a lock for all user data.

Returns:A lock for all user data.
Return type:asyncio.Lock
guild(guild)[source]

Returns a Group for the given guild.

Parameters:guild (discord.Guild) – A guild object.
Returns:The guild’s Group object.
Return type:Group
guild_from_id(guild_id)[source]

Returns a Group for the given guild id.

Parameters:guild_id (int) – A guild id.
Returns:The guild’s Group object.
Return type:Group
init_custom(group_identifier, identifier_count)[source]

Initializes a custom group for usage. This method must be called first!

member(member)[source]

Returns a Group for the given member.

Parameters:member (discord.Member) – A member object.
Returns:The member’s Group object.
Return type:Group
member_from_ids(guild_id, member_id)[source]

Returns a Group for the ids which represent a member.

Parameters:
  • guild_id (int) – The id of the guild of the member
  • member_id (int) – The id of the member
Returns:

The member’s Group object.

Return type:

Group

register_channel(**kwargs)[source]

Register default values on a per-channel level.

See register_global for more details.

register_custom(group_identifier, **kwargs)[source]

Registers default values for a custom group.

See register_global for more details.

register_global(**kwargs)[source]

Register default values for attributes you wish to store in Config at a global level.

Examples

You can register a single value or multiple values:

config.register_global(
    foo=True
)

config.register_global(
    bar=False,
    baz=None
)

You can also now register nested values:

_defaults = {
    "foo": {
        "bar": True,
        "baz": False
    }
}

# Will register `foo.bar` == True and `foo.baz` == False
config.register_global(
    **_defaults
)

You can do the same thing without a _defaults dict by using double underscore as a variable name separator:

# This is equivalent to the previous example
config.register_global(
    foo__bar=True,
    foo__baz=False
)
register_guild(**kwargs)[source]

Register default values on a per-guild level.

See register_global for more details.

register_member(**kwargs)[source]

Registers default values on a per-member level.

This means that each user’s data is guild-dependent.

See register_global for more details.

register_role(**kwargs)[source]

Registers default values on a per-role level.

See register_global for more details.

register_user(**kwargs)[source]

Registers default values on a per-user level.

This means that each user’s data is guild-independent.

See register_global for more details.

role(role)[source]

Returns a Group for the given role.

Parameters:role (discord.Role) – A role object.
Returns:The role’s Group object.
Return type:Group
role_from_id(role_id)[source]

Returns a Group for the given role id.

Parameters:role_id (int) – A role id.
Returns:The role’s Group object.
Return type:Group
user(user)[source]

Returns a Group for the given user.

Parameters:user (discord.User) – A user object.
Returns:The user’s Group object.
Return type:Group
user_from_id(user_id)[source]

Returns a Group for the given user id.

Parameters:user_id (int) – The user’s id
Returns:The user’s Group object.
Return type:Group

Group

class redbot.core.config.Group(identifier_data, defaults, driver, config, force_registration=False)[source]

Bases: redbot.core.config.Value

Represents a group of data, composed of more Group or Value objects.

Inherits from Value which means that all of the attributes and methods available in Value are also available when working with a Group object.

defaults

All registered default values for this Group.

Type:dict
force_registration

Same as Config.force_registration.

Type:bool
driver

A reference to Config.driver.

Type:redbot.core.drivers.BaseDriver
__getattr__(item)[source]

Get an attribute of this group.

This special method is called whenever dot notation is used on this object.

Parameters:item (str) – The name of the attribute being accessed.
Returns:A child value of this Group. This, of course, can be another Group, due to Config’s composite pattern.
Return type:Group or Value
Raises:AttributeError – If the attribute has not been registered and force_registration is set to True.
__init__(identifier_data, defaults, driver, config, force_registration=False)[source]

Initialize self. See help(type(self)) for accurate signature.

all(*, acquire_lock=True)[source]

Get a dictionary representation of this group’s data.

The return value of this method can also be used as an asynchronous context manager, i.e. with async with syntax.

Note

The return value of this method will include registered defaults for values which have not yet been set.

Other Parameters:
 acquire_lock (bool) – Same as the acquire_lock keyword parameter in Value.__call__.
Returns:All of this Group’s attributes, resolved as raw data values.
Return type:dict
await clear_raw(*nested_path)[source]

Allows a developer to clear data as if it was stored in a standard Python dictionary.

For example:

await config.clear_raw("foo", "bar")

# is equivalent to

data = {"foo": {"bar": None}}
del data["foo"]["bar"]
Parameters:nested_path (Any) – Multiple arguments that mirror the arguments passed in for nested dict access. These are casted to str for you.
get_attr(item)[source]

Manually get an attribute of this Group.

This is available to use as an alternative to using normal Python attribute access. It may be required if you find a need for dynamic attribute access.

Example

A possible use case:

@commands.command()
async def some_command(self, ctx, item: str):
    user = ctx.author

    # Where the value of item is the name of the data field in Config
    await ctx.send(await self.config.user(user).get_attr(item).foo())
Parameters:item (str) – The name of the data field in Config. This is casted to str for you.
Returns:The attribute which was requested.
Return type:Value or Group
await get_raw(*nested_path, default=Ellipsis)[source]

Allows a developer to access data as if it was stored in a standard Python dictionary.

For example:

d = await config.get_raw("foo", "bar")

# is equivalent to

data = {"foo": {"bar": "baz"}}
d = data["foo"]["bar"]

Note

If retreiving a sub-group, the return value of this method will include registered defaults for values which have not yet been set.

Parameters:
  • nested_path (str) – Multiple arguments that mirror the arguments passed in for nested dict access. These are casted to str for you.
  • default – Default argument for the value attempting to be accessed. If the value does not exist the default will be returned.
Returns:

The value of the path requested.

Return type:

Any

Raises:

KeyError – If the value does not exist yet in Config’s internal storage.

is_group(item)[source]

A helper method for __getattr__. Most developers will have no need to use this.

Parameters:item (Any) – See __getattr__.
is_value(item)[source]

A helper method for __getattr__. Most developers will have no need to use this.

Parameters:item (Any) – See __getattr__.
nested_update(current, defaults=Ellipsis)[source]

Robust updater for nested dictionaries

If no defaults are passed, then the instance attribute ‘defaults’ will be used.

await set(value)[source]

Set the value of the data elements pointed to by Identifiers and keywords.

Example

# Sets global value "foo" to False
await config.foo.set(False)

# Sets guild specific value of "bar" to True
await config.guild(some_guild).bar.set(True)
Parameters:value – The new literal value of this attribute.
await set_raw(*nested_path, value)[source]

Allows a developer to set data as if it was stored in a standard Python dictionary.

For example:

await config.set_raw("foo", "bar", value="baz")

# is equivalent to

data = {"foo": {"bar": None}}
data["foo"]["bar"] = "baz"
Parameters:
  • nested_path (Any) – Multiple arguments that mirror the arguments passed in for nested dict access. These are casted to str for you.
  • value – The value to store.

Value

class redbot.core.config.Value(identifier_data, default_value, driver, config)[source]

Bases: object

A singular “value” of data.

identifier_data

Information on identifiers for this value.

Type:IdentifierData
default

The default value for the data element that Identifiers and keywords points at.

driver

A reference to Config.driver.

Type:redbot.core.drivers.BaseDriver
__call__(default=Ellipsis, *, acquire_lock=True)[source]

Get the literal value of this data element.

Each Value object is created by the Group.__getattr__ method. The “real” data of the Value object is accessed by this method. It is a replacement for a get() method.

The return value of this method can also be used as an asynchronous context manager, i.e. with async with syntax. This can only be used on values which are mutable (namely lists and dicts), and will set the value with its changes on exit of the context manager. It will also acquire this value’s lock to protect the critical region inside this context manager’s body, unless the acquire_lock keyword argument is set to False.

Example

foo = await config.guild(some_guild).foo()

# Is equivalent to this

group_obj = config.guild(some_guild)
value_obj = group_obj.foo
foo = await value_obj()

Important

This is now, for all intents and purposes, a coroutine.

Parameters:default (object, optional) – This argument acts as an override for the registered default provided by default. This argument is ignored if its value is ....
Other Parameters:
 acquire_lock (bool) – Set to False to disable the acquisition of the value’s lock over the context manager body. Defaults to True. Has no effect when not used as a context manager.
Returns:A coroutine object mixed in with an async context manager. When awaited, this returns the raw data value. When used in async with syntax, on gets the value on entrance, and sets it on exit.
Return type:awaitable mixed with asynchronous context manager
await clear()[source]

Clears the value from record for the data element pointed to by Identifiers and keywords.

get_lock()[source]

Get a lock to create a critical region where this value is accessed.

When using this lock, make sure you either use it with the async with syntax, or if that’s not feasible, ensure you keep a reference to it from the acquisition to the release of the lock. That is, if you can’t use async with syntax, use the lock like this:

lock = config.foo.get_lock()
await lock.acquire()
# Do stuff...
lock.release()

Do not use it like this:

await config.foo.get_lock().acquire()
# Do stuff...
config.foo.get_lock().release()

Doing it the latter way will likely cause an error, as the acquired lock will be cleaned up by the garbage collector before it is released, meaning the second call to get_lock() will return a different lock to the first call.

Returns:A lock which is weakly cached for this value object.
Return type:asyncio.Lock
await set(value)[source]

Set the value of the data elements pointed to by Identifiers and keywords.

Example

# Sets global value "foo" to False
await config.foo.set(False)

# Sets guild specific value of "bar" to True
await config.guild(some_guild).bar.set(True)
Parameters:value – The new literal value of this attribute.

Driver Reference

redbot.core.drivers.get_driver(cog_name, identifier, storage_type=None, *, allow_old=False, **kwargs)[source]

Get a driver instance.

Parameters:
  • cog_name (str) – The cog’s name.
  • identifier (str) – The cog’s discriminator.
  • storage_type (Optional[BackendType]) – The backend you want a driver for. Omit to try to obtain the backend from data manager.
  • **kwargs – Driver-specific keyword arguments.
Returns:

A driver instance.

Return type:

BaseDriver

Raises:

RuntimeError – If the storage type is MongoV1, Mongo, or invalid.

class redbot.core.drivers.BackendType[source]

Bases: enum.Enum

Represents storage backend type.

JSON = 'JSON'

JSON storage backend.

POSTGRES = 'Postgres'

Postgres storage backend.

class redbot.core.drivers.ConfigCategory[source]

Bases: str, enum.Enum

Represents config category.

CHANNEL = 'TEXTCHANNEL'

Channel category.

GLOBAL = 'GLOBAL'

Global category.

GUILD = 'GUILD'

Guild category.

MEMBER = 'MEMBER'

Member category.

ROLE = 'ROLE'

Role category.

USER = 'USER'

User category.

Base Driver

class redbot.core.drivers.BaseDriver(cog_name, identifier, **kwargs)[source]

Bases: abc.ABC

abstractmethod classmethod aiter_cogs()[source]

Get info for cogs which have data stored on this backend.

Yields:Tuple[str, str] – Asynchronously yields (cog_name, cog_identifier) tuples.
abstractmethod await clear(identifier_data)[source]

Clears out the value specified by the given identifiers.

Equivalent to using del on a dict.

Parameters:identifier_data
classmethod await delete_all_data(**kwargs)[source]

Delete all data being stored by this driver.

The driver must be initialized before this operation.

The BaseDriver provides a generic method which may be overridden by subclasses.

Parameters:**kwargs – Driver-specific kwargs to change the way this method operates.
abstractmethod await get(identifier_data)[source]

Finds the value indicate by the given identifiers.

Parameters:identifier_data
Returns:Stored value.
Return type:Any
abstractmethod staticmethod get_config_details()[source]

Asks users for additional configuration information necessary to use this config driver.

Returns:Dictionary of configuration details.
Return type:Dict[str, Any]
abstractmethod classmethod await initialize(**storage_details)[source]

Initialize this driver.

Parameters:**storage_details – The storage details required to initialize this driver. Should be the same as data_manager.storage_details()
Raises:MissingExtraRequirements – If initializing the driver requires an extra which isn’t installed.
classmethod await migrate_to(new_driver_cls, all_custom_group_data)[source]

Migrate data from this backend to another.

Both drivers must be initialized beforehand.

This will only move the data - no instance metadata is modified as a result of this operation.

Parameters:
  • new_driver_cls – Subclass of BaseDriver.
  • all_custom_group_data (Dict[str, Dict[str, Dict[str, int]]]) – Dict mapping cog names, to cog IDs, to custom groups, to primary key lengths.
abstractmethod await set(identifier_data, value=None)[source]

Sets the value of the key indicated by the given identifiers.

Parameters:
  • identifier_data
  • value – Any JSON serializable python object.
abstractmethod classmethod await teardown()[source]

Tear down this driver.

JSON Driver

class redbot.core.drivers.JsonDriver(cog_name, identifier, *, data_path_override=None, file_name_override='settings.json')[source]

Bases: redbot.core.drivers.base.BaseDriver

Subclass of BaseDriver.

file_name

The name of the file in which to store JSON data.

data_path

The path in which to store the file indicated by file_name.

classmethod async for ... in aiter_cogs()[source]

Get info for cogs which have data stored on this backend.

Yields:Tuple[str, str] – Asynchronously yields (cog_name, cog_identifier) tuples.
await clear(identifier_data)[source]

Clears out the value specified by the given identifiers.

Equivalent to using del on a dict.

Parameters:identifier_data
await get(identifier_data)[source]

Finds the value indicate by the given identifiers.

Parameters:identifier_data
Returns:Stored value.
Return type:Any
staticmethod get_config_details()[source]

Asks users for additional configuration information necessary to use this config driver.

Returns:Dictionary of configuration details.
Return type:Dict[str, Any]
classmethod await initialize(**storage_details)[source]

Initialize this driver.

Parameters:**storage_details – The storage details required to initialize this driver. Should be the same as data_manager.storage_details()
Raises:MissingExtraRequirements – If initializing the driver requires an extra which isn’t installed.
await set(identifier_data, value=None)[source]

Sets the value of the key indicated by the given identifiers.

Parameters:
  • identifier_data
  • value – Any JSON serializable python object.
classmethod await teardown()[source]

Tear down this driver.

Postgres Driver

class redbot.core.drivers.PostgresDriver(cog_name, identifier, **kwargs)[source]

Bases: redbot.core.drivers.base.BaseDriver

classmethod async for ... in aiter_cogs()[source]

Get info for cogs which have data stored on this backend.

Yields:Tuple[str, str] – Asynchronously yields (cog_name, cog_identifier) tuples.
await clear(identifier_data)[source]

Clears out the value specified by the given identifiers.

Equivalent to using del on a dict.

Parameters:identifier_data
classmethod await delete_all_data(*, interactive=False, drop_db=None, **kwargs)[source]

Delete all data being stored by this driver.

Parameters:
  • interactive (bool) – Set to True to allow the method to ask the user for input from the console, regarding the other unset parameters for this method.
  • drop_db (Optional[bool]) – Set to True to drop the entire database for the current bot’s instance. Otherwise, schemas within the database which store bot data will be dropped, as well as functions, aggregates, event triggers, and meta-tables.
await get(identifier_data)[source]

Finds the value indicate by the given identifiers.

Parameters:identifier_data
Returns:Stored value.
Return type:Any
staticmethod get_config_details()[source]

Asks users for additional configuration information necessary to use this config driver.

Returns:Dictionary of configuration details.
Return type:Dict[str, Any]
classmethod await initialize(**storage_details)[source]

Initialize this driver.

Parameters:**storage_details – The storage details required to initialize this driver. Should be the same as data_manager.storage_details()
Raises:MissingExtraRequirements – If initializing the driver requires an extra which isn’t installed.
await set(identifier_data, value=None)[source]

Sets the value of the key indicated by the given identifiers.

Parameters:
  • identifier_data
  • value – Any JSON serializable python object.
classmethod await teardown()[source]

Tear down this driver.