From fd684bdb58b4e16d9dd71cb5c9093cb1ba7c4374 Mon Sep 17 00:00:00 2001 From: palmtree5 Date: Fri, 11 Aug 2017 17:59:27 -0800 Subject: [PATCH] [Docs] Add bank docs (#900) * Add bank docs * [Docs] fix bank docstrings for formatting * [Docs] add bank to toctree * rename and make bank rst use members * Formatting changes * Add account to dunder all --- core/bank.py | 266 +++++++++++++++++++++++++++++++--------- docs/framework_bank.rst | 42 +++++++ docs/index.rst | 1 + 3 files changed, 250 insertions(+), 59 deletions(-) create mode 100644 docs/framework_bank.rst diff --git a/core/bank.py b/core/bank.py index f8f326b22..7838aa992 100644 --- a/core/bank.py +++ b/core/bank.py @@ -7,10 +7,10 @@ from copy import deepcopy from core import Config -__all__ = ["get_balance", "set_balance", "withdraw_credits", "deposit_credits", +__all__ = ["Account", "get_balance", "set_balance", "withdraw_credits", "deposit_credits", "can_spend", "transfer_credits", "wipe_bank", "get_guild_accounts", - "get_global_accounts", "get_account", "is_global", "get_bank_name", - "set_bank_name", "get_currency_name", "set_currency_name", + "get_global_accounts", "get_account", "is_global", "set_global", + "get_bank_name", "set_bank_name", "get_currency_name", "set_currency_name", "get_default_balance", "set_default_balance"] _DEFAULT_GLOBAL = { @@ -35,11 +35,19 @@ _DEFAULT_MEMBER = { _DEFAULT_USER = _DEFAULT_MEMBER _bank_type = type("Bank", (object,), {}) -Account = namedtuple("Account", "name balance created_at") _conf = Config.get_conf(_bank_type(), 384734293238749, force_registration=True) +class Account: + """A single account. This class should ONLY be instantiated by the bank itself.""" + + def __init__(self, name: str, balance: int, created_at: datetime.datetime): + self.name = name + self.balance = balance + self.created_at = created_at + + def _register_defaults(): _conf.register_global(**_DEFAULT_GLOBAL) _conf.register_guild(**_DEFAULT_GUILD) @@ -81,8 +89,13 @@ def _decode_time(time: int) -> datetime.datetime: async def get_balance(member: discord.Member) -> int: """ Gets the current balance of a member. - :param member: - :return: + + :param discord.Member member: + The member whose balance to check. + :return: + The member's balance + :rtype: + int """ acc = await get_account(member) return acc.balance @@ -91,9 +104,15 @@ async def get_balance(member: discord.Member) -> int: async def can_spend(member: discord.Member, amount: int) -> bool: """ Determines if a member can spend the given amount. - :param member: - :param amount: - :return: + + :param discord.Member member: + The member wanting to spend. + :param int amount: + The amount the member wants to spend. + :return: + :code:`True` if the member has a sufficient balance to spend the amount, else :code:`False`. + :rtype: + bool """ if _invalid_amount(amount): return False @@ -105,9 +124,17 @@ async def set_balance(member: discord.Member, amount: int) -> int: Sets an account balance. May raise ValueError if amount is invalid. - :param member: - :param amount: - :return: New account balance. + + :param discord.Member member: + The member whose balance to set. + :param int amount: + The amount to set the balance to. + :return: + New account balance. + :rtype: + int + :raises ValueError: + If attempting to set the balance to a negative number """ if amount < 0: raise ValueError("Not allowed to have negative balance.") @@ -136,10 +163,18 @@ async def withdraw_credits(member: discord.Member, amount: int) -> int: Removes a certain amount of credits from an account. May raise ValueError if the amount is invalid or if the account has - insufficient funds. - :param member: - :param amount: - :return: New account balance. + insufficient funds. + + :param discord.Member member: + The member to withdraw credits from. + :param int amount: + The amount to withdraw. + :return: + New account balance. + :rtype: + int + :raises ValueError: + if the withdrawal amount is invalid or if the account has insufficient funds """ if _invalid_amount(amount): raise ValueError("Invalid withdrawal amount {} <= 0".format(amount)) @@ -156,9 +191,17 @@ async def deposit_credits(member: discord.Member, amount: int) -> int: Adds a given amount of credits to an account. May raise ValueError if the amount is invalid. - :param member: - :param amount: - :return: + + :param discord.Member member: + The member to deposit credits to. + :param int amount: + The amount to deposit. + :return: + The new balance + :rtype: + int + :raises ValueError: + If the deposit amount is invalid. """ if _invalid_amount(amount): raise ValueError("Invalid withdrawal amount {} <= 0".format(amount)) @@ -171,12 +214,21 @@ async def transfer_credits(from_: discord.Member, to: discord.Member, amount: in """ Transfers a given amount of credits from one account to another. - May raise ValueError if the amount is invalid or if the from_ - account has insufficient funds. - :param from_: - :param to: - :param amount: - :return: + May raise ValueError if the amount is invalid or if the :code:`from_` + account has insufficient funds. + + :param discord.Member from_: + The member to transfer from. + :param discord.Member to: + The member to transfer to. + :param int amount: + The amount to transfer. + :return: + The new balance. + :rtype: + int + :raises ValueError: + If the amount is invalid or if :code:`from_` has insufficient funds. """ if _invalid_amount(amount): raise ValueError("Invalid transfer amount {} <= 0".format(amount)) @@ -188,7 +240,16 @@ async def transfer_credits(from_: discord.Member, to: discord.Member, amount: in async def wipe_bank(user: Union[discord.User, discord.Member]): """ Deletes all accounts from the bank. - :return: + + .. important:: + + A member is required if the bank is currently guild specific. + + :param user: + A user to be used in clearing the bank, this is required for technical + reasons and it does not matter which user/member is used. + :type user: + discord.User or discord.Member """ if await is_global(): await _conf.user(user).clear() @@ -201,8 +262,15 @@ async def get_guild_accounts(guild: discord.Guild) -> List[Account]: Gets all account data for the given guild. May raise RuntimeError if the bank is currently global. - :param guild: - :return: + + :param discord.Guild guild: + The guild to get accounts for. + :return: + A generator for all guild accounts. + :rtype: + generator + :raises RuntimeError: + If the bank is global. """ if is_global(): raise RuntimeError("The bank is currently global.") @@ -221,8 +289,15 @@ async def get_global_accounts(user: discord.User) -> List[Account]: Gets all global account data. May raise RuntimeError if the bank is currently guild specific. - :param user: - :return: + + :param discord.User user: + A user to be used for getting accounts. + :return: + A generator of all global accounts. + :rtype: + generator + :raises RuntimeError: + If the bank is guild specific. """ if not is_global(): raise RuntimeError("The bank is not currently global.") @@ -239,9 +314,17 @@ async def get_global_accounts(user: discord.User) -> List[Account]: async def get_account(member: Union[discord.Member, discord.User]) -> Account: """ - Gets the appropriate account for the given member. + Gets the appropriate account for the given user or member. A member is + required if the bank is currently guild specific. + :param member: - :return: + The user whose account to get. + :type member: + discord.User or discord.Member + :return: + The user's account. + :rtype: + :py:class:`Account` """ if await is_global(): acc_data = (await _conf.user(member)()).copy() @@ -265,17 +348,34 @@ async def get_account(member: Union[discord.Member, discord.User]) -> Account: async def is_global() -> bool: """ Determines if the bank is currently global. - :return: + + :return: + :code:`True` if the bank is global, otherwise :code:`False`. + :rtype: + bool """ return await _conf.is_global() async def set_global(global_: bool, user: Union[discord.User, discord.Member]) -> bool: """ - Sets global status of the bank, all accounts are reset when you switch! - :param global_: True will set bank to global mode. - :param user: Must be a Member object if changing TO global mode. - :return: New bank mode, True is global. + Sets global status of the bank, requires the user parameter for technical reasons. + + .. important:: + All accounts are reset when you switch! + + :param global_: + :code:`True` will set bank to global mode. + :param user: + Must be a Member object if changing TO global mode. + :type user: + discord.User or discord.Member + :return: + New bank mode, :code:`True` is global. + :rtype: + bool + :raises RuntimeError: + If bank is becoming global and :py:class:`discord.Member` was not provided. """ if (await is_global()) is global_: return global_ @@ -295,11 +395,18 @@ async def set_global(global_: bool, user: Union[discord.User, discord.Member]) - async def get_bank_name(guild: discord.Guild=None) -> str: """ Gets the current bank name. If the bank is guild-specific the - guild parameter is required. + guild parameter is required. May raise RuntimeError if guild is missing and required. - :param guild: - :return: + + :param discord.Guild guild: + The guild to get the bank name for (required if bank is guild-specific). + :return: + The bank's name. + :rtype: + str + :raises RuntimeError: + If the bank is guild-specific and guild was not provided. """ if await is_global(): return await _conf.bank_name() @@ -311,13 +418,21 @@ async def get_bank_name(guild: discord.Guild=None) -> str: async def set_bank_name(name: str, guild: discord.Guild=None) -> str: """ - Sets the bank name, if bank is server specific the guild parameter is - required. + Sets the bank name, if bank is guild specific the guild parameter is + required. May throw RuntimeError if guild is required and missing. - :param name: - :param guild: - :return: + + :param str name: + The new name for the bank. + :param discord.Guild guild: + The guild to set the bank name for (required if bank is guild-specific). + :return: + The new name for the bank. + :rtype: + str + :raises RuntimeError: + If the bank is guild-specific and guild was not provided. """ if await is_global(): await _conf.bank_name.set(name) @@ -332,11 +447,18 @@ async def set_bank_name(name: str, guild: discord.Guild=None) -> str: async def get_currency_name(guild: discord.Guild=None) -> str: """ Gets the currency name of the bank. The guild parameter is required if - the bank is guild-specific. + the bank is guild-specific. May raise RuntimeError if the guild is missing and required. - :param guild: - :return: + + :param discord.Guild guild: + The guild to get the currency name for (required if bank is guild-specific). + :return: + The currency name. + :rtype: + str + :raises RuntimeError: + If the bank is guild-specific and guild was not provided. """ if await is_global(): return await _conf.currency() @@ -349,12 +471,20 @@ async def get_currency_name(guild: discord.Guild=None) -> str: async def set_currency_name(name: str, guild: discord.Guild=None) -> str: """ Sets the currency name for the bank, if bank is guild specific the - guild parameter is required. + guild parameter is required. May raise RuntimeError if guild is missing and required. - :param name: - :param guild: - :return: + + :param str name: + The new name for the currency. + :param discord.Guild guild: + The guild to set the currency name for (required if bank is guild-specific). + :return: + The new name for the currency. + :rtype: + str + :raises RuntimeError: + If the bank is guild-specific and guild was not provided. """ if await is_global(): await _conf.currency.set(name) @@ -369,11 +499,18 @@ async def set_currency_name(name: str, guild: discord.Guild=None) -> str: async def get_default_balance(guild: discord.Guild=None) -> int: """ Gets the current default balance amount. If the bank is guild-specific - you must pass guild. + you must pass guild. May raise RuntimeError if guild is missing and required. - :param guild: - :return: + + :param discord.Guild guild: + The guild to get the default balance for (required if bank is guild-specific). + :return: + The bank's default balance. + :rtype: + str + :raises RuntimeError: + If the bank is guild-specific and guild was not provided. """ if await is_global(): return await _conf.default_balance() @@ -386,13 +523,24 @@ async def get_default_balance(guild: discord.Guild=None) -> int: async def set_default_balance(amount: int, guild: discord.Guild=None) -> int: """ Sets the default balance amount. Guild is required if the bank is - guild-specific. + guild-specific. May raise RuntimeError if guild is missing and required. + May raise ValueError if amount is invalid. - :param guild: - :param amount: - :return: + + :param int amount: + The new default balance. + :param discord.Guild guild: + The guild to set the default balance for (required if bank is guild-specific). + :return: + The new default balance. + :rtype: + str + :raises RuntimeError: + If the bank is guild-specific and guild was not provided. + :raises ValueError: + If the amount is invalid. """ amount = int(amount) if amount < 0: diff --git a/docs/framework_bank.rst b/docs/framework_bank.rst new file mode 100644 index 000000000..5cb50e629 --- /dev/null +++ b/docs/framework_bank.rst @@ -0,0 +1,42 @@ +.. V3 Bank + +.. role:: python(code) + :language: python + +==== +Bank +==== + +Bank has now been separated from Economy for V3. New to bank is support for +having a global bank. + +*********** +Basic Usage +*********** + +.. code-block:: python + + from core import bank + + class MyCog: + @commands.command() + async def balance(self, ctx, user: discord.Member=None): + if user is None: + user = ctx.author + bal = bank.get_balance(user) + currency = bank.get_currency_name(ctx.guild) + await ctx.send( + "{}'s balance is {} {}".format( + user.display_name, bal, currency + ) + ) + +************* +API Reference +************* + +Bank +====== + +.. automodule:: core.bank + :members: diff --git a/docs/index.rst b/docs/index.rst index c6778cac3..d7954d971 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,6 +16,7 @@ Welcome to Red - Discord Bot's documentation! :maxdepth: 2 :caption: Red Development Framework Reference: + framework_bank framework_config framework_downloader