From fa5cdf3e1d104e051e302e590acd55340f131046 Mon Sep 17 00:00:00 2001 From: disqualifier Date: Mon, 29 Jun 2026 21:35:01 -0400 Subject: [PATCH] fix: F3 guard per_page>=1; swallow on_timeout HTTPException per_page<=0 raised ZeroDivisionError (==0) or yielded a negative max_pages (<0) at the divmod; now a clear ValueError. on_timeout swallows a transient delete HTTPException (with a log) so a best-effort cleanup doesn't surface as an unretrieved-task traceback. add the module logger. Signed-off-by: disqualifier --- src/dpy_paginator/dpy_paginator.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/dpy_paginator/dpy_paginator.py b/src/dpy_paginator/dpy_paginator.py index d307c06..f2516b3 100644 --- a/src/dpy_paginator/dpy_paginator.py +++ b/src/dpy_paginator/dpy_paginator.py @@ -29,6 +29,7 @@ config-free: no host config import; everything is passed at construction. from __future__ import annotations import asyncio +import logging from typing import ( Any, Dict, @@ -69,6 +70,8 @@ DEFAULT_EMOJIS = { "cache": "\U0001f5c2\ufe0f", # 🗂️ } +log = logging.getLogger(__name__) + PageT_co = TypeVar("PageT_co", bound=Page, covariant=True) @@ -161,6 +164,10 @@ class ButtonPaginator(Generic[PageT_co], discord.ui.View): super().__init__(timeout=timeout) if not pages: raise ValueError("ButtonPaginator requires at least one page") + if per_page < 1: + # per_page <= 0 would ZeroDivisionError (==0) or yield a negative max_pages + # (<0) at the divmod below; fail loud like the other construction guards + raise ValueError("per_page must be >= 1") self.author_id: Optional[int] = author_id self.delete_message_after: bool = delete_message_after self.mentions_allowed = mentions_allowed or discord.AllowedMentions.all() @@ -427,3 +434,7 @@ class ButtonPaginator(Generic[PageT_co], discord.ui.View): await self.message.delete() except (discord.NotFound, discord.Forbidden): pass + except discord.HTTPException: + # on_timeout runs as a fire-and-forget task; a transient delete failure must + # not surface as an unretrieved-task traceback on a best-effort cleanup + log.warning("paginator on_timeout: failed to delete message", exc_info=True)