aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar sco1 <[email protected]>2019-09-10 18:49:30 -0400
committerGravatar sco1 <[email protected]>2019-09-10 18:49:30 -0400
commit77c9b0f2194072b19616bad4ce81f72ebcdad27d (patch)
tree1c0efc3f8315617ef7dfdb24d62b5df21e3b29d6
parentDocstring linting chunk 3 (diff)
Docstring linting chunk 4
-rw-r--r--bot/cogs/bot.py71
-rw-r--r--bot/cogs/doc.py133
-rw-r--r--bot/cogs/error_handler.py6
-rw-r--r--bot/cogs/eval.py22
-rw-r--r--bot/cogs/jams.py13
-rw-r--r--bot/cogs/site.py28
-rw-r--r--bot/cogs/utils.py28
7 files changed, 125 insertions, 176 deletions
diff --git a/bot/cogs/bot.py b/bot/cogs/bot.py
index 828e2514c..be7922ef9 100644
--- a/bot/cogs/bot.py
+++ b/bot/cogs/bot.py
@@ -2,6 +2,7 @@ import ast
import logging
import re
import time
+from typing import Optional, Tuple, Union
from discord import Embed, Message, RawMessageUpdateEvent
from discord.ext.commands import Bot, Context, command, group
@@ -17,9 +18,7 @@ log = logging.getLogger(__name__)
class Bot:
- """
- Bot information commands
- """
+ """Bot information commands."""
def __init__(self, bot: Bot):
self.bot = bot
@@ -46,20 +45,14 @@ class Bot:
@group(invoke_without_command=True, name="bot", hidden=True)
@with_role(Roles.verified)
- async def bot_group(self, ctx: Context):
- """
- Bot informational commands
- """
-
+ async def bot_group(self, ctx: Context) -> None:
+ """Bot informational commands."""
await ctx.invoke(self.bot.get_command("help"), "bot")
@bot_group.command(name='about', aliases=('info',), hidden=True)
@with_role(Roles.verified)
- async def about_command(self, ctx: Context):
- """
- Get information about the bot
- """
-
+ async def about_command(self, ctx: Context) -> None:
+ """Get information about the bot."""
embed = Embed(
description="A utility bot designed just for the Python server! Try `!help` for more info.",
url="https://gitlab.com/discord-python/projects/bot"
@@ -77,24 +70,18 @@ class Bot:
@command(name='echo', aliases=('print',))
@with_role(*MODERATION_ROLES)
- async def echo_command(self, ctx: Context, *, text: str):
- """
- Send the input verbatim to the current channel
- """
-
+ async def echo_command(self, ctx: Context, *, text: str) -> None:
+ """Send the input verbatim to the current channel."""
await ctx.send(text)
@command(name='embed')
@with_role(*MODERATION_ROLES)
- async def embed_command(self, ctx: Context, *, text: str):
- """
- Send the input within an embed to the current channel
- """
-
+ async def embed_command(self, ctx: Context, *, text: str) -> None:
+ """Send the input within an embed to the current channel."""
embed = Embed(description=text)
await ctx.send(embed=embed)
- def codeblock_stripping(self, msg: str, bad_ticks: bool):
+ def codeblock_stripping(self, msg: str, bad_ticks: bool) -> Union[Tuple[Tuple[str, Optional[str]], str], None]:
"""
Strip msg in order to find Python code.
@@ -163,15 +150,10 @@ class Bot:
log.trace(f"Returning message.\n\n{content}\n\n")
return (content,), repl_code
- def fix_indentation(self, msg: str):
- """
- Attempts to fix badly indented code.
- """
-
- def unindent(code, skip_spaces=0):
- """
- Unindents all code down to the number of spaces given ins skip_spaces
- """
+ def fix_indentation(self, msg: str) -> str:
+ """Attempts to fix badly indented code."""
+ def unindent(code, skip_spaces: int = 0) -> str:
+ """Unindents all code down to the number of spaces given in skip_spaces."""
final = ""
current = code[0]
leading_spaces = 0
@@ -207,11 +189,13 @@ class Bot:
msg = f"{first_line}\n{unindent(code, 4)}"
return msg
- def repl_stripping(self, msg: str):
+ def repl_stripping(self, msg: str) -> Tuple[str, bool]:
"""
Strip msg in order to extract Python code out of REPL output.
Tries to strip out REPL Python code out of msg and returns the stripped msg.
+
+ Returns a second boolean output if REPL code was found in the input msg.
"""
final = ""
for line in msg.splitlines(keepends=True):
@@ -225,7 +209,8 @@ class Bot:
log.trace(f"Found REPL code in \n\n{msg}\n\n")
return final.rstrip(), True
- def has_bad_ticks(self, msg: Message):
+ def has_bad_ticks(self, msg: Message) -> bool:
+ """Check to see if msg contains ticks that aren't '`'."""
not_backticks = [
"'''", '"""', "\u00b4\u00b4\u00b4", "\u2018\u2018\u2018", "\u2019\u2019\u2019",
"\u2032\u2032\u2032", "\u201c\u201c\u201c", "\u201d\u201d\u201d", "\u2033\u2033\u2033",
@@ -234,13 +219,13 @@ class Bot:
return msg.content[:3] in not_backticks
- async def on_message(self, msg: Message):
- """
- Detect poorly formatted Python code and send the user
- a helpful message explaining how to do properly
- formatted Python syntax highlighting codeblocks.
+ async def on_message(self, msg: Message) -> None:
"""
+ Detect poorly formatted Python code in new messages.
+ If poorly formatted code is detected, send the user a helpful message explaining how to do
+ properly formatted Python syntax highlighting codeblocks.
+ """
parse_codeblock = (
(
msg.channel.id in self.channel_cooldowns
@@ -355,7 +340,8 @@ class Bot:
f"The message that was posted was:\n\n{msg.content}\n\n"
)
- async def on_raw_message_edit(self, payload: RawMessageUpdateEvent):
+ async def on_raw_message_edit(self, payload: RawMessageUpdateEvent) -> None:
+ """Check to see if an edited message (previously called out) still contains poorly formatted code."""
if (
# Checks to see if the message was called out by the bot
payload.message_id not in self.codeblock_message_ids
@@ -381,6 +367,7 @@ class Bot:
log.trace("User's incorrect code block has been fixed. Removing bot formatting message.")
-def setup(bot):
+def setup(bot: Bot) -> None:
+ """Bot cog load."""
bot.add_cog(Bot(bot))
log.info("Cog loaded: Bot")
diff --git a/bot/cogs/doc.py b/bot/cogs/doc.py
index aa49b0c25..ef14d1797 100644
--- a/bot/cogs/doc.py
+++ b/bot/cogs/doc.py
@@ -4,10 +4,11 @@ import logging
import re
import textwrap
from collections import OrderedDict
-from typing import Optional, Tuple
+from typing import Callable, Optional, Tuple
import discord
from bs4 import BeautifulSoup
+from bs4.element import PageElement
from discord.ext import commands
from markdownify import MarkdownConverter
from requests import ConnectionError
@@ -27,24 +28,22 @@ UNWANTED_SIGNATURE_SYMBOLS = ('[source]', '¶')
WHITESPACE_AFTER_NEWLINES_RE = re.compile(r"(?<=\n\n)(\s+)")
-def async_cache(max_size=128, arg_offset=0):
+def async_cache(max_size: int = 128, arg_offset: int = 0) -> Callable:
"""
LRU cache implementation for coroutines.
- :param max_size:
- Specifies the maximum size the cache should have.
- Once it exceeds the maximum size, keys are deleted in FIFO order.
- :param arg_offset:
- The offset that should be applied to the coroutine's arguments
- when creating the cache key. Defaults to `0`.
- """
+ Once the cache exceeds the maximum size, keys are deleted in FIFO order.
+ An offset may be optionally provided to be applied to the coroutine's arguments when creating the cache key.
+ """
# Assign the cache to the function itself so we can clear it from outside.
async_cache.cache = OrderedDict()
- def decorator(function):
+ def decorator(function: Callable) -> Callable:
+ """Define the async_cache decorator."""
@functools.wraps(function)
- async def wrapper(*args):
+ async def wrapper(*args) -> OrderedDict:
+ """Decorator wrapper for the caching logic."""
key = ':'.join(args[arg_offset:])
value = async_cache.cache.get(key)
@@ -59,27 +58,25 @@ def async_cache(max_size=128, arg_offset=0):
class DocMarkdownConverter(MarkdownConverter):
- def convert_code(self, el, text):
- """Undo `markdownify`s underscore escaping."""
+ """Subclass markdownify's MarkdownCoverter to provide custom conversion methods."""
+ def convert_code(self, el: PageElement, text: str) -> str:
+ """Undo `markdownify`s underscore escaping."""
return f"`{text}`".replace('\\', '')
- def convert_pre(self, el, text):
+ def convert_pre(self, el: PageElement, text: str) -> str:
"""Wrap any codeblocks in `py` for syntax highlighting."""
-
code = ''.join(el.strings)
return f"```py\n{code}```"
-def markdownify(html):
+def markdownify(html: str) -> DocMarkdownConverter:
+ """Create a DocMarkdownConverter object from the input html."""
return DocMarkdownConverter(bullets='•').convert(html)
class DummyObject(object):
- """
- A dummy object which supports assigning anything,
- which the builtin `object()` does not support normally.
- """
+ """A dummy object which supports assigning anything, which the builtin `object()` does not support normally."""
class SphinxConfiguration:
@@ -94,14 +91,15 @@ class InventoryURL(commands.Converter):
"""
Represents an Intersphinx inventory URL.
- This converter checks whether intersphinx
- accepts the given inventory URL, and raises
+ This converter checks whether intersphinx accepts the given inventory URL, and raises
`BadArgument` if that is not the case.
+
Otherwise, it simply passes through the given URL.
"""
@staticmethod
- async def convert(ctx, url: str):
+ async def convert(ctx: commands.Context, url: str) -> str:
+ """Convert url to Intersphinx inventory URL."""
try:
intersphinx.fetch_inventory(SphinxConfiguration(), '', url)
except AttributeError:
@@ -121,30 +119,32 @@ class InventoryURL(commands.Converter):
class Doc:
- def __init__(self, bot):
+ """A set of commands for querying & displaying documentation."""
+
+ def __init__(self, bot: commands.Bot):
self.base_urls = {}
self.bot = bot
self.inventories = {}
- async def on_ready(self):
+ async def on_ready(self) -> None:
+ """Refresh documentation inventory."""
await self.refresh_inventory()
async def update_single(
self, package_name: str, base_url: str, inventory_url: str, config: SphinxConfiguration
- ):
+ ) -> None:
"""
Rebuild the inventory for a single package.
- :param package_name: The package name to use, appears in the log.
- :param base_url: The root documentation URL for the specified package.
- Used to build absolute paths that link to specific symbols.
- :param inventory_url: The absolute URL to the intersphinx inventory.
- Fetched by running `intersphinx.fetch_inventory` in an
- executor on the bot's event loop.
- :param config: A `SphinxConfiguration` instance to mock the regular sphinx
- project layout. Required for use with intersphinx.
+ Where:
+ * `package_name` is the package name to use, appears in the log
+ * `base_url` is the root documentation URL for the specified package, used to build
+ absolute paths that link to specific symbols
+ * `inventory_url` is the absolute URL to the intersphinx inventory, fetched by running
+ `intersphinx.fetch_inventory` in an executor on the bot's event loop
+ * `config` is a `SphinxConfiguration` instance to mock the regular sphinx
+ project layout, required for use with intersphinx
"""
-
self.base_urls[package_name] = base_url
fetch_func = functools.partial(intersphinx.fetch_inventory, config, '', inventory_url)
@@ -158,7 +158,8 @@ class Doc:
log.trace(f"Fetched inventory for {package_name}.")
- async def refresh_inventory(self):
+ async def refresh_inventory(self) -> None:
+ """Refresh internal documentation inventory."""
log.debug("Refreshing documentation inventory...")
# Clear the old base URLS and inventories to ensure
@@ -185,16 +186,13 @@ class Doc:
"""
Given a Python symbol, return its signature and description.
- :param symbol: The symbol for which HTML data should be returned.
- :return:
- A tuple in the form (str, str), or `None`.
- The first tuple element is the signature of the given
- symbol as a markup-free string, and the second tuple
- element is the description of the given symbol with HTML
- markup included. If the given symbol could not be found,
- returns `None`.
- """
+ Returns a tuple in the form (str, str), or `None`.
+ The first tuple element is the signature of the given symbol as a markup-free string, and
+ the second tuple element is the description of the given symbol with HTML markup included.
+
+ If the given symbol could not be found, returns `None`.
+ """
url = self.inventories.get(symbol)
if url is None:
return None
@@ -222,16 +220,10 @@ class Doc:
@async_cache(arg_offset=1)
async def get_symbol_embed(self, symbol: str) -> Optional[discord.Embed]:
"""
- Using `get_symbol_html`, attempt to scrape and
- fetch the data for the given `symbol`, and build
- a formatted embed out of its contents.
-
- :param symbol: The symbol for which the embed should be returned
- :return:
- If the symbol is known, an Embed with documentation about it.
- Otherwise, `None`.
- """
+ Attempt to scrape and fetch the data for the given `symbol`, and build an embed from its contents.
+ If the symbol is known, an Embed with documentation about it is returned.
+ """
scraped_html = await self.get_symbol_html(symbol)
if scraped_html is None:
return None
@@ -266,20 +258,16 @@ class Doc:
)
@commands.group(name='docs', aliases=('doc', 'd'), invoke_without_command=True)
- async def docs_group(self, ctx, symbol: commands.clean_content = None):
+ async def docs_group(self, ctx: commands.Context, symbol: commands.clean_content = None) -> None:
"""Lookup documentation for Python symbols."""
-
await ctx.invoke(self.get_command)
@docs_group.command(name='get', aliases=('g',))
- async def get_command(self, ctx, symbol: commands.clean_content = None):
+ async def get_command(self, ctx: commands.Context, symbol: commands.clean_content = None) -> None:
"""
Return a documentation embed for a given symbol.
- If no symbol is given, return a list of all available inventories.
- :param ctx: Discord message context
- :param symbol: The symbol for which documentation should be returned,
- or nothing to get a list of all inventories
+ If no symbol is given, return a list of all available inventories.
Examples:
!docs
@@ -287,7 +275,6 @@ class Doc:
!docs aiohttp.ClientSession
!docs get aiohttp.ClientSession
"""
-
if symbol is None:
inventory_embed = discord.Embed(
title=f"All inventories (`{len(self.base_urls)}` total)",
@@ -321,18 +308,13 @@ class Doc:
@docs_group.command(name='set', aliases=('s',))
@with_role(*MODERATION_ROLES)
async def set_command(
- self, ctx, package_name: ValidPythonIdentifier,
+ self, ctx: commands.Context, package_name: ValidPythonIdentifier,
base_url: ValidURL, inventory_url: InventoryURL
- ):
+ ) -> None:
"""
Adds a new documentation metadata object to the site's database.
- The database will update the object, should an existing item
- with the specified `package_name` already exist.
- :param ctx: Discord message context
- :param package_name: The package name, for example `aiohttp`.
- :param base_url: The package documentation's root URL, used to build absolute links.
- :param inventory_url: The intersphinx inventory URL.
+ The database will update the object, should an existing item with the specified `package_name` already exist.
Example:
!docs set \
@@ -340,7 +322,6 @@ class Doc:
https://discordpy.readthedocs.io/en/rewrite/ \
https://discordpy.readthedocs.io/en/rewrite/objects.inv
"""
-
body = {
'package': package_name,
'base_url': base_url,
@@ -364,17 +345,13 @@ class Doc:
@docs_group.command(name='delete', aliases=('remove', 'rm', 'd'))
@with_role(*MODERATION_ROLES)
- async def delete_command(self, ctx, package_name: ValidPythonIdentifier):
+ async def delete_command(self, ctx: commands.Context, package_name: ValidPythonIdentifier) -> None:
"""
Removes the specified package from the database.
- :param ctx: Discord message context
- :param package_name: The package name, for example `aiohttp`.
-
Examples:
!docs delete aiohttp
"""
-
await self.bot.api_client.delete(f'bot/documentation-links/{package_name}')
async with ctx.typing():
@@ -384,5 +361,7 @@ class Doc:
await ctx.send(f"Successfully deleted `{package_name}` and refreshed inventory.")
-def setup(bot):
+def setup(bot: commands.Bot) -> None:
+ """Doc cog load."""
bot.add_cog(Doc(bot))
+ log.info("Cog loaded: Doc")
diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py
index 2063df09d..f8a27fda8 100644
--- a/bot/cogs/error_handler.py
+++ b/bot/cogs/error_handler.py
@@ -24,7 +24,8 @@ class ErrorHandler:
def __init__(self, bot: Bot):
self.bot = bot
- async def on_command_error(self, ctx: Context, e: CommandError):
+ async def on_command_error(self, ctx: Context, e: CommandError) -> None:
+ """Provide command error handling."""
command = ctx.command
parent = None
@@ -87,6 +88,7 @@ class ErrorHandler:
raise e
-def setup(bot: Bot):
+def setup(bot: Bot) -> None:
+ """Error handler cog load."""
bot.add_cog(ErrorHandler(bot))
log.info("Cog loaded: Events")
diff --git a/bot/cogs/eval.py b/bot/cogs/eval.py
index 8e97a35a2..5fbd9dca5 100644
--- a/bot/cogs/eval.py
+++ b/bot/cogs/eval.py
@@ -6,6 +6,7 @@ import re
import textwrap
import traceback
from io import StringIO
+from typing import Any, Tuple, Union
import discord
from discord.ext.commands import Bot, group
@@ -18,10 +19,7 @@ log = logging.getLogger(__name__)
class CodeEval:
- """
- Owner and admin feature that evaluates code
- and returns the result to the channel.
- """
+ """Owner and admin feature that evaluates code and returns the result to the channel."""
def __init__(self, bot: Bot):
self.bot = bot
@@ -31,7 +29,8 @@ class CodeEval:
self.interpreter = Interpreter(bot)
- def _format(self, inp, out): # (str, Any) -> (str, discord.Embed)
+ def _format(self, inp: str, out: Any) -> Tuple[str, Union[discord.embed, None]]:
+ """Format the eval output into a string & attempt to format it into an Embed."""
self._ = out
res = ""
@@ -124,7 +123,8 @@ class CodeEval:
return res # Return (text, embed)
- async def _eval(self, ctx, code): # (discord.Context, str) -> None
+ async def _eval(self, ctx: discord.Context, code: str) -> None:
+ """Eval the input code string & send an embed to the invoking context."""
self.ln += 1
if code.startswith("exit"):
@@ -174,16 +174,15 @@ async def func(): # (None,) -> Any
@group(name='internal', aliases=('int',))
@with_role(Roles.owner, Roles.admin)
- async def internal_group(self, ctx):
+ async def internal_group(self, ctx: discord.Context) -> None:
"""Internal commands. Top secret!"""
-
if not ctx.invoked_subcommand:
await ctx.invoke(self.bot.get_command("help"), "internal")
@internal_group.command(name='eval', aliases=('e',))
@with_role(Roles.admin, Roles.owner)
- async def eval(self, ctx, *, code: str):
- """ Run eval in a REPL-like format. """
+ async def eval(self, ctx: discord.Context, *, code: str) -> None:
+ """Run eval in a REPL-like format."""
code = code.strip("`")
if re.match('py(thon)?\n', code):
code = "\n".join(code.split("\n")[1:])
@@ -197,6 +196,7 @@ async def func(): # (None,) -> Any
await self._eval(ctx, code)
-def setup(bot):
+def setup(bot: Bot) -> None:
+ """Code eval cog load."""
bot.add_cog(CodeEval(bot))
log.info("Cog loaded: Eval")
diff --git a/bot/cogs/jams.py b/bot/cogs/jams.py
index 96b98e559..f7a5896c0 100644
--- a/bot/cogs/jams.py
+++ b/bot/cogs/jams.py
@@ -10,9 +10,7 @@ log = logging.getLogger(__name__)
class CodeJams:
- """
- Manages the code-jam related parts of our server
- """
+ """Manages the code-jam related parts of our server."""
def __init__(self, bot: commands.Bot):
self.bot = bot
@@ -22,14 +20,12 @@ class CodeJams:
async def createteam(
self, ctx: commands.Context,
team_name: str, members: commands.Greedy[Member]
- ):
+ ) -> None:
"""
- Create a team channel (both voice and text) in the Code Jams category, assign roles
- and then add overwrites for the team.
+ Create team channels (voice and text) in the Code Jams category, assign roles, and add overwrites for the team.
The first user passed will always be the team leader.
"""
-
# We had a little issue during Code Jam 4 here, the greedy converter did it's job
# and ignored anything which wasn't a valid argument which left us with teams of
# two members or at some times even 1 member. This fixes that by checking that there
@@ -105,6 +101,7 @@ class CodeJams:
await ctx.send(f":ok_hand: Team created: {team_channel.mention}")
-def setup(bot):
+def setup(bot: commands.Bot) -> None:
+ """Code Jams cog load."""
bot.add_cog(CodeJams(bot))
log.info("Cog loaded: CodeJams")
diff --git a/bot/cogs/site.py b/bot/cogs/site.py
index 37bf4f4ea..a941f27a7 100644
--- a/bot/cogs/site.py
+++ b/bot/cogs/site.py
@@ -19,15 +19,13 @@ class Site:
self.bot = bot
@group(name="site", aliases=("s",), invoke_without_command=True)
- async def site_group(self, ctx):
+ async def site_group(self, ctx: Context) -> None:
"""Commands for getting info about our website."""
-
await ctx.invoke(self.bot.get_command("help"), "site")
@site_group.command(name="home", aliases=("about",))
- async def site_main(self, ctx: Context):
+ async def site_main(self, ctx: Context) -> None:
"""Info about the website itself."""
-
url = f"{URLs.site_schema}{URLs.site}/"
embed = Embed(title="Python Discord website")
@@ -43,9 +41,8 @@ class Site:
await ctx.send(embed=embed)
@site_group.command(name="resources")
- async def site_resources(self, ctx: Context):
+ async def site_resources(self, ctx: Context) -> None:
"""Info about the site's Resources page."""
-
url = f"{INFO_URL}/resources"
embed = Embed(title="Resources")
@@ -60,9 +57,8 @@ class Site:
await ctx.send(embed=embed)
@site_group.command(name="help")
- async def site_help(self, ctx: Context):
+ async def site_help(self, ctx: Context) -> None:
"""Info about the site's Getting Help page."""
-
url = f"{INFO_URL}/help"
embed = Embed(title="Getting Help")
@@ -77,9 +73,8 @@ class Site:
await ctx.send(embed=embed)
@site_group.command(name="faq")
- async def site_faq(self, ctx: Context):
+ async def site_faq(self, ctx: Context) -> None:
"""Info about the site's FAQ page."""
-
url = f"{INFO_URL}/faq"
embed = Embed(title="FAQ")
@@ -96,14 +91,8 @@ class Site:
@site_group.command(aliases=['r', 'rule'], name='rules')
@redirect_output(destination_channel=Channels.bot, bypass_roles=STAFF_ROLES)
- async def site_rules(self, ctx: Context, *rules: int):
- """
- Provides a link to the `rules` endpoint of the website, or displays
- specific rules, if they are requested.
-
- **`ctx`:** The Discord message context
- **`rules`:** The rules a user wants to get.
- """
+ async def site_rules(self, ctx: Context, *rules: int) -> None:
+ """Provides a link to the `rules` endpoint of the website, or displays specific rule(s), if requested."""
rules_embed = Embed(title='Rules', color=Colour.blurple())
rules_embed.url = f"{URLs.site_schema}{URLs.site}/about/rules"
@@ -135,6 +124,7 @@ class Site:
await LinePaginator.paginate(final_rules, ctx, rules_embed, max_lines=3)
-def setup(bot):
+def setup(bot: Bot) -> None:
+ """Site cog load."""
bot.add_cog(Site(bot))
log.info("Cog loaded: Site")
diff --git a/bot/cogs/utils.py b/bot/cogs/utils.py
index 0c6d9d2ba..09e8f70d6 100644
--- a/bot/cogs/utils.py
+++ b/bot/cogs/utils.py
@@ -6,7 +6,7 @@ from email.parser import HeaderParser
from io import StringIO
from discord import Colour, Embed
-from discord.ext.commands import AutoShardedBot, Context, command
+from discord.ext.commands import Bot, CheckFailure, Context, command
from bot.constants import Channels, NEGATIVE_REPLIES, STAFF_ROLES
from bot.decorators import InChannelCheckFailure, in_channel
@@ -15,22 +15,17 @@ log = logging.getLogger(__name__)
class Utils:
- """
- A selection of utilities which don't have a clear category.
- """
+ """A selection of utilities which don't have a clear category."""
- def __init__(self, bot: AutoShardedBot):
+ def __init__(self, bot: Bot):
self.bot = bot
self.base_pep_url = "http://www.python.org/dev/peps/pep-"
self.base_github_pep_url = "https://raw.githubusercontent.com/python/peps/master/pep-"
@command(name='pep', aliases=('get_pep', 'p'))
- async def pep_command(self, ctx: Context, pep_number: str):
- """
- Fetches information about a PEP and sends it to the channel.
- """
-
+ async def pep_command(self, ctx: Context, pep_number: str) -> None:
+ """Fetches information about a PEP and sends it to the channel."""
if pep_number.isdigit():
pep_number = int(pep_number)
else:
@@ -90,11 +85,8 @@ class Utils:
@command()
@in_channel(Channels.bot, bypass_roles=STAFF_ROLES)
- async def charinfo(self, ctx, *, characters: str):
- """
- Shows you information on up to 25 unicode characters.
- """
-
+ async def charinfo(self, ctx: Context, *, characters: str) -> None:
+ """Shows you information on up to 25 unicode characters."""
match = re.match(r"<(a?):(\w+):(\d+)>", characters)
if match:
embed = Embed(
@@ -133,7 +125,8 @@ class Utils:
await ctx.send(embed=embed)
- async def __error(self, ctx, error):
+ async def __error(self, ctx: Context, error: CheckFailure) -> None:
+ """Send Check failure error to invoking context if command is invoked in a blacklisted channel by non-staff."""
embed = Embed(colour=Colour.red())
if isinstance(error, InChannelCheckFailure):
embed.title = random.choice(NEGATIVE_REPLIES)
@@ -141,6 +134,7 @@ class Utils:
await ctx.send(embed=embed)
-def setup(bot):
+def setup(bot: Bot) -> None:
+ """Utils cog load."""
bot.add_cog(Utils(bot))
log.info("Cog loaded: Utils")