1 Commits
Author SHA1 Message Date
dsql bba01fa931 refactor: rename ButtonPaginator -> DPYPaginator (keep ButtonPaginator as alias)
the paginator class is now DPYPaginator, matching the package name (dpy_paginator),
for naming consistency with the suite. ButtonPaginator is kept as a back-compat alias
(ButtonPaginator = DPYPaginator), so existing imports and call sites keep working
unchanged. both names are exported in __all__. mirrors the suite's alias convention
(aioweb Response/aiowebResponse, envelope_crypto EnvelopeCrypto/PCICrypto).

verified against discord.py 2.7.1: both names resolve to the same class, construction
via either name works, the empty-pages ValueError message updated. v0.1.6.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-07-02 17:50:24 -04:00
4 changed files with 30 additions and 18 deletions
+11 -8
View File
@@ -9,28 +9,31 @@ buttons) behind previous / jump / next navigation, with an optional cache button
`requirements.txt`:
```
dpy_paginator @ git+ssh://git@git.rethinkstudios.io/rethink-public/dpy_paginator.git@v0.1.5
dpy_paginator @ git+ssh://git@git.rethinkstudios.io/rethink-public/dpy_paginator.git@v0.1.6
```
Direct:
```bash
pip install "dpy_paginator @ git+ssh://git@git.rethinkstudios.io/rethink-public/dpy_paginator.git@v0.1.5"
pip install "dpy_paginator @ git+ssh://git@git.rethinkstudios.io/rethink-public/dpy_paginator.git@v0.1.6"
```
Requires `discord.py` (pulled transitively).
Drop the `@v0.1.5` suffix from the line above to install the latest unpinned.
Drop the `@v0.1.6` suffix from the line above to install the latest unpinned.
## Basic usage
The paginator class is `DPYPaginator`. It is also exported as `ButtonPaginator` (a
back-compat alias) — both names refer to the same class, so either import works.
Plain pages — just navigation:
```python
from dpy_paginator import ButtonPaginator
from dpy_paginator import DPYPaginator # or: from dpy_paginator import ButtonPaginator
pages = [discord.Embed(title=f"Page {i}") for i in range(5)]
await ButtonPaginator(pages, author_id=ctx.author.id).start(ctx)
await DPYPaginator(pages, author_id=ctx.author.id).start(ctx)
```
`start()` accepts an `Interaction` or any `Messageable` (a `Context`, channel, etc.).
@@ -41,7 +44,7 @@ Navigation uses plain Unicode by default — no setup, no emoji upload required.
`emojis=` to override with custom application/guild emojis the bot can use:
```python
ButtonPaginator(pages, emojis={
DPYPaginator(pages, emojis={
"previous": "<:icon_back:123...>",
"next": "<:icon_next:123...>",
"cache": "<:icon_cache:123...>",
@@ -91,7 +94,7 @@ for session in sessions:
],
})
paginator = ButtonPaginator(
paginator = DPYPaginator(
pages, cache=None, timeout=900, delete_message_after=True,
mentions_allowed=discord.AllowedMentions.none(), ephemeral=True,
page_text="Session {} of {}",
@@ -124,7 +127,7 @@ for group in groups:
pages.append(build_embed(group))
cache.append(" ".join(f"<@{uid}>" for uid in group["user_ids"]))
await ButtonPaginator(pages, cache=cache, cache_sleep=1.0).start(ctx)
await DPYPaginator(pages, cache=cache, cache_sleep=1.0).start(ctx)
```
Omit `cache` or pass `None`/`[]` and the button never appears. When set, `cache`
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "dpy_paginator"
version = "0.1.5"
version = "0.1.6"
description = "Button-navigated paginator for discord.py — config-free, injectable emojis, installable."
requires-python = ">=3.10"
dependencies = [
+2 -2
View File
@@ -1,3 +1,3 @@
from .dpy_paginator import ButtonPaginator, JumpToPageModal, DEFAULT_EMOJIS, Page
from .dpy_paginator import DPYPaginator, ButtonPaginator, JumpToPageModal, DEFAULT_EMOJIS, Page
__all__ = ["ButtonPaginator", "JumpToPageModal", "DEFAULT_EMOJIS", "Page"]
__all__ = ["DPYPaginator", "ButtonPaginator", "JumpToPageModal", "DEFAULT_EMOJIS", "Page"]
+16 -7
View File
@@ -5,15 +5,15 @@ a discord.ui.View that paginates mixed content (strings, embeds, files,
attachments, or dicts of mixed content with custom buttons) behind
previous / jump / next navigation, with an optional cache button.
from dpy_paginator import ButtonPaginator
from dpy_paginator import DPYPaginator # or ButtonPaginator, an alias
pages = [discord.Embed(title=f"Page {i}") for i in range(5)]
await ButtonPaginator(pages, author_id=ctx.author.id).start(ctx)
await DPYPaginator(pages, author_id=ctx.author.id).start(ctx)
emojis: navigation uses plain unicode by default (no setup). pass emojis= to
override with custom application/guild emojis the bot can use:
ButtonPaginator(pages, emojis={
DPYPaginator(pages, emojis={
"previous": "<:icon_back:123...>",
"next": "<:icon_next:123...>",
"cache": "<:icon_cache:123...>",
@@ -111,7 +111,7 @@ class _CustomButton(discord.ui.Button):
class JumpToPageModal(discord.ui.Modal, title="Jump to Page"):
"""modal that lets a user jump to a specific page"""
def __init__(self, paginator: "ButtonPaginator"):
def __init__(self, paginator: "DPYPaginator"):
super().__init__()
self.paginator = paginator
self.page_number = discord.ui.TextInput(
@@ -139,8 +139,12 @@ class JumpToPageModal(discord.ui.Modal, title="Jump to Page"):
)
class ButtonPaginator(Generic[PageT_co], discord.ui.View):
"""button-navigated paginator supporting mixed page content and custom buttons"""
class DPYPaginator(Generic[PageT_co], discord.ui.View):
"""button-navigated paginator supporting mixed page content and custom buttons
also importable as `ButtonPaginator` (a back-compat alias defined below); both
names refer to this same class.
"""
message: Optional[Union[discord.Message, discord.WebhookMessage]] = None
@@ -177,7 +181,7 @@ class ButtonPaginator(Generic[PageT_co], discord.ui.View):
"""
super().__init__(timeout=timeout)
if not pages:
raise ValueError("ButtonPaginator requires at least one page")
raise ValueError("DPYPaginator 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
@@ -513,3 +517,8 @@ class ButtonPaginator(Generic[PageT_co], discord.ui.View):
# 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)
# back-compat alias: the class was originally named ButtonPaginator; DPYPaginator is
# the canonical name (matching the package), both refer to the same class
ButtonPaginator = DPYPaginator