diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 39c2eb2..e48d07b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -142,7 +142,6 @@ repos: asyncpg-stubs, polyfactory, discord-py, - types-pytz, ] - repo: https://github.com/sphinx-contrib/sphinx-lint rev: "v0.9.1" diff --git a/pdm.lock b/pdm.lock index 6550d1f..934b060 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "docs", "lint", "test"] strategy = ["cross_platform", "inherit_metadata"] lock_version = "4.4.1" -content_hash = "sha256:14f8129662e9236268f43ba1658ebf5548efce0ff45321b27eea03f689537e95" +content_hash = "sha256:7098b3193b937e135dd887069755130b9528dc064cdd068424cf78340e091281" [[package]] name = "accessible-pygments" @@ -1804,16 +1804,6 @@ files = [ {file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"}, ] -[[package]] -name = "pytz" -version = "2024.1" -summary = "World timezone definitions, modern and historical" -groups = ["default"] -files = [ - {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, - {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, -] - [[package]] name = "pyyaml" version = "6.0.1" diff --git a/pyproject.toml b/pyproject.toml index f9c1c9e..93400bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,6 @@ dependencies = [ "alembic>=1.13.0", "pre-commit>=3.6.2", "ruff>=0.1.7", - "pytz>=2024.1", ] requires-python = ">=3.11,<4.0" readme = "README.md" diff --git a/src/byte/lib/utils.py b/src/byte/lib/utils.py index f91159f..3b4b56e 100644 --- a/src/byte/lib/utils.py +++ b/src/byte/lib/utils.py @@ -4,13 +4,12 @@ import json import re import subprocess -from datetime import datetime +from datetime import UTC, datetime from enum import StrEnum from itertools import islice from typing import TYPE_CHECKING, TypedDict, TypeVar import httpx -import pytz from anyio import run_process from discord.ext import commands from ruff.__main__ import find_ruff_bin # type: ignore[import-untyped] @@ -414,7 +413,7 @@ async def query_all_peps() -> list[PEP]: "status": PEPStatus(pep_info["status"]), "type": PEPType(pep_info["type"]), "topic": pep_info.get("topic", ""), - "created": datetime.strptime(pep_info["created"], "%d-%b-%Y").replace(tzinfo=pytz.utc), + "created": datetime.strptime(pep_info["created"], "%d-%b-%Y").replace(tzinfo=UTC), "python_version": pep_info.get("python_version"), "post_history": pep_info.get("post_history", []), "resolution": pep_info.get("resolution"), diff --git a/src/byte/plugins/python.py b/src/byte/plugins/python.py index 2007ded..4e572c2 100644 --- a/src/byte/plugins/python.py +++ b/src/byte/plugins/python.py @@ -9,6 +9,7 @@ from byte.lib.common.assets import python_logo from byte.lib.common.colors import python_blue, python_yellow from byte.lib.utils import PEP, query_all_peps +from byte.views.embed import ExtendedEmbed, Field from byte.views.python import PEPView __all__ = ("Python", "setup") @@ -29,10 +30,10 @@ async def _pep_autocomplete(self, interaction: Interaction, current_pep: str) -> .. warning:: ``interaction`` is not used, but is required. """ return [ - Choice(name=f'PEP {number} - {pep["title"]}', value=str(number)) - for number, pep in self._peps.items() - if current_pep.lower() in str(number) or current_pep.lower() in pep["title"].lower() - ][:25] + Choice(name=f'PEP {number} - {pep["title"]}', value=str(number)) + for number, pep in self._peps.items() + if current_pep.lower() in str(number) or current_pep.lower() in pep["title"].lower() + ][:25] @app_command(name="pep") @autocomplete(pep=_pep_autocomplete) @@ -52,26 +53,20 @@ async def peps(self, interaction: Interaction, pep: int) -> None: docs_field = f"- [PEP Documentation]({pep_details['url']})\n" - minified_embed = Embed(title=f"PEP #{pep_details['number']}", color=python_blue) - minified_embed.add_field(name="Summary", value=pep_details["title"], inline=False) - minified_embed.add_field(name="Status", value=pep_details["status"], inline=True) - minified_embed.add_field(name="Type", value=pep_details["type"], inline=True) - minified_embed.add_field(name="Authors", value=", ".join(pep_details["authors"]), inline=False) - minified_embed.add_field(name="Created", value=pep_details["created"], inline=True) - minified_embed.add_field(name="Python Version", value=pep_details["python_version"], inline=True) - minified_embed.add_field(name="Documentation", value=docs_field, inline=False) + fields = [ + Field(name="Summary", value=pep_details["title"], inline=False), + Field(name="Status", value=pep_details["status"], inline=True), + Field(name="Type", value=pep_details["type"], inline=True), + Field(name="Authors", value=", ".join(pep_details["authors"]), inline=False), + Field(name="Created", value=str(pep_details["created"]), inline=True), + Field(name="Python Version", value=pep_details["python_version"], inline=True), + Field(name="Documentation", value=docs_field, inline=False), + ] + minified_embed = ExtendedEmbed.from_field_dicts( + title=f"PEP #{pep_details['number']}", color=python_blue, fields=fields + ) minified_embed.set_thumbnail(url=python_logo) - - embed = Embed(title=f"PEP #{pep_details['number']}", color=python_blue) - embed.add_field(name="Summary", value=pep_details["title"], inline=False) - embed.add_field(name="Status", value=pep_details["status"], inline=True) - embed.add_field(name="Type", value=pep_details["type"], inline=True) - embed.add_field(name="Authors", value=", ".join(pep_details["authors"]), inline=False) - embed.add_field(name="Created", value=pep_details["created"], inline=True) - embed.add_field(name="Python Version", value=pep_details["python_version"], inline=True) - embed.add_field(name="Documentation", value=docs_field, inline=False) - embed.set_thumbnail(url=python_logo) - + embed = minified_embed.deepcopy() view = PEPView(author=interaction.user.id, bot=self.bot, original_embed=embed, minified_embed=minified_embed) await interaction.followup.send(embed=minified_embed, view=view) diff --git a/src/byte/views/embed.py b/src/byte/views/embed.py new file mode 100644 index 0000000..701eaf1 --- /dev/null +++ b/src/byte/views/embed.py @@ -0,0 +1,56 @@ +from copy import deepcopy +from datetime import datetime +from typing import Any, Literal, Self, TypedDict + +from discord import Colour, Embed + +__all__ = ("ExtendedEmbed", "Field") + + +# TODO: find a better place + + +class Field(TypedDict): + # NOTE: types are matching the ones in ``Embed`.add_fields` + name: Any + value: Any + inline: bool = True + + +class ExtendedEmbed(Embed): + # TODO: better name + def add_field_dict(self, field: Field) -> Self: + self.add_field(**field) + return self + + def add_field_dicts(self, fields: list[Field]) -> Self: + for field in fields: + self.add_field_dict(field) + return self + + @classmethod + def from_field_dicts( + cls, + colour: int | Colour | None = None, + color: int | Colour | None = None, + title: Any | None = None, + type: Literal["rich", "image", "video", "gifv", "article", "link"] = "rich", + url: Any | None = None, + description: Any | None = None, + timestamp: datetime | None = None, + fields: list[Field] | None = None, + ) -> Self: + embed = cls( + colour=colour, + color=color, + title=title, + type=type, + url=url, + description=description, + timestamp=timestamp, + ) + embed.add_field_dicts(fields or []) + return embed + + def deepcopy(self) -> Self: + return deepcopy(self)