Added black formatter to pre-commit hook

develop
Jef Roosens 2020-09-01 09:17:09 +02:00
parent 6f2d9d1dde
commit 7a7bd6fed4
14 changed files with 127 additions and 70 deletions

View File

@ -3,8 +3,8 @@
# This hooks runs tests and checks if the linter doesn't hate you
# Linting
printf "flake8....."
make lint > /dev/null 2>&1 && printf "OK!\n" || { printf "Fail." && exit 1; }
printf "black......"
make format > /dev/null 2>&1 && printf "OK!\n" || { printf "Fail." && exit 1; }
# Running tests
printf "pytest....."

View File

@ -69,6 +69,11 @@ test: pytest.ini build-venv
lint: build-venv
@ "$(VENV)/bin/flake8" "$(SRC)"/**/*.py
# =====FORMATTING=====
# Run black
format: build-venv
@ "$(VENV)/bin/black" '$(SRC)'
# =====PACKAGING=====
package: README.md LICENSE setup.py test clean-setup

View File

@ -1,18 +1,25 @@
from .frank import Frank
from .module import (
Module, command, Command, default, Default, daemon, Daemon,
regex_command, RegexCommand,
Module,
command,
Command,
default,
Default,
daemon,
Daemon,
regex_command,
RegexCommand,
)
__all__ = [
'Frank',
'Module',
'command',
'Command',
'default',
'Default',
'daemon',
'Daemon',
'regex_command',
'RegexCommand',
"Frank",
"Module",
"command",
"Command",
"default",
"Default",
"daemon",
"Daemon",
"regex_command",
"RegexCommand",
]

View File

@ -11,6 +11,7 @@ import discord
# Typing imports
from typing import TYPE_CHECKING, List
if TYPE_CHECKING:
# Own imports
from .module import Module
@ -23,8 +24,12 @@ class Frank(discord.Client):
their own behavior.
"""
def __init__(self, modules: List[Module], config_file: str = 'frank.yaml',
prefix: str = 'fr'):
def __init__(
self,
modules: List[Module],
config_file: str = "frank.yaml",
prefix: str = "fr",
):
"""
Args:
modules: modules to load
@ -39,7 +44,7 @@ class Frank(discord.Client):
self.PREFIX = prefix
try:
with open(config_file, 'r') as f:
with open(config_file, "r") as f:
self._config = yaml.load(f, Loader=yaml.FullLoader)
except FileNotFoundError:
@ -50,7 +55,7 @@ class Frank(discord.Client):
Runs when the bot has succesfully connected to Discord
"""
print('Connected')
print("Connected")
# Startup all modules
for module in self._modules:
@ -63,7 +68,7 @@ class Frank(discord.Client):
await loaded._start()
self._loaded_modules.append(loaded)
print('All modules loaded')
print("All modules loaded")
async def stop(self):
"""
@ -92,9 +97,14 @@ class Frank(discord.Client):
if not (cmd and cmd[0] == self.PREFIX):
return
module = next((mod for mod in self._loaded_modules
if mod.match(cmd[1])), None)
module = next(
(mod for mod in self._loaded_modules if mod.match(cmd[1])), None
)
if module:
await module(cmd=cmd[2:], author=message.author,
channel=message.channel, mid=message.id)
await module(
cmd=cmd[2:],
author=message.author,
channel=message.channel,
mid=message.id,
)

View File

@ -1,18 +1,24 @@
from .module import Module
from .decorators import (
command, Command, default, Default, daemon, Daemon, regex_command,
command,
Command,
default,
Default,
daemon,
Daemon,
regex_command,
RegexCommand,
)
__all__ = [
'Module',
'command',
'Command',
'default',
'Default',
'daemon',
'Daemon',
'regex_command',
'RegexCommand',
"Module",
"command",
"Command",
"default",
"Default",
"daemon",
"Daemon",
"regex_command",
"RegexCommand",
]

View File

@ -2,12 +2,12 @@ from .classes import Command, RegexCommand, Daemon, Default
from .functions import command, regex_command, daemon, default
__all__ = [
'command',
'Command',
'regex_command',
'RegexCommand',
'default',
'Default',
'daemon',
'Daemon',
"command",
"Command",
"regex_command",
"RegexCommand",
"default",
"Default",
"daemon",
"Daemon",
]

View File

@ -8,6 +8,7 @@ import asyncio
# Typing imports
from typing import TYPE_CHECKING
if TYPE_CHECKING:
# Built-in imports
from typing import Union
@ -120,6 +121,7 @@ class Daemon(Simple):
# If an interval > 0 is given, it wraps the function inside an infinite
# loop with the desired delay
if interval > 0:
async def loop(self, *args, **kwargs):
while True:
# TODO: does this make func and sleep run at the same time?

View File

@ -7,6 +7,7 @@ from .classes import Command, RegexCommand, Daemon, Default
# Typing imports
from typing import TYPE_CHECKING
if TYPE_CHECKING:
# Built-in imports
from typing import Union

View File

@ -7,4 +7,4 @@ class DuplicateCommand(Exception):
class MultipleDefaults(Exception):
message = 'Multiple default commands detected'
message = "Multiple default commands detected"

View File

@ -10,6 +10,7 @@ from .decorators import Command, Daemon, Default, RegexCommand
# Typing imports
from typing import TYPE_CHECKING
if TYPE_CHECKING:
# Built-in imports
from typing import List, Any
@ -18,7 +19,7 @@ if TYPE_CHECKING:
class ModuleMeta:
def _filter_attrs(self, condition: callable[[Any], bool]) -> List[Any]:
# This prevents an infinite loop of getting the attribute
illegal_names = ['commands', 'daemons', 'default']
illegal_names = ["commands", "daemons", "default"]
output = []
@ -36,8 +37,10 @@ class ModuleMeta:
# The sort puts all the RegexCommand objects at the back, making them
# be matched last
return sorted(self._filter_attrs(lambda val: isinstance(val, Command)),
key=lambda x: isinstance(x, RegexCommand))
return sorted(
self._filter_attrs(lambda val: isinstance(val, Command)),
key=lambda x: isinstance(x, RegexCommand),
)
@cached_property
def daemons(self) -> List[Daemon]:
@ -45,5 +48,6 @@ class ModuleMeta:
@cached_property
def default(self) -> Default:
return next(iter(self._filter_attrs(
lambda val: isinstance(val, Default))), None)
return next(
iter(self._filter_attrs(lambda val: isinstance(val, Default))), None
)

View File

@ -12,6 +12,7 @@ from .decorators import RegexCommand
# Typing imports
from typing import TYPE_CHECKING
if TYPE_CHECKING:
# Built-in imports
from typing import List, Dict
@ -33,13 +34,13 @@ class Module(ModuleMeta):
Prefix to activate this module.
"""
NAME = ''
NAME = ""
"""
The name is used in various places, such as the config file and the
help function.
"""
HELP = ''
HELP = ""
"""
Short description of the module to use in the help function.
"""
@ -84,8 +85,9 @@ class Module(ModuleMeta):
for task in self._tasks:
task.cancel()
async def __call__(self, cmd: List[str], author: User,
channel: Messageable, mid: int):
async def __call__(
self, cmd: List[str], author: User, channel: Messageable, mid: int
):
"""
Execute the command, if found.
@ -97,21 +99,26 @@ class Module(ModuleMeta):
"""
if cmd:
func = next((func for func in self.commands
if func.match(cmd[0])), None)
func = next(
(func for func in self.commands if func.match(cmd[0])), None
)
# Throw error if no function is found
if not func:
raise InvalidCommand(f'Unknown command: {cmd}')
raise InvalidCommand(f"Unknown command: {cmd}")
# A RegexCommand can use the prefix, as it's not a fixed string
if isinstance(func, RegexCommand):
await func(prefix=cmd[0], cmd=cmd[1:], author=author,
channel=channel, mid=mid)
await func(
prefix=cmd[0],
cmd=cmd[1:],
author=author,
channel=channel,
mid=mid,
)
else:
await func(cmd=cmd[1:], author=author, channel=channel,
mid=mid)
await func(cmd=cmd[1:], author=author, channel=channel, mid=mid)
elif self.default:
await self.default(author=author, channel=channel, mid=mid)

View File

@ -2,5 +2,5 @@ from .help import HelpMod
__all__ = [
'HelpMod',
"HelpMod",
]

View File

@ -10,6 +10,7 @@ from .. import Module, default, regex_command
# Typing imports
from typing import TYPE_CHECKING
if TYPE_CHECKING:
# Built-in imports
from typing import List
@ -24,11 +25,11 @@ class HelpMod(Module):
other modules.
"""
PREFIX = 'help'
NAME = 'help'
HELP = 'Shows help info about all modules'
PREFIX = "help"
NAME = "help"
HELP = "Shows help info about all modules"
@default(help_str='Show help about all modules.')
@default(help_str="Show help about all modules.")
async def send_all(self, author: User, channel: Messageable, mid: int):
embed = Embed()
@ -37,20 +38,33 @@ class HelpMod(Module):
await channel.send(embed=embed)
@regex_command(pattern='.+', help_str='Show help about a certain module.')
async def show_module_help(self, prefix: str, cmd: List[str], author: User,
channel: Messageable, mid: int):
@regex_command(pattern=".+", help_str="Show help about a certain module.")
async def show_module_help(
self,
prefix: str,
cmd: List[str],
author: User,
channel: Messageable,
mid: int,
):
# Yes, this command just ignores cmd at the moment
mod_name = prefix.lower()
mod = next((mod for mod in self._client._modules
if mod.NAME.lower() == mod_name), None)
mod = next(
(
mod
for mod in self._client._modules
if mod.NAME.lower() == mod_name
),
None,
)
if mod:
embed = Embed()
if mod.default:
embed.add_field(name='default', value=mod.default.help_str,
inline=False)
embed.add_field(
name="default", value=mod.default.help_str, inline=False
)
for cmd in mod._COMMANDS:
embed.add_field(name=cmd.cmd, value=mod.help_str, inline=False)

View File

@ -13,3 +13,4 @@ pytest-asyncio>=0.14.0,<1.0.0
twine>=3.2.0,<4.0.0
Sphinx==3.2.1
sphinx-rtd-theme==0.5.0
black