diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..3b71da3 --- /dev/null +++ b/.flake8 @@ -0,0 +1,18 @@ +[flake8] +exclude = + .git, + .github, + .mypy_cache, + .pytest_cache, + __pycache__, + alembic, + htmlcov, + tests, + venv +ignore=E203 +max-line-length = 120 +per-file-ignores = + # Missing __all__, main isn't supposed to be imported + main.py: DALL000, + # Missing __all__, Cogs aren't modules + ./didier/cogs/*: DALL000 \ No newline at end of file diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index ebcf246..b083e02 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -78,7 +78,7 @@ jobs: - name: Install dependencies run: pip3 install -r requirements.txt -r requirements-dev.txt - name: Linting - run: pylint didier database + run: flake8 typing: needs: [dependencies] runs-on: ubuntu-latest diff --git a/database/crud/currency.py b/database/crud/currency.py index 8e7f2e6..f72b653 100644 --- a/database/crud/currency.py +++ b/database/crud/currency.py @@ -6,8 +6,23 @@ from sqlalchemy.ext.asyncio import AsyncSession from database.crud import users from database.exceptions import currency as exceptions from database.models import Bank, NightlyData -from database.utils.math.currency import rob_upgrade_price, interest_upgrade_price, capacity_upgrade_price +from database.utils.math.currency import ( + capacity_upgrade_price, + interest_upgrade_price, + rob_upgrade_price, +) +__all__ = [ + "add_dinks", + "claim_nightly", + "get_bank", + "get_nightly_data", + "invest", + "upgrade_capacity", + "upgrade_interest", + "upgrade_rob", + "NIGHTLY_AMOUNT", +] NIGHTLY_AMOUNT = 420 diff --git a/database/crud/custom_commands.py b/database/crud/custom_commands.py index 4f5dd2f..c6377c6 100644 --- a/database/crud/custom_commands.py +++ b/database/crud/custom_commands.py @@ -7,6 +7,16 @@ from database.exceptions.constraints import DuplicateInsertException from database.exceptions.not_found import NoResultFoundException from database.models import CustomCommand, CustomCommandAlias +__all__ = [ + "clean_name", + "create_alias", + "create_command", + "edit_command", + "get_command", + "get_command_by_alias", + "get_command_by_name", +] + def clean_name(name: str) -> str: """Convert a name to lowercase & remove spaces to allow easier matching""" diff --git a/database/crud/ufora_announcements.py b/database/crud/ufora_announcements.py index c4d67f6..5f82390 100644 --- a/database/crud/ufora_announcements.py +++ b/database/crud/ufora_announcements.py @@ -1,9 +1,11 @@ import datetime -from sqlalchemy import select, delete +from sqlalchemy import delete, select from sqlalchemy.ext.asyncio import AsyncSession -from database.models import UforaCourse, UforaAnnouncement +from database.models import UforaAnnouncement, UforaCourse + +__all__ = ["create_new_announcement", "get_courses_with_announcements", "remove_old_announcements"] async def get_courses_with_announcements(session: AsyncSession) -> list[UforaCourse]: diff --git a/database/crud/users.py b/database/crud/users.py index 794d951..cc5a899 100644 --- a/database/crud/users.py +++ b/database/crud/users.py @@ -3,7 +3,11 @@ from typing import Optional from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession -from database.models import User, Bank, NightlyData +from database.models import Bank, NightlyData, User + +__all__ = [ + "get_or_add", +] async def get_or_add(session: AsyncSession, user_id: int) -> User: diff --git a/database/engine.py b/database/engine.py index 6636bcc..44b5e92 100644 --- a/database/engine.py +++ b/database/engine.py @@ -1,7 +1,7 @@ from urllib.parse import quote_plus from sqlalchemy.engine import URL -from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession +from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.orm import sessionmaker import settings diff --git a/database/exceptions/constraints.py b/database/exceptions/constraints.py index 1e78089..1087d6e 100644 --- a/database/exceptions/constraints.py +++ b/database/exceptions/constraints.py @@ -1,2 +1,5 @@ +__all__ = ["DuplicateInsertException"] + + class DuplicateInsertException(Exception): """Exception raised when a value already exists""" diff --git a/database/exceptions/currency.py b/database/exceptions/currency.py index 5710c62..c06c76f 100644 --- a/database/exceptions/currency.py +++ b/database/exceptions/currency.py @@ -1,3 +1,6 @@ +__all__ = ["DoubleNightly", "NotEnoughDinks"] + + class DoubleNightly(Exception): """Exception raised when claiming nightlies multiple times per day""" diff --git a/database/exceptions/not_found.py b/database/exceptions/not_found.py index eccfaa5..8a47fad 100644 --- a/database/exceptions/not_found.py +++ b/database/exceptions/not_found.py @@ -1,2 +1,5 @@ +__all__ = ["NoResultFoundException"] + + class NoResultFoundException(Exception): """Exception raised when nothing was found""" diff --git a/database/migrations.py b/database/migrations.py index 464c811..1effdff 100644 --- a/database/migrations.py +++ b/database/migrations.py @@ -2,9 +2,10 @@ import logging from alembic import config, script from alembic.runtime import migration - from database.engine import engine +__all__ = ["ensure_latest_migration"] + async def ensure_latest_migration(): """Make sure we are currently on the latest revision, otherwise raise an exception""" diff --git a/database/models.py b/database/models.py index ef2e439..71d4f3c 100644 --- a/database/models.py +++ b/database/models.py @@ -3,12 +3,25 @@ from __future__ import annotations from datetime import datetime from typing import Optional -from sqlalchemy import BigInteger, Column, Integer, Text, ForeignKey, Boolean, DateTime +from sqlalchemy import BigInteger, Boolean, Column, DateTime, ForeignKey, Integer, Text from sqlalchemy.orm import declarative_base, relationship Base = declarative_base() +__all__ = [ + "Base", + "Bank", + "CustomCommand", + "CustomCommandAlias", + "NightlyData", + "UforaAnnouncement", + "UforaCourse", + "UforaCourseAlias", + "User", +] + + class Bank(Base): """A user's currency information""" diff --git a/database/utils/math/currency.py b/database/utils/math/currency.py index c6d36d0..b06c558 100644 --- a/database/utils/math/currency.py +++ b/database/utils/math/currency.py @@ -1,5 +1,7 @@ import math +__all__ = ["capacity_upgrade_price", "interest_upgrade_price", "rob_upgrade_price"] + def interest_upgrade_price(level: int) -> int: """Calculate the price to upgrade your interest level""" diff --git a/didier/__init__.py b/didier/__init__.py index 62f3e85..42c3fc4 100644 --- a/didier/__init__.py +++ b/didier/__init__.py @@ -1 +1,3 @@ from .didier import Didier + +__all__ = ["Didier"] diff --git a/didier/cogs/currency.py b/didier/cogs/currency.py index b30c283..4c76e58 100644 --- a/didier/cogs/currency.py +++ b/didier/cogs/currency.py @@ -5,7 +5,11 @@ from discord.ext import commands from database.crud import currency as crud from database.exceptions.currency import DoubleNightly, NotEnoughDinks -from database.utils.math.currency import capacity_upgrade_price, interest_upgrade_price, rob_upgrade_price +from database.utils.math.currency import ( + capacity_upgrade_price, + interest_upgrade_price, + rob_upgrade_price, +) from didier import Didier from didier.utils.discord.checks import is_owner from didier.utils.discord.converters import abbreviated_number diff --git a/didier/cogs/help.py b/didier/cogs/help.py index 9da24ca..33250a8 100644 --- a/didier/cogs/help.py +++ b/didier/cogs/help.py @@ -1,4 +1,4 @@ -from typing import Mapping, Optional, List +from typing import List, Mapping, Optional import discord from discord.ext import commands diff --git a/didier/cogs/owner.py b/didier/cogs/owner.py index 0bde065..401067c 100644 --- a/didier/cogs/owner.py +++ b/didier/cogs/owner.py @@ -8,8 +8,8 @@ from database.crud import custom_commands from database.exceptions.constraints import DuplicateInsertException from database.exceptions.not_found import NoResultFoundException from didier import Didier -from didier.data.modals.custom_commands import CreateCustomCommand, EditCustomCommand from didier.data.flags.owner import EditCustomFlags +from didier.data.modals.custom_commands import CreateCustomCommand, EditCustomCommand class Owner(commands.Cog): diff --git a/didier/data/embeds/ufora/announcements.py b/didier/data/embeds/ufora/announcements.py index 138837e..984674e 100644 --- a/didier/data/embeds/ufora/announcements.py +++ b/didier/data/embeds/ufora/announcements.py @@ -17,6 +17,12 @@ from database.models import UforaCourse from didier.utils.types.datetime import int_to_weekday from didier.utils.types.string import leading +__all__ = [ + "fetch_ufora_announcements", + "parse_ids", + "UforaNotification", +] + @dataclass class UforaNotification: diff --git a/didier/data/flags/__init__.py b/didier/data/flags/__init__.py index 1ef3b46..93c1df6 100644 --- a/didier/data/flags/__init__.py +++ b/didier/data/flags/__init__.py @@ -1 +1,3 @@ from .posix import PosixFlags + +__all__ = ["PosixFlags"] diff --git a/didier/data/flags/owner.py b/didier/data/flags/owner.py index e3e9789..5ff75a9 100644 --- a/didier/data/flags/owner.py +++ b/didier/data/flags/owner.py @@ -2,6 +2,8 @@ from typing import Optional from didier.data.flags import PosixFlags +__all__ = ["EditCustomFlags"] + class EditCustomFlags(PosixFlags): """Flags for the edit custom command""" diff --git a/didier/data/flags/posix.py b/didier/data/flags/posix.py index 8747165..4a0ba85 100644 --- a/didier/data/flags/posix.py +++ b/didier/data/flags/posix.py @@ -1,5 +1,7 @@ from discord.ext import commands +__all__ = ["PosixFlags"] + class PosixFlags(commands.FlagConverter, delimiter=" ", prefix="--"): # type: ignore """Base class to add POSIX-like flags to commands diff --git a/didier/data/modals/custom_commands.py b/didier/data/modals/custom_commands.py index a54f690..65c259f 100644 --- a/didier/data/modals/custom_commands.py +++ b/didier/data/modals/custom_commands.py @@ -6,6 +6,8 @@ import discord from database.crud.custom_commands import create_command, edit_command from didier import Didier +__all__ = ["CreateCustomCommand", "EditCustomCommand"] + class CreateCustomCommand(discord.ui.Modal, title="Create Custom Command"): """Modal to create new custom commands""" diff --git a/didier/didier.py b/didier/didier.py index ff26e7a..14a9943 100644 --- a/didier/didier.py +++ b/didier/didier.py @@ -10,6 +10,8 @@ from database.crud import custom_commands from database.engine import DBSession from didier.utils.discord.prefix import get_prefix +__all__ = ["Didier"] + class Didier(commands.Bot): """DIDIER <3""" diff --git a/didier/utils/discord/checks/__init__.py b/didier/utils/discord/checks/__init__.py index 7332b42..cbccbc5 100644 --- a/didier/utils/discord/checks/__init__.py +++ b/didier/utils/discord/checks/__init__.py @@ -1 +1,3 @@ from .message_commands import is_owner + +__all__ = ["is_owner"] diff --git a/didier/utils/discord/checks/message_commands.py b/didier/utils/discord/checks/message_commands.py index a57b315..bb65270 100644 --- a/didier/utils/discord/checks/message_commands.py +++ b/didier/utils/discord/checks/message_commands.py @@ -1,5 +1,7 @@ from discord.ext import commands +__all__ = ["is_owner"] + async def is_owner(ctx: commands.Context) -> bool: """Check that a command is being invoked by the owner of the bot""" diff --git a/didier/utils/discord/converters/__init__.py b/didier/utils/discord/converters/__init__.py index 3f47753..9ce48ad 100644 --- a/didier/utils/discord/converters/__init__.py +++ b/didier/utils/discord/converters/__init__.py @@ -1 +1,3 @@ -from .numbers import * +from .numbers import abbreviated_number + +__all__ = ["abbreviated_number"] diff --git a/didier/utils/discord/converters/numbers.py b/didier/utils/discord/converters/numbers.py index 443f3e7..573652f 100644 --- a/didier/utils/discord/converters/numbers.py +++ b/didier/utils/discord/converters/numbers.py @@ -31,11 +31,11 @@ def abbreviated_number(argument: str) -> Union[str, int]: value = units.get(unit) argument = argument[:-1] - # [int][unit] + # [int][unit] # noqa: E800 if "." not in argument and value is not None: return int(argument) * (10**value) - # [float][unit] + # [float][unit] # noqa: E800 if "." in argument: # Floats themselves are not supported if value is None: diff --git a/didier/utils/discord/prefix.py b/didier/utils/discord/prefix.py index a096920..f57e06d 100644 --- a/didier/utils/discord/prefix.py +++ b/didier/utils/discord/prefix.py @@ -5,6 +5,8 @@ from discord.ext import commands from didier.data import constants +__all__ = ["get_prefix"] + def get_prefix(client: commands.Bot, message: Message) -> str: """Match a prefix against a message diff --git a/didier/utils/types/datetime.py b/didier/utils/types/datetime.py index 73d9072..3701b4f 100644 --- a/didier/utils/types/datetime.py +++ b/didier/utils/types/datetime.py @@ -1,3 +1,6 @@ +__all__ = ["int_to_weekday"] + + def int_to_weekday(number: int) -> str: # pragma: no cover # it's useless to write a test for this """Get the Dutch name of a weekday from the number""" return ["Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"][number] diff --git a/didier/utils/types/string.py b/didier/utils/types/string.py index 0255877..ab4f415 100644 --- a/didier/utils/types/string.py +++ b/didier/utils/types/string.py @@ -1,6 +1,8 @@ import math from typing import Optional +__all__ = ["leading", "pluralize"] + def leading(character: str, string: str, target_length: Optional[int] = 2) -> str: """Add a leading [character] to [string] to make it length [target_length] diff --git a/main.py b/main.py index 34a2cf3..fdbc027 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,8 @@ +import asyncio import logging import sys from logging.handlers import RotatingFileHandler -import asyncio - import settings from database.migrations import ensure_latest_migration from didier import Didier diff --git a/pyproject.toml b/pyproject.toml index a81c771..ba0c283 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,9 @@ omit = [ "./didier/data/*" ] +[tool.isort] +profile = "black" + [tool.mypy] plugins = [ "sqlalchemy.ext.mypy.plugin" @@ -25,19 +28,6 @@ plugins = [ module = ["discord.*", "feedparser.*", "markdownify.*"] ignore_missing_imports = true -[tool.pylint.master] -disable = [ - "missing-module-docstring", - "too-few-public-methods", - "too-many-arguments", - "too-many-instance-attributes", - "too-many-locals" -] - -[tool.pylint.format] -max-line-length = 120 -good-names = ["i", "dt"] - [tool.pytest.ini_options] asyncio_mode = "auto" env = [ diff --git a/requirements-dev.txt b/requirements-dev.txt index 646f5e6..d8cb56f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,9 +1,18 @@ black==22.3.0 coverage[toml]==6.4.1 mypy==0.961 -pylint==2.14.1 pytest==7.1.2 pytest-asyncio==0.18.3 pytest-env==0.6.2 sqlalchemy2-stubs==0.0.2a23 -types-pytz==2021.3.8 \ No newline at end of file +types-pytz==2021.3.8 + +# Flake8 + plugins +flake8==4.0.1 +flake8-bandit==3.0.0 +flake8-black==0.3.3 +flake8-bugbear==22.7.1 +flake8-dunder-all==0.2.1 +flake8-eradicate==1.2.1 +flake8-isort==4.1.1 +flake8-simplify==0.19.2