Lint and add lint.sh dev script

This commit is contained in:
Andrew Morgan 2020-08-09 15:02:07 -07:00
parent 5b0c3dead3
commit af22f00868
10 changed files with 89 additions and 60 deletions

View file

@ -43,8 +43,10 @@ class Command(object):
async def _show_help(self): async def _show_help(self):
"""Show the help text""" """Show the help text"""
if not self.args: if not self.args:
text = ("Hello, I am a bot made with matrix-nio! Use `help commands` to view " text = (
"available commands.") "Hello, I am a bot made with matrix-nio! Use `help commands` to view "
"available commands."
)
await send_text_to_room(self.client, self.room.room_id, text) await send_text_to_room(self.client, self.room.room_id, text)
return return

View file

@ -1,15 +1,14 @@
import logging
from nio import JoinError
from my_project_name.bot_commands import Command from my_project_name.bot_commands import Command
from nio import (
JoinError,
)
from my_project_name.message_responses import Message from my_project_name.message_responses import Message
import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Callbacks(object): class Callbacks(object):
def __init__(self, client, store, config): def __init__(self, client, store, config):
""" """
Args: Args:
@ -57,7 +56,7 @@ class Callbacks(object):
# treat it as a command # treat it as a command
if has_command_prefix: if has_command_prefix:
# Remove the command prefix # Remove the command prefix
msg = msg[len(self.command_prefix):] msg = msg[len(self.command_prefix) :]
command = Command(self.client, self.store, self.config, msg, room, event) command = Command(self.client, self.store, self.config, msg, room, event)
await command.process() await command.process()
@ -72,7 +71,8 @@ class Callbacks(object):
if type(result) == JoinError: if type(result) == JoinError:
logger.error( logger.error(
f"Error joining room {room.room_id} (attempt %d): %s", f"Error joining room {room.room_id} (attempt %d): %s",
attempt, result.message, attempt,
result.message,
) )
else: else:
break break

View file

@ -1,18 +1,13 @@
import logging import logging
from nio import (
SendRetryError
)
from markdown import markdown from markdown import markdown
from nio import SendRetryError
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
async def send_text_to_room( async def send_text_to_room(
client, client, room_id, message, notice=True, markdown_convert=True
room_id,
message,
notice=True,
markdown_convert=True
): ):
"""Send text to a matrix room """Send text to a matrix room
@ -43,11 +38,7 @@ async def send_text_to_room(
try: try:
await client.room_send( await client.room_send(
room_id, room_id, "m.room.message", content, ignore_unverified_devices=True,
"m.room.message",
content,
ignore_unverified_devices=True,
) )
except SendRetryError: except SendRetryError:
logger.exception(f"Unable to send message response to {room_id}") logger.exception(f"Unable to send message response to {room_id}")

View file

@ -1,9 +1,11 @@
import logging import logging
import re
import os import os
import yaml import re
import sys import sys
from typing import List, Any from typing import Any, List
import yaml
from my_project_name.errors import ConfigError from my_project_name.errors import ConfigError
logger = logging.getLogger() logger = logging.getLogger()
@ -23,34 +25,48 @@ class Config(object):
self.config = yaml.safe_load(file_stream.read()) self.config = yaml.safe_load(file_stream.read())
# Logging setup # Logging setup
formatter = logging.Formatter('%(asctime)s | %(name)s [%(levelname)s] %(message)s') formatter = logging.Formatter(
"%(asctime)s | %(name)s [%(levelname)s] %(message)s"
)
log_level = self._get_cfg(["logging", "level"], default="INFO") log_level = self._get_cfg(["logging", "level"], default="INFO")
logger.setLevel(log_level) logger.setLevel(log_level)
file_logging_enabled = self._get_cfg(["logging", "file_logging", "enabled"], default=False) file_logging_enabled = self._get_cfg(
file_logging_filepath = self._get_cfg(["logging", "file_logging", "filepath"], default="bot.log") ["logging", "file_logging", "enabled"], default=False
)
file_logging_filepath = self._get_cfg(
["logging", "file_logging", "filepath"], default="bot.log"
)
if file_logging_enabled: if file_logging_enabled:
handler = logging.FileHandler(file_logging_filepath) handler = logging.FileHandler(file_logging_filepath)
handler.setFormatter(formatter) handler.setFormatter(formatter)
logger.addHandler(handler) logger.addHandler(handler)
console_logging_enabled = self._get_cfg(["logging", "console_logging", "enabled"], default=True) console_logging_enabled = self._get_cfg(
["logging", "console_logging", "enabled"], default=True
)
if console_logging_enabled: if console_logging_enabled:
handler = logging.StreamHandler(sys.stdout) handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(formatter) handler.setFormatter(formatter)
logger.addHandler(handler) logger.addHandler(handler)
# Storage setup # Storage setup
self.database_filepath = self._get_cfg(["storage", "database_filepath"], required=True) self.database_filepath = self._get_cfg(
self.store_filepath = self._get_cfg(["storage", "store_filepath"], required=True) ["storage", "database_filepath"], required=True
)
self.store_filepath = self._get_cfg(
["storage", "store_filepath"], required=True
)
# Create the store folder if it doesn't exist # Create the store folder if it doesn't exist
if not os.path.isdir(self.store_filepath): if not os.path.isdir(self.store_filepath):
if not os.path.exists(self.store_filepath): if not os.path.exists(self.store_filepath):
os.mkdir(self.store_filepath) os.mkdir(self.store_filepath)
else: else:
raise ConfigError(f"storage.store_filepath '{self.store_filepath}' is not a directory") raise ConfigError(
f"storage.store_filepath '{self.store_filepath}' is not a directory"
)
# Matrix bot account setup # Matrix bot account setup
self.user_id = self._get_cfg(["matrix", "user_id"], required=True) self.user_id = self._get_cfg(["matrix", "user_id"], required=True)
@ -59,16 +75,15 @@ class Config(object):
self.user_password = self._get_cfg(["matrix", "user_password"], required=True) self.user_password = self._get_cfg(["matrix", "user_password"], required=True)
self.device_id = self._get_cfg(["matrix", "device_id"], required=True) self.device_id = self._get_cfg(["matrix", "device_id"], required=True)
self.device_name = self._get_cfg(["matrix", "device_name"], default="nio-template") self.device_name = self._get_cfg(
["matrix", "device_name"], default="nio-template"
)
self.homeserver_url = self._get_cfg(["matrix", "homeserver_url"], required=True) self.homeserver_url = self._get_cfg(["matrix", "homeserver_url"], required=True)
self.command_prefix = self._get_cfg(["command_prefix"], default="!c") + " " self.command_prefix = self._get_cfg(["command_prefix"], default="!c") + " "
def _get_cfg( def _get_cfg(
self, self, path: List[str], default: Any = None, required: bool = True,
path: List[str],
default: Any = None,
required: bool = True,
) -> Any: ) -> Any:
"""Get a config option from a path and option name, specifying whether it is """Get a config option from a path and option name, specifying whether it is
required. required.

View file

@ -4,5 +4,6 @@ class ConfigError(RuntimeError):
Args: Args:
msg (str): The message displayed to the user on error msg (str): The message displayed to the user on error
""" """
def __init__(self, msg): def __init__(self, msg):
super(ConfigError, self).__init__("%s" % (msg,)) super(ConfigError, self).__init__("%s" % (msg,))

View file

@ -1,21 +1,19 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import logging
import asyncio import asyncio
import logging
import sys import sys
from time import sleep from time import sleep
from aiohttp import ClientConnectionError, ServerDisconnectedError
from nio import ( from nio import (
AsyncClient, AsyncClient,
AsyncClientConfig, AsyncClientConfig,
RoomMessageText,
InviteMemberEvent, InviteMemberEvent,
LoginError,
LocalProtocolError, LocalProtocolError,
LoginError,
RoomMessageText,
) )
from aiohttp import (
ServerDisconnectedError,
ClientConnectionError
)
from my_project_name.callbacks import Callbacks from my_project_name.callbacks import Callbacks
from my_project_name.config import Config from my_project_name.config import Config
from my_project_name.storage import Storage from my_project_name.storage import Storage
@ -64,13 +62,12 @@ async def main():
# Try to login with the configured username/password # Try to login with the configured username/password
try: try:
login_response = await client.login( login_response = await client.login(
password=config.user_password, password=config.user_password, device_name=config.device_name,
device_name=config.device_name,
) )
# Check if login failed # Check if login failed
if type(login_response) == LoginError: if type(login_response) == LoginError:
logger.error(f"Failed to login: %s", login_response.message) logger.error("Failed to login: %s", login_response.message)
return False return False
except LocalProtocolError as e: except LocalProtocolError as e:
# There's an edge case here where the user hasn't installed the correct C # There's an edge case here where the user hasn't installed the correct C
@ -78,7 +75,8 @@ async def main():
logger.fatal( logger.fatal(
"Failed to login. Have you installed the correct dependencies? " "Failed to login. Have you installed the correct dependencies? "
"https://github.com/poljar/matrix-nio#installation " "https://github.com/poljar/matrix-nio#installation "
"Error: %s", e "Error: %s",
e,
) )
return False return False
@ -101,4 +99,5 @@ async def main():
# Make sure to close the client connection on disconnect # Make sure to close the client connection on disconnect
await client.close() await client.close()
asyncio.get_event_loop().run_until_complete(main()) asyncio.get_event_loop().run_until_complete(main())

View file

@ -1,11 +1,11 @@
from my_project_name.chat_functions import send_text_to_room
import logging import logging
from my_project_name.chat_functions import send_text_to_room
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Message(object): class Message(object):
def __init__(self, client, store, config, message_content, room, event): def __init__(self, client, store, config, message_content, room, event):
"""Initialize a new Message """Initialize a new Message
@ -38,4 +38,3 @@ class Message(object):
"""Say hello""" """Say hello"""
text = "Hello, world!" text = "Hello, world!"
await send_text_to_room(self.client, self.room.room_id, text) await send_text_to_room(self.client, self.room.room_id, text)

View file

@ -1,6 +1,6 @@
import sqlite3
import os.path
import logging import logging
import os.path
import sqlite3
latest_db_version = 0 latest_db_version = 0
@ -34,10 +34,12 @@ class Storage(object):
self.cursor = self.conn.cursor() self.cursor = self.conn.cursor()
# Sync token table # Sync token table
self.cursor.execute("CREATE TABLE sync_token (" self.cursor.execute(
"dedupe_id INTEGER PRIMARY KEY, " "CREATE TABLE sync_token ("
"token TEXT NOT NULL" "dedupe_id INTEGER PRIMARY KEY, "
")") "token TEXT NOT NULL"
")"
)
logger.info("Database setup complete") logger.info("Database setup complete")

20
scripts-dev/lint.sh Executable file
View file

@ -0,0 +1,20 @@
#!/bin/sh
#
# Runs linting scripts over the local checkout
# isort - sorts import statements
# flake8 - lints and finds mistakes
# black - opinionated code formatter
set -e
if [ $# -ge 1 ]
then
files=$*
else
files="my_project_name my-project-name"
fi
echo "Linting these locations: $files"
isort $files
flake8 $files
python3 -m black $files

View file

@ -10,7 +10,7 @@ ignore=W503,W504,E203,E731,E501
[isort] [isort]
line_length = 88 line_length = 88
sections=FUTURE,STDLIB,COMPAT,THIRDPARTY,FIRSTPARTY,TESTS,LOCALFOLDER sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,TESTS,LOCALFOLDER
default_section=THIRDPARTY default_section=THIRDPARTY
known_first_party=my_project_name known_first_party=my_project_name
known_tests=tests known_tests=tests