Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
Signed-off-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>
  • Loading branch information
Dorukyum committed Dec 2, 2023
2 parents 42d0c93 + 5849d64 commit b413933
Show file tree
Hide file tree
Showing 13 changed files with 113 additions and 25 deletions.
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ci:

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
Expand All @@ -19,7 +19,7 @@ repos:
# - --remove-duplicate-keys
# - --remove-unused-variables
- repo: https://github.com/asottile/pyupgrade
rev: v3.13.0
rev: v3.15.0
hooks:
- id: pyupgrade
args: [--py38-plus]
Expand All @@ -28,7 +28,7 @@ repos:
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 23.9.1
rev: 23.11.0
hooks:
- id: black
args: [--safe, --quiet]
Expand Down Expand Up @@ -77,7 +77,7 @@ repos:
# - id: mypy

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.3
rev: v3.1.0
hooks:
- id: prettier
args: [--prose-wrap=always, --print-width=88]
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ These changes are available on the `master` branch, but have not yet been releas
([#2206](https://github.com/Pycord-Development/pycord/pull/2206))
- Added function `Guild.delete_auto_moderation_rule`.
([#2153](https://github.com/Pycord-Development/pycord/pull/2153))
- Added `VoiceChannel.slowmode_delay`.
([#2112](https://github.com/Pycord-Development/pycord/pull/2112))

### Changed

Expand Down Expand Up @@ -180,6 +182,18 @@ These changes are available on the `master` branch, but have not yet been releas
([#2192](https://github.com/Pycord-Development/pycord/pull/2192))
- Fixed `DMChannel.recipient` being `None` and consequently `User.dm_channel` also being
`None`. ([#2219](https://github.com/Pycord-Development/pycord/pull/2219))
- Fixed ffmpeg being terminated prematurely when piping audio stream.
([#2240](https://github.com/Pycord-Development/pycord/pull/2240))
- Fixed tasks looping infinitely when `tzinfo` is neither `None` nor UTC.
([#2196](https://github.com/Pycord-Development/pycord/pull/2196))
- Fixed `AttributeError` when running permission checks without the `bot` scope.
([#2113](https://github.com/Pycord-Development/pycord/issues/2113))
- Fixed `Option` not working on bridge commands because `ext.commands.Command` doesn't
recognize them. ([#2256](https://github.com/Pycord-Development/pycord/pull/2256))
- Fixed offset-aware tasks causing `TypeError` when being prepared.
([#2271](https://github.com/Pycord-Development/pycord/pull/2271))
- Fixed `AttributeError` when serializing commands with `Annotated` type hints.
([#2243](https://github.com/Pycord-Development/pycord/pull/2243))
- Fixed `Intents.all()` returning the wrong value.
([#2257](https://github.com/Pycord-Development/pycord/issues/2257))

Expand Down
2 changes: 1 addition & 1 deletion discord/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ def permissions_for(self, obj: Member | Role, /) -> Permissions:
return Permissions.all()

default = self.guild.default_role
base = Permissions(default.permissions.value)
base = Permissions(default.permissions.value if default else 0)

# Handle the role case first
if isinstance(obj, Role):
Expand Down
10 changes: 10 additions & 0 deletions discord/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,7 @@ class VocalGuildChannel(discord.abc.Connectable, discord.abc.GuildChannel, Hasha
"user_limit",
"_state",
"position",
"slowmode_delay",
"_overwrites",
"category_id",
"rtc_region",
Expand Down Expand Up @@ -1376,6 +1377,7 @@ def _update(
data, "last_message_id"
)
self.position: int = data.get("position")
self.slowmode_delay = data.get("rate_limit_per_user", 0)
self.bitrate: int = data.get("bitrate")
self.user_limit: int = data.get("user_limit")
self.flags: ChannelFlags = ChannelFlags._from_value(data.get("flags", 0))
Expand Down Expand Up @@ -1483,6 +1485,13 @@ class VoiceChannel(discord.abc.Messageable, VocalGuildChannel):
The ID of the last message sent to this channel. It may not always point to an existing or valid message.
.. versionadded:: 2.0
slowmode_delay: :class:`int`
The number of seconds a member must wait between sending messages
in this channel. A value of `0` denotes that it is disabled.
Bots and users with :attr:`~Permissions.manage_channels` or
:attr:`~Permissions.manage_messages` bypass slowmode.
.. versionadded:: 2.5
flags: :class:`ChannelFlags`
Extra features of the channel.
Expand Down Expand Up @@ -1791,6 +1800,7 @@ async def edit(
overwrites: Mapping[Role | Member, PermissionOverwrite] = ...,
rtc_region: VoiceRegion | None = ...,
video_quality_mode: VideoQualityMode = ...,
slowmode_delay: int = ...,
reason: str | None = ...,
) -> VoiceChannel | None:
...
Expand Down
6 changes: 4 additions & 2 deletions discord/commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -746,10 +746,12 @@ def _parse_options(self, params, *, check_params: bool = True) -> list[Option]:
option = next(option_gen, Option())
# Handle Optional
if self._is_typing_optional(type_hint):
option.input_type = get_args(type_hint)[0]
option.input_type = SlashCommandOptionType.from_datatype(
get_args(type_hint)[0]
)
option.default = None
else:
option.input_type = type_hint
option.input_type = SlashCommandOptionType.from_datatype(type_hint)

if self._is_typing_union(option):
if self._is_typing_optional(option):
Expand Down
11 changes: 9 additions & 2 deletions discord/ext/commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

from ...commands import (
ApplicationCommand,
Option,
_BaseCommand,
message_command,
slash_command,
Expand Down Expand Up @@ -562,7 +563,13 @@ async def dispatch_error(self, ctx: Context, error: Exception) -> None:
ctx.bot.dispatch("command_error", ctx, error)

async def transform(self, ctx: Context, param: inspect.Parameter) -> Any:
required = param.default is param.empty
if isinstance(param.annotation, Option):
default = param.annotation.default
required = param.annotation.required or default is None
else:
default = param.default
required = default is param.empty

converter = get_converter(param)
consume_rest_is_special = (
param.kind == param.KEYWORD_ONLY and not self.rest_is_raw
Expand Down Expand Up @@ -599,7 +606,7 @@ async def transform(self, ctx: Context, param: inspect.Parameter) -> Any:
):
return await converter._construct_default(ctx)
raise MissingRequiredArgument(param)
return param.default
return default

previous = view.index
if consume_rest_is_special:
Expand Down
22 changes: 15 additions & 7 deletions discord/ext/tasks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ def _get_next_sleep_time(self) -> datetime.datetime:
if self._current_loop == 0:
# if we're at the last index on the first iteration, we need to sleep until tomorrow
return datetime.datetime.combine(
datetime.datetime.now(datetime.timezone.utc)
datetime.datetime.now(self._time[0].tzinfo or datetime.timezone.utc)
+ datetime.timedelta(days=1),
self._time[0],
)
Expand All @@ -584,18 +584,26 @@ def _get_next_sleep_time(self) -> datetime.datetime:

if self._current_loop == 0:
self._time_index += 1
if next_time > datetime.datetime.now(datetime.timezone.utc).timetz():
if (
next_time
> datetime.datetime.now(
next_time.tzinfo or datetime.timezone.utc
).timetz()
):
return datetime.datetime.combine(
datetime.datetime.now(datetime.timezone.utc), next_time
datetime.datetime.now(next_time.tzinfo or datetime.timezone.utc),
next_time,
)
else:
return datetime.datetime.combine(
datetime.datetime.now(datetime.timezone.utc)
datetime.datetime.now(next_time.tzinfo or datetime.timezone.utc)
+ datetime.timedelta(days=1),
next_time,
)

next_date = cast(datetime.datetime, self._last_iteration)
next_date = cast(
datetime.datetime, self._last_iteration.astimezone(next_time.tzinfo)
)
if next_time < next_date.timetz():
next_date += datetime.timedelta(days=1)

Expand All @@ -611,9 +619,9 @@ def _prepare_time_index(self, now: datetime.datetime = MISSING) -> None:
now
if now is not MISSING
else datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0)
).timetz()
)
for idx, time in enumerate(self._time):
if time >= time_now:
if time >= time_now.astimezone(time.tzinfo).timetz():
self._time_index = idx
break
else:
Expand Down
9 changes: 9 additions & 0 deletions discord/interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ class Interaction:
"custom_id",
"_channel_data",
"_message_data",
"_guild_data",
"_guild",
"_permissions",
"_app_permissions",
"_state",
Expand Down Expand Up @@ -188,6 +190,11 @@ def _from_data(self, data: InteractionPayload):
self.user: User | Member | None = None
self._permissions: int = 0

self._guild: Guild | None = None
self._guild_data = data.get("guild")
if self.guild is None and self._guild_data:
self._guild = Guild(data=self._guild_data, state=self)

# TODO: there's a potential data loss here
if self.guild_id:
guild = (
Expand Down Expand Up @@ -246,6 +253,8 @@ def client(self) -> Client:
@property
def guild(self) -> Guild | None:
"""The guild the interaction was sent from."""
if self._guild:
return self._guild
return self._state and self._state._get_guild(self.guild_id)

def is_command(self) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion discord/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def _pipe_writer(self, source: io.BufferedIOBase) -> None:
# arbitrarily large read size
data = source.read(8192)
if not data:
self._process.terminate()
self._stdin.close()
return
try:
self._stdin.write(data)
Expand Down
2 changes: 1 addition & 1 deletion requirements/_.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
aiohttp>=3.6.0,<3.9.0
aiohttp>=3.6.0,<3.10.0
typing_extensions>=4,<5; python_version < "3.11"
4 changes: 2 additions & 2 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
-r _.txt
pylint~=2.17.5
pylint~=3.0.2
pytest~=7.4.3
pytest-asyncio~=0.21.1
# pytest-order~=1.0.1
mypy~=1.5.1
mypy~=1.7.1
coverage~=7.3
pre-commit==3.5.0
codespell==2.2.6
Expand Down
2 changes: 1 addition & 1 deletion requirements/docs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ sphinx==5.3.0
sphinxcontrib_trio==1.1.2
sphinxcontrib-websupport==1.2.4
myst-parser==1.0.0
sphinxext-opengraph==0.8.2
sphinxext-opengraph==0.9.0
sphinx-copybutton==0.5.2
furo@ git+https://github.com/pradyunsg/furo@193643f
sphinx-autodoc-typehints==1.23.0
46 changes: 42 additions & 4 deletions tests/test_typing_annotated.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from typing import Optional

import pytest
from typing_extensions import Annotated

import discord
from discord import ApplicationContext
from discord import SlashCommandOptionType
from discord.commands.core import SlashCommand, slash_command


Expand All @@ -15,6 +14,10 @@ async def echo(ctx, txt: Annotated[str, discord.Option()]):
cmd = SlashCommand(echo)
bot = discord.Bot()
bot.add_application_command(cmd)
dict_result = cmd.to_dict()
assert (
dict_result.get("options")[0].get("type") == SlashCommandOptionType.string.value
)


def test_typing_annotated_decorator():
Expand All @@ -24,6 +27,12 @@ def test_typing_annotated_decorator():
async def echo(ctx, txt: Annotated[str, discord.Option(description="Some text")]):
await ctx.respond(txt)

dict_result = echo.to_dict()

option = dict_result.get("options")[0]
assert option.get("type") == SlashCommandOptionType.string.value
assert option.get("description") == "Some text"


def test_typing_annotated_cog():
class echoCog(discord.Cog):
Expand All @@ -38,7 +47,14 @@ async def echo(
await ctx.respond(txt)

bot = discord.Bot()
bot.add_cog(echoCog(bot))
cog = echoCog(bot)
bot.add_cog(cog)

dict_result = cog.echo.to_dict()

option = dict_result.get("options")[0]
assert option.get("type") == SlashCommandOptionType.string.value
assert option.get("description") == "Some text"


def test_typing_annotated_cog_slashgroup():
Expand All @@ -56,7 +72,14 @@ async def echo(
await ctx.respond(txt)

bot = discord.Bot()
bot.add_cog(echoCog(bot))
cog = echoCog(bot)
bot.add_cog(cog)

dict_result = cog.echo.to_dict()

option = dict_result.get("options")[0]
assert option.get("type") == SlashCommandOptionType.string.value
assert option.get("description") == "Some text"


def test_typing_annotated_optional():
Expand All @@ -67,6 +90,11 @@ async def echo(ctx, txt: Annotated[Optional[str], discord.Option()]):
bot = discord.Bot()
bot.add_application_command(cmd)

dict_result = cmd.to_dict()

option = dict_result.get("options")[0]
assert option.get("type") == SlashCommandOptionType.string.value


def test_no_annotation():
async def echo(ctx, txt: str):
Expand All @@ -76,6 +104,11 @@ async def echo(ctx, txt: str):
bot = discord.Bot()
bot.add_application_command(cmd)

dict_result = cmd.to_dict()

option = dict_result.get("options")[0]
assert option.get("type") == SlashCommandOptionType.string.value


def test_annotated_no_option():
async def echo(ctx, txt: Annotated[str, "..."]):
Expand All @@ -84,3 +117,8 @@ async def echo(ctx, txt: Annotated[str, "..."]):
cmd = SlashCommand(echo)
bot = discord.Bot()
bot.add_application_command(cmd)

dict_result = cmd.to_dict()

option = dict_result.get("options")[0]
assert option.get("type") == SlashCommandOptionType.string.value

0 comments on commit b413933

Please sign in to comment.