8000 [pull] master from Pycord-Development:master by pull[bot] · Pull Request #55 · pirica/pycord · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[pull] master from Pycord-Development:master #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
509569b
feat: add created_at property to Interaction (#2801)
Lumabots Jun 4, 2025
f944b25
chore(deps): update setuptools requirement from <=78.1.0,>=62.6 to >=…
dependabot[bot] Jun 4, 2025
acf0c7a
chore!: :fire: Remove deprecated support for Option in bridge command…
Paillat-dev Jun 4, 2025
7efe9a2
fix: :bug: `TypeError` when specifying `thread_name` in Webhook.send …
Paillat-dev Jun 4, 2025
aeacfed
fix: add BanEntry to __all__ exports in guild.py (#2798)
Lumabots Jun 4, 2025
0571244
fix: correct generic return type in component utils (#2796)
8000 Lumabots Jun 4, 2025
5ddd1e2
chore(deps): update setuptools-scm requirement from <=8.2.1,>=6.2 to …
dependabot[bot] Jun 4, 2025
0618653
chore(deps-dev): update pylint requirement from ~=3.3.6 to ~=3.3.7 (#…
dependabot[bot] Jun 4, 2025
2377245
chore(pre-commit): pre-commit autoupdate (#2792)
pre-commit-ci[bot] Jun 4, 2025
5eaebfb
docs: :memo: Fix malformed CHANGELOG.md hyperlinks (#2804)
Paillat-dev Jun 5, 2025
ad3d2a8
fix: :bug: Fix `ValueError` when using `Flag` (#2759)
Paillat-dev Jun 5, 2025
f17fedd
ci(deps): bump crowdin/github-action from 2.7.0 to 2.7.1 in the patch…
dependabot[bot] Jun 5, 2025
8e97cb5
fix: resolve regex library warnings (#2807)
emmanuel-ferdman Jun 6, 2025
735673b
fix: support emoji aliases like `:smile:` in PartialEmoji.from_str (#…
Lumabots Jun 20, 2025
8619b69
Revert "fix: support emoji aliases like `:smile:` in PartialEmoji.fro…
Lulalaby Jun 20, 2025
1c65fc8
chore: :memo: update license format in pyproject.toml (#2824)
Paillat-dev Jul 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docs-localization-download.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
working-directory: ./docs
- name: "Crowdin"
id: crowdin
uses: crowdin/github-action@v2.7.0
uses: crowdin/github-action@v2.7.1
with:
upload_sources: false
upload_translations: false
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs-localization-upload.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
sphinx-intl update -p ./build/locales ${{ vars.SPHINX_LANGUAGES }}
working-directory: ./docs
- name: "Crowdin"
uses: crowdin/github-action@v2.7.0
uses: crowdin/github-action@v2.7.1
with:
upload_sources: true
upload_translations: false
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ repos:
# - --remove-duplicate-keys
# - --remove-unused-variables
- repo: https://github.com/asottile/pyupgrade
rev: v3.19.1
rev: v3.20.0
hooks:
- id: pyupgrade
exclude: \.(po|pot|yml|yaml)$
Expand Down
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ These changes are available on the `master` branch, but have not yet been releas
([#2598](https://github.com/Pycord-Development/pycord/pull/2598))
- Added the ability to change the API's base URL with `Route.API_BASE_URL`.
([#2714](https://github.com/Pycord-Development/pycord/pull/2714))
- Added the ability to pass a `datetime.time` object to `format_dt`
- Added the ability to pass a `datetime.time` object to `format_dt`.
([#2747](https://github.com/Pycord-Development/pycord/pull/2747))
- Added `discord.Interaction.created_at`.
([#2801](https://github.com/Pycord-Development/pycord/pull/2801))

### Fixed

Expand Down Expand Up @@ -105,6 +107,10 @@ These changes are available on the `master` branch, but have not yet been releas
([#2739](https://github.com/Pycord-Development/pycord/pull/2739))
- Fixed missing `None` type hints in `Select.__init__`.
([#2746](https://github.com/Pycord-Development/pycord/pull/2746))
- Fixed `TypeError` when using `Flag` with Python 3.11+.
([#2759](https://github.com/Pycord-Development/pycord/pull/2759))
- Fixed `TypeError` when specifying `thread_name` in `Webhook.send`.
([#2761](https://github.com/Pycord-Development/pycord/pull/2761))
- Updated `valid_locales` to support `in` and `es-419`.
([#2767](https://github.com/Pycord-Development/pycord/pull/2767))
- Fixed `Webhook.edit` not working with `attachments=[]`.
Expand Down Expand Up @@ -142,6 +148,11 @@ These changes are available on the `master` branch, but have not yet been releas
- Deprecated `Interaction.cached_channel` in favor of `Interaction.channel`.
([#2658](https://github.com/Pycord-Development/pycord/pull/2658))

### Removed

- Removed deprecated support for `Option` in `BridgeCommand`. Use `BridgeOption`
instead. ([#2731])(https://github.com/Pycord-Development/pycord/pull/2731))

## [2.6.1] - 2024-09-15

### Fixed
Expand Down
20 changes: 3 additions & 17 deletions discord/ext/bridge/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,26 +98,12 @@ class BridgeExtCommand(Command):
def __init__(self, func, **kwargs):
super().__init__(func, **kwargs)

# TODO: v2.7: Remove backwards support for Option in bridge commands.
for name, option in self.params.items():
for option in self.params.values():
if isinstance(option.annotation, Option) and not isinstance(
option.annotation, BridgeOption
):
# Warn not to do this
warn_deprecated(
"Using Option for bridge commands",
"BridgeOption",
"2.5",
"2.7",
reference="https://github.com/Pycord-Development/pycord/pull/2417",
stacklevel=6,
)
# Override the convert method of the parameter's annotated Option.
# We can use the convert method from BridgeOption, and bind "self"
# using a manual invocation of the descriptor protocol.
# Definitely not a good approach, but gets the job done until removal.
self.params[name].annotation.convert = BridgeOption.convert.__get__(
self.params[name].annotation
raise TypeError(
f"{option.annotation.__class__.__name__} is not supported in bridge commands. Use BridgeOption instead."
)

async def dispatch_error(self, ctx: BridgeExtContext, error: Exception) -> None:
Expand Down
27 changes: 15 additions & 12 deletions discord/ext/commands/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, Iterator, Literal, Pattern, TypeVar, Union

from discord.utils import MISSING, MissingField, maybe_coroutine, resolve_annotation

if sys.version_info >= (3, 11):
_MISSING = MissingField
else:
_MISSING = MISSING
from discord.utils import (
MISSING,
maybe_coroutine,
resolve_annotation,
)

from .converter import run_converters
from .errors import (
Expand All @@ -59,6 +58,10 @@
from .context import Context


def _missing_field_factory() -> field:
return field(default_factory=lambda: MISSING)


@dataclass
class Flag:
"""Represents a flag parameter for :class:`FlagConverter`.
Expand Down Expand Up @@ -86,13 +89,13 @@ class Flag:
Whether multiple given values overrides the previous value.
"""

name: str = _MISSING
name: str = _missing_field_factory()
aliases: list[str] = field(default_factory=list)
attribute: str = _MISSING
annotation: Any = _MISSING
default: Any = _MISSING
max_args: int = _MISSING
override: bool = _MISSING
attribute: str = _missing_field_factory()
annotation: Any = _missing_field_factory()
default: Any = _missing_field_factory()
max_args: int = _missing_field_factory()
override: bool = _missing_field_factory()
cast_to_dict: bool = False

@property
Expand Down
2 changes: 1 addition & 1 deletion discord/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
from .welcome_screen import WelcomeScreen, WelcomeScreenChannel
from .widget import Widget

__all__ = ("Guild",)
__all__ = ("BanEntry", "Guild")

MISSING = utils.MISSING

Expand Down
6 changes: 6 additions & 0 deletions discord/interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from __future__ import annotations

import asyncio
import datetime
from typing import TYPE_CHECKING, Any, Coroutine, Union

from . import utils
Expand Down Expand Up @@ -300,6 +301,11 @@ def guild(self) -> Guild | None:
return self._guild
return self._state and self._state._get_guild(self.guild_id)

@property
def created_at(self) -> datetime.datetime:
"""Returns the interaction's creation time in UTC."""
return utils.snowflake_time(self.id)

def is_command(self) -> bool:
"""Indicates whether the interaction is an application command."""
return self.type == InteractionType.application_command
Expand Down
44 changes: 23 additions & 21 deletions discord/ui/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import traceback
from functools import partial
from itertools import groupby
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Iterator, Sequence
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Iterator, Sequence, TypeVar

from ..components import ActionRow as ActionRowComponent
from ..components import Button as ButtonComponent
Expand All @@ -51,6 +51,8 @@
from ..state import ConnectionState
from ..types.components import Component as ComponentPayload

V = TypeVar("V", bound="View", covariant=True)


def _walk_all_components(components: list[Component]) -> Iterator[Component]:
for item in components:
Expand All @@ -60,7 +62,7 @@ def _walk_all_components(components: list[Component]) -> Iterator[Component]:
yield item


def _component_to_item(component: Component) -> Item:
def _component_to_item(component: Component) -> Item[V]:
if isinstance(component, ButtonComponent):
from .button import Button

Expand All @@ -75,7 +77,7 @@ def _component_to_item(component: Component) -> Item:
class _ViewWeights:
__slots__ = ("weights",)

def __init__(self, children: list[Item]):
def __init__(self, children: list[Item[V]]):
self.weights: list[int] = [0, 0, 0, 0, 0]

key = lambda i: sys.maxsize if i.row is None else i.row
Expand All @@ -84,14 +86,14 @@ def __init__(self, children: list[Item]):
for item in group:
self.add_item(item)

def find_open_space(self, item: Item) -> int:
def find_open_space(self, item: Item[V]) -> int:
for index, weight in enumerate(self.weights):
if weight + item.width <= 5:
return index

raise ValueError("could not find open space for item")

def add_item(self, item: Item) -> None:
def add_item(self, item: Item[V]) -> None:
if item.row is not None:
total = self.weights[item.row] + item.width
if total > 5:
Expand All @@ -105,7 +107,7 @@ def add_item(self, item: Item) -> None:
self.weights[index] += item.width
item._rendered_row = index

def remove_item(self, item: Item) -> None:
def remove_item(self, item: Item[V]) -> None:
if item._rendered_row is not None:
self.weights[item._rendered_row] -= item.width
item._rendered_row = None
Expand Down Expand Up @@ -163,15 +165,15 @@ def __init_subclass__(cls) -> None:

def __init__(
self,
*items: Item,
*items: Item[V],
timeout: float | None = 180.0,
disable_on_timeout: bool = False,
):
self.timeout = timeout
self.disable_on_timeout = disable_on_timeout
self.children: list[Item] = []
self.children: list[Item[V]] = []
for func in self.__view_children_items__:
item: Item = func.__discord_ui_model_type__(
item: Item[V] = func.__discord_ui_model_type__(
**func.__discord_ui_model_kwargs__
)
item.callback = partial(func, self, item)
Expand Down Expand Up @@ -213,7 +215,7 @@ async def __timeout_task_impl(self) -> None:
await asyncio.sleep(self.__timeout_expiry - now)

def to_components(self) -> list[dict[str, Any]]:
def key(item: Item) -> int:
def key(item: Item[V]) -> int:
return item._rendered_row or 0

children = sorted(self.children, key=key)
Expand Down Expand Up @@ -267,7 +269,7 @@ def _expires_at(self) -> float | None:
return time.monotonic() + self.timeout
return None

def add_item(self, item: Item) -> None:
def add_item(self, item: Item[V]) -> None:
"""Adds an item to the view.

Parameters
Expand Down Expand Up @@ -295,7 +297,7 @@ def add_item(self, item: Item) -> None:
item._view = self
self.children.append(item)

def remove_item(self, item: Item) -> None:
def remove_item(self, item: Item[V]) -> None:
"""Removes an item from the view.

Parameters
Expand All @@ -316,7 +318,7 @@ def clear_items(self) -> None:
self.children.clear()
self.__weights.clear()

def get_item(self, custom_id: str) -> Item | None:
def get_item(self, custom_id: str) -> Item[V] | None:
"""Get an item from the view with the given custom ID. Alias for `utils.get(view.children, custom_id=custom_id)`.

Parameters
Expand Down Expand Up @@ -391,7 +393,7 @@ async def on_check_failure(self, interaction: Interaction) -> None:
"""

async def on_error(
self, error: Exception, item: Item, interaction: Interaction
self, error: Exception, item: Item[V], interaction: Interaction
) -> None:
"""|coro|

Expand All @@ -414,7 +416,7 @@ async def on_error(
error.__class__, error, error.__traceback__, file=sys.stderr
)

async def _scheduled_task(self, item: Item, interaction: Interaction):
async def _scheduled_task(self, item: Item[V], interaction: Interaction):
try:
if self.timeout:
self.__timeout_expiry = time.monotonic() + self.timeout
Expand Down Expand Up @@ -446,7 +448,7 @@ def _dispatch_timeout(self):
self.on_timeout(), name=f"discord-ui-view-timeout-{self.id}"
)

def _dispatch_item(self, item: Item, interaction: Interaction):
def _dispatch_item(self, item: Item[V], interaction: Interaction):
if self.__stopped.done():
return

Expand All @@ -460,10 +462,10 @@ def _dispatch_item(self, item: Item, interaction: Interaction):

def refresh(self, components: list[Component]):
# This is pretty hacky at the moment
old_state: dict[tuple[int, str], Item] = {
old_state: dict[tuple[int, str], Item[V]] = {
(item.type.value, item.custom_id): item for item in self.children if item.is_dispatchable() # type: ignore
}
children: list[Item] = [
children: list[Item[V]] = [
item for item in self.children if not item.is_dispatchable()
]
for component in _walk_all_components(components):
Expand Down Expand Up @@ -529,7 +531,7 @@ async def wait(self) -> bool:
"""
return await self.__stopped

def disable_all_items(self, *, exclusions: list[Item] | None = None) -> None:
def disable_all_items(self, *, exclusions: list[Item[V]] | None = None) -> None:
"""
Disables all items in the view.

Expand All @@ -542,7 +544,7 @@ def disable_all_items(self, *, exclusions: list[Item] | None = None) -> None:
if exclusions is None or child not in exclusions:
child.disabled = True

def enable_all_items(self, *, exclusions: list[Item] | None = None) -> None:
def enable_all_items(self, *, exclusions: list[Item[V]] | None = None) -> None:
"""
Enables all items in the view.

Expand All @@ -567,7 +569,7 @@ def message(self, value):
class ViewStore:
def __init__(self, state: ConnectionState):
# (component_type, message_id, custom_id): (View, Item)
self._views: dict[tuple[int, int | None, str], tuple[View, Item]] = {}
self._views: dict[tuple[int, int | None, str], tuple[View, Item[V]]] = {}
# message_id: View
self._synced_message_views: dict[int, View] = {}
self._state: ConnectionState = state
Expand Down
10 changes: 2 additions & 8 deletions discord/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import warnings
from base64 import b64encode
from bisect import bisect_left
from dataclasses import field
from inspect import isawaitable as _isawaitable
from inspect import signature as _signature
from operator import attrgetter
Expand Down Expand Up @@ -115,11 +114,6 @@ def __repr__(self) -> str:


MISSING: Any = _MissingSentinel()
# As of 3.11, directly setting a dataclass field to MISSING causes a ValueError. Using
# field(default=MISSING) produces the same error, but passing a lambda to
# default_factory produces the same behavior as default=MISSING and does not raise an
# error.
MissingField = field(default_factory=lambda: MISSING)


class _cached_property:
Expand Down Expand Up @@ -939,7 +933,7 @@ def replacement(match):
regex = _MARKDOWN_STOCK_REGEX
if ignore_links:
regex = f"(?:{_URL_REGEX}|{regex})"
return re.sub(regex, replacement, text, 0, re.MULTILINE)
return re.sub(regex, replacement, text, count=0, flags=re.MULTILINE)


def escape_markdown(
Expand Down Expand Up @@ -981,7 +975,7 @@ def replacement(match):
regex = _MARKDOWN_STOCK_REGEX
if ignore_links:
regex = f"(?:{_URL_REGEX}|{regex})"
return re.sub(regex, replacement, text, 0, re.MULTILINE | re.X)
return re.sub(regex, replacement, text, count=0, flags=re.MULTILINE | re.X)
else:
text = re.sub(r"\\", r"\\\\", text)
return _MARKDOWN_ESCAPE_REGEX.sub(r"\\\1", text)
Expand Down
Loading
Loading
0