diff --git a/.dockerignore b/.dockerignore index 765f5a5..4bcba1f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,9 +1,8 @@ -* -!/src +**/* + +!/src/**/*.py !/uv.lock !/pyproject.toml !/accents -!/accents2 +!/accents2/ !/schema.sql - -**/__pycache__ diff --git a/.gitignore b/.gitignore index 1b06e14..3be7559 100644 --- a/.gitignore +++ b/.gitignore @@ -6,11 +6,10 @@ settings.toml !/example.settings.toml # cache -__pycache__ +__pycache__/ /target -/.venv -/.mypy_cache -/.pytest_cache +/.venv/ +*.egg-info/ # db /pink.db diff --git a/Dockerfile b/Dockerfile index 1d5b67f..1610ff2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,8 +25,7 @@ RUN : \ gifsicle \ # Font for trocr ttf-dejavu \ - && uv sync --frozen --no-cache \ - && rm uv.lock pyproject.toml \ + && uv sync --frozen --no-cache --no-dev \ && rm /bin/uv COPY --from=accents_builder /build/target/release/sayit /usr/bin/sayit @@ -48,5 +47,6 @@ RUN addgroup -g $GID -S pink \ USER pink COPY --chown=pink:pink . . +RUN rm uv.lock pyproject.toml ENTRYPOINT ["/code/.venv/bin/python", "-m", "src"] diff --git a/pyproject.toml b/pyproject.toml index 5f1c73f..6cd4a90 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,9 +52,6 @@ select = [ "N", # pyupgrade "UP", - # flake8-bandit - # most rules are stupid - # "S", # flake8-comprehensions "C4", # flake8-logging-format @@ -67,6 +64,10 @@ select = [ "RUF", # flake8-unused-arguments "ARG", + # perflint + "PERF", + # refurb + "FURB", ] fixable = [ "I" diff --git a/src/bot.py b/src/bot.py index 871665d..41699f1 100644 --- a/src/bot.py +++ b/src/bot.py @@ -27,7 +27,7 @@ def mention_or_prefix_regex(user_id: int, prefix: str) -> re.Pattern[str]: choices = [re.escape(prefix), rf"<@!?{user_id}>"] - return re.compile(rf"(?:{'|'.join(choices)})\s*", re.I) + return re.compile(rf"(?:{'|'.join(choices)})\s*", re.IGNORECASE) class Prefix: diff --git a/src/cogs/fun.py b/src/cogs/fun.py index 33e01af..fe9be0b 100644 --- a/src/cogs/fun.py +++ b/src/cogs/fun.py @@ -4,7 +4,7 @@ from collections import defaultdict from collections.abc import Iterable -from datetime import datetime, timezone +from datetime import UTC, datetime from typing import Optional import discord @@ -33,7 +33,7 @@ async def convert(cls, _: Context, argument: str) -> datetime: except ValueError: continue - return parsed.replace(tzinfo=timezone.utc) + return parsed.replace(tzinfo=UTC) raise ValueError("Could not parse date") @@ -294,10 +294,13 @@ async def scramble2(self, ctx: Context, *, text: Optional[str]) -> None: indexes = [i for i, _ in group] group_words = [w for _, w in group] - for i, word in zip(indexes, random.sample(group_words, k=len(group_words))): + for i, word in zip(indexes, random.sample(group_words, k=len(group_words)), strict=True): # replace and copy case for each letter from old value words[i] = "".join( - [c_new.upper() if c_old.isupper() else c_new.lower() for c_new, c_old in zip(word, words[i])] + [ + c_new.upper() if c_old.isupper() else c_new.lower() + for c_new, c_old in zip(word, words[i], strict=True) + ] ) first, second = (words, nonwords) if word_was_first else (nonwords, words) diff --git a/src/cogs/images/flies.py b/src/cogs/images/flies.py index 709a9e3..bf41101 100644 --- a/src/cogs/images/flies.py +++ b/src/cogs/images/flies.py @@ -228,9 +228,7 @@ def draw_flies( speed: int, amount: int, ) -> Path: - flies = [] - for _ in range(amount): - flies.append(Fly(speed=speed)) + flies = [Fly(speed=speed) for _ in range(amount)] filename = FlyDrawer(src, flies, steps=steps, fly_src=fly_src).run() src.close() diff --git a/src/cogs/images/types.py b/src/cogs/images/types.py index 3268ed6..1b01856 100644 --- a/src/cogs/images/types.py +++ b/src/cogs/images/types.py @@ -1,11 +1,9 @@ from __future__ import annotations -import asyncio import base64 import re import warnings -from asyncio import TimeoutError from enum import Enum, auto from io import BytesIO from typing import Any, Literal, Optional @@ -448,7 +446,7 @@ async def _fetch( max_content_length: int = 8000000, ) -> bytes: try: - async with ctx.session.get(url, timeout=timeout) as r: + async with ctx.session.get(url, timeout=aiohttp.ClientTimeout(total=timeout)) as r: if r.status != 200: raise PINKError(f"bad status code: **{r.status}**") @@ -470,7 +468,7 @@ async def _fetch( return await r.read() except PINKError: raise - except (Exception, asyncio.TimeoutError) as e: + except (Exception, TimeoutError) as e: error = "Download error: " if isinstance(e, TimeoutError): error += f"timeout reached: **{timeout}s**"