From 407b41a22ee1f5a0573c1d8e098aa3ba1b994403 Mon Sep 17 00:00:00 2001 From: Middledot Date: Tue, 10 Jan 2023 22:10:50 -0500 Subject: [PATCH 1/7] chore(i18n): make defaults for l10ns an empty dict --- discord/commands/core.py | 54 ++++++++++++++++++------------------- discord/commands/options.py | 18 ++++++------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/discord/commands/core.py b/discord/commands/core.py index 6ba369c5d0..75c317d6d6 100644 --- a/discord/commands/core.py +++ b/discord/commands/core.py @@ -155,16 +155,14 @@ def unwrap_function(function: Callable[..., Any]) -> Callable[..., Any]: def _validate_names(obj): validate_chat_input_name(obj.name) - if obj.name_localizations: - for locale, string in obj.name_localizations.items(): - validate_chat_input_name(string, locale=locale) + for locale, string in obj.name_localizations.items(): + validate_chat_input_name(string, locale=locale) def _validate_descriptions(obj): validate_chat_input_description(obj.description) - if obj.description_localizations: - for locale, string in obj.description_localizations.items(): - validate_chat_input_description(string, locale=locale) + for locale, string in obj.description_localizations.items(): + validate_chat_input_description(string, locale=locale) class _BaseCommand: @@ -647,10 +645,10 @@ class SlashCommand(ApplicationCommand): cooldown: Optional[:class:`~discord.ext.commands.Cooldown`] The cooldown applied when the command is invoked. ``None`` if the command doesn't have a cooldown. - name_localizations: Optional[Dict[:class:`str`, :class:`str`]] + name_localizations: Dict[:class:`str`, :class:`str`] The name localizations for this command. The values of this should be ``"locale": "name"``. See `here `_ for a list of valid locales. - description_localizations: Optional[Dict[:class:`str`, :class:`str`]] + description_localizations: Dict[:class:`str`, :class:`str`] The description localizations for this command. The values of this should be ``"locale": "description"``. See `here `_ for a list of valid locales. """ @@ -668,8 +666,8 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: raise TypeError("Callback must be a coroutine.") self.callback = func - self.name_localizations: dict[str, str] | None = kwargs.get( - "name_localizations", None + self.name_localizations: dict[str, str] = kwargs.get( + "name_localizations", {} ) _validate_names(self) @@ -680,8 +678,8 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: ) self.description: str = description - self.description_localizations: dict[str, str] | None = kwargs.get( - "description_localizations", None + self.description_localizations: dict[str, str] = kwargs.get( + "description_localizations", {} ) _validate_descriptions(self) @@ -843,9 +841,9 @@ def to_dict(self) -> dict: "description": self.description, "options": [o.to_dict() for o in self.options], } - if self.name_localizations is not None: + if self.name_localizations: as_dict["name_localizations"] = self.name_localizations - if self.description_localizations is not None: + if self.description_localizations: as_dict["description_localizations"] = self.description_localizations if self.is_subcommand: as_dict["type"] = SlashCommandOptionType.sub_command.value @@ -1079,10 +1077,10 @@ class SlashCommandGroup(ApplicationCommand): :exc:`.ApplicationCommandError` should be used. Note that if the checks fail then :exc:`.CheckFailure` exception is raised to the :func:`.on_application_command_error` event. - name_localizations: Optional[Dict[:class:`str`, :class:`str`]] + name_localizations: Dict[:class:`str`, :class:`str`] The name localizations for this command. The values of this should be ``"locale": "name"``. See `here `_ for a list of valid locales. - description_localizations: Optional[Dict[:class:`str`, :class:`str`]] + description_localizations: Dict[:class:`str`, :class:`str`] The description localizations for this command. The values of this should be ``"locale": "description"``. See `here `_ for a list of valid locales. """ @@ -1144,11 +1142,11 @@ def __init__( self.guild_only: bool | None = kwargs.get("guild_only", None) self.nsfw: bool | None = kwargs.get("nsfw", None) - self.name_localizations: dict[str, str] | None = kwargs.get( - "name_localizations", None + self.name_localizations: dict[str, str] = kwargs.get( + "name_localizations", {} ) - self.description_localizations: dict[str, str] | None = kwargs.get( - "description_localizations", None + self.description_localizations: dict[str, str] = kwargs.get( + "description_localizations", {} ) @property @@ -1161,9 +1159,9 @@ def to_dict(self) -> dict: "description": self.description, "options": [c.to_dict() for c in self.subcommands], } - if self.name_localizations is not None: + if self.name_localizations: as_dict["name_localizations"] = self.name_localizations - if self.description_localizations is not None: + if self.description_localizations: as_dict["description_localizations"] = self.description_localizations if self.parent is not None: @@ -1234,10 +1232,10 @@ def create_subgroup( :exc:`.ApplicationCommandError` should be used. Note that if the checks fail then :exc:`.CheckFailure` exception is raised to the :func:`.on_application_command_error` event. - name_localizations: Optional[Dict[:class:`str`, :class:`str`]] + name_localizations: Dict[:class:`str`, :class:`str`] The name localizations for this command. The values of this should be ``"locale": "name"``. See `here `_ for a list of valid locales. - description_localizations: Optional[Dict[:class:`str`, :class:`str`]] + description_localizations: Dict[:class:`str`, :class:`str`] The description localizations for this command. The values of this should be ``"locale": "description"``. See `here `_ for a list of valid locales. @@ -1411,7 +1409,7 @@ class ContextMenuCommand(ApplicationCommand): cooldown: Optional[:class:`~discord.ext.commands.Cooldown`] The cooldown applied when the command is invoked. ``None`` if the command doesn't have a cooldown. - name_localizations: Optional[Dict[:class:`str`, :class:`str`]] + name_localizations: Dict[:class:`str`, :class:`str`] The name localizations for this command. The values of this should be ``"locale": "name"``. See `here `_ for a list of valid locales. """ @@ -1428,8 +1426,8 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: raise TypeError("Callback must be a coroutine.") self.callback = func - self.name_localizations: dict[str, str] | None = kwargs.get( - "name_localizations", None + self.name_localizations: dict[str, str] = kwargs.get( + "name_localizations", {} ) # Discord API doesn't support setting descriptions for context menu commands, so it must be empty @@ -1504,7 +1502,7 @@ def to_dict(self) -> dict[str, str | int]: "default_member_permissions" ] = self.default_member_permissions.value - if self.name_localizations is not None: + if self.name_localizations: as_dict["name_localizations"] = self.name_localizations return as_dict diff --git a/discord/commands/options.py b/discord/commands/options.py index 936eb34d9c..101a185dee 100644 --- a/discord/commands/options.py +++ b/discord/commands/options.py @@ -138,10 +138,10 @@ class Option: .. note:: Does not validate the input value against the autocomplete results. - name_localizations: Optional[Dict[:class:`str`, :class:`str`]] + name_localizations: Dict[:class:`str`, :class:`str`] The name localizations for this option. The values of this should be ``"locale": "name"``. See `here `_ for a list of valid locales. - description_localizations: Optional[Dict[:class:`str`, :class:`str`]] + description_localizations: Dict[:class:`str`, :class:`str`] The description localizations for this option. The values of this should be ``"locale": "description"``. See `here `_ for a list of valid locales. @@ -308,8 +308,8 @@ def __init__( self.autocomplete = kwargs.pop("autocomplete", None) - self.name_localizations = kwargs.pop("name_localizations", None) - self.description_localizations = kwargs.pop("description_localizations", None) + self.name_localizations = kwargs.pop("name_localizations", {}) + self.description_localizations = kwargs.pop("description_localizations", {}) def to_dict(self) -> dict: as_dict = { @@ -320,9 +320,9 @@ def to_dict(self) -> dict: "choices": [c.to_dict() for c in self.choices], "autocomplete": bool(self.autocomplete), } - if self.name_localizations is not None: + if self.name_localizations: as_dict["name_localizations"] = self.name_localizations - if self.description_localizations is not None: + if self.description_localizations: as_dict["description_localizations"] = self.description_localizations if self.channel_types: as_dict["channel_types"] = [t.value for t in self.channel_types] @@ -353,7 +353,7 @@ class OptionChoice: The name of the choice. Shown in the UI when selecting an option. value: Optional[Union[:class:`str`, :class:`int`, :class:`float`]] The value of the choice. If not provided, will use the value of ``name``. - name_localizations: Optional[Dict[:class:`str`, :class:`str`]] + name_localizations: Dict[:class:`str`, :class:`str`] The name localizations for this choice. The values of this should be ``"locale": "name"``. See `here `_ for a list of valid locales. """ @@ -362,7 +362,7 @@ def __init__( self, name: str, value: str | int | float | None = None, - name_localizations: dict[str, str] | None = None, + name_localizations: dict[str, str] = {}, ): self.name = str(name) self.value = value if value is not None else name @@ -370,7 +370,7 @@ def __init__( def to_dict(self) -> dict[str, str | int | float]: as_dict = {"name": self.name, "value": self.value} - if self.name_localizations is not None: + if self.name_localizations: as_dict["name_localizations"] = self.name_localizations return as_dict From f220092ad8a8156e39c854a6ba1a8cd1adfed294 Mon Sep 17 00:00:00 2001 From: Middledot Date: Tue, 10 Jan 2023 22:13:54 -0500 Subject: [PATCH 2/7] chore(changelog): add entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e663073008..5b79d76c0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,9 @@ These changes are available on the `master` branch, but have not yet been releas - Changed `EmbeddedActivity` values to update accordingly with the new activities. ([#1859](https://github.com/Pycord-Development/pycord/pull/1859)) +- Change default for all `name_localizations` & `description_localizations` attributes + from being `None` to an empty dictionary. + ([#1866](https://github.com/Pycord-Development/pycord/pull/1859)) ## [2.3.2] - 2022-12-03 From 4f5bf818b0fc34f926703f1e6b495a77fefc14d9 Mon Sep 17 00:00:00 2001 From: Middledot Date: Tue, 10 Jan 2023 22:17:25 -0500 Subject: [PATCH 3/7] fix(changlog): update entry oops --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b79d76c0a..f8e302f28a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,7 +30,7 @@ These changes are available on the `master` branch, but have not yet been releas ([#1859](https://github.com/Pycord-Development/pycord/pull/1859)) - Change default for all `name_localizations` & `description_localizations` attributes from being `None` to an empty dictionary. - ([#1866](https://github.com/Pycord-Development/pycord/pull/1859)) + ([#1866](https://github.com/Pycord-Development/pycord/pull/1866)) ## [2.3.2] - 2022-12-03 From 5bc36e64ba164ec70e00a7d19ea6ea023c73c074 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 11 Jan 2023 03:20:00 +0000 Subject: [PATCH 4/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- discord/commands/core.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/discord/commands/core.py b/discord/commands/core.py index 75c317d6d6..23e4a747e6 100644 --- a/discord/commands/core.py +++ b/discord/commands/core.py @@ -666,9 +666,7 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: raise TypeError("Callback must be a coroutine.") self.callback = func - self.name_localizations: dict[str, str] = kwargs.get( - "name_localizations", {} - ) + self.name_localizations: dict[str, str] = kwargs.get("name_localizations", {}) _validate_names(self) description = kwargs.get("description") or ( @@ -1142,9 +1140,7 @@ def __init__( self.guild_only: bool | None = kwargs.get("guild_only", None) self.nsfw: bool | None = kwargs.get("nsfw", None) - self.name_localizations: dict[str, str] = kwargs.get( - "name_localizations", {} - ) + self.name_localizations: dict[str, str] = kwargs.get("name_localizations", {}) self.description_localizations: dict[str, str] = kwargs.get( "description_localizations", {} ) @@ -1426,9 +1422,7 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: raise TypeError("Callback must be a coroutine.") self.callback = func - self.name_localizations: dict[str, str] = kwargs.get( - "name_localizations", {} - ) + self.name_localizations: dict[str, str] = kwargs.get("name_localizations", {}) # Discord API doesn't support setting descriptions for context menu commands, so it must be empty self.description = "" From 4512de10274f14e0dd3db8e015b5ab1ad569bb99 Mon Sep 17 00:00:00 2001 From: Middledot Date: Sun, 2 Apr 2023 04:38:40 -0400 Subject: [PATCH 5/7] feat(i18n): None -> MISSING --- CHANGELOG.md | 8 ++++---- discord/commands/core.py | 18 +++++++++--------- discord/commands/options.py | 13 +++++++------ 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d182b11def..9867e9e883 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ These changes are available on the `master` branch, but have not yet been releas ### Added +- Change default for all `name_localizations` & `description_localizations` attributes + from being `None` to be `MISSING`. + ([#1866](https://github.com/Pycord-Development/pycord/pull/1866)) - Added new events `on_bridge_command`, `on_bridge_command_completion`, and `on_bridge_command_error`. ([#1916](https://github.com/Pycord-Development/pycord/pull/1916)) @@ -22,7 +25,7 @@ These changes are available on the `master` branch, but have not yet been releas - Added support for one-time event listeners in `@client.listen()`. ([#1957](https://github.com/Pycord-Development/pycord/pull/1957)) - Added `current_page` argument to Paginator.update(). - ([#1983](https://github.com/Pycord-Development/pycord/pull/1983) + ([#1983](https://github.com/Pycord-Development/pycord/pull/1983)) - Added new `application_auto_moderation_rule_create_badge` to `ApplicationFlags`. ([#1992](https://github.com/Pycord-Development/pycord/pull/1992)) @@ -88,9 +91,6 @@ These changes are available on the `master` branch, but have not yet been releas - Changed `EmbeddedActivity` values to update accordingly with the new activities. ([#1859](https://github.com/Pycord-Development/pycord/pull/1859)) -- Change default for all `name_localizations` & `description_localizations` attributes - from being `None` to an empty dictionary. - ([#1866](https://github.com/Pycord-Development/pycord/pull/1866)) - Advanced version info is now stored as a dict in `version_info.advanced` instead of attributes on the `version_info` object. ([#1920](https://github.com/Pycord-Development/pycord/pull/1920)) diff --git a/discord/commands/core.py b/discord/commands/core.py index 153100043b..6a2bd6fd9b 100644 --- a/discord/commands/core.py +++ b/discord/commands/core.py @@ -666,7 +666,7 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: raise TypeError("Callback must be a coroutine.") self.callback = func - self.name_localizations: dict[str, str] = kwargs.get("name_localizations", {}) + self.name_localizations: dict[str, str] = kwargs.get("name_localizations", MISSING) _validate_names(self) description = kwargs.get("description") or ( @@ -677,7 +677,7 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: self.description: str = description self.description_localizations: dict[str, str] = kwargs.get( - "description_localizations", {} + "description_localizations", MISSING ) _validate_descriptions(self) @@ -839,9 +839,9 @@ def to_dict(self) -> dict: "description": self.description, "options": [o.to_dict() for o in self.options], } - if self.name_localizations: + if self.name_localizations is not MISSING: as_dict["name_localizations"] = self.name_localizations - if self.description_localizations: + if self.description_localizations is not MISSING: as_dict["description_localizations"] = self.description_localizations if self.is_subcommand: as_dict["type"] = SlashCommandOptionType.sub_command.value @@ -1142,9 +1142,9 @@ def __init__( self.guild_only: bool | None = kwargs.get("guild_only", None) self.nsfw: bool | None = kwargs.get("nsfw", None) - self.name_localizations: dict[str, str] = kwargs.get("name_localizations", {}) + self.name_localizations: dict[str, str] = kwargs.get("name_localizations", MISSING) self.description_localizations: dict[str, str] = kwargs.get( - "description_localizations", {} + "description_localizations", MISSING ) @property @@ -1157,9 +1157,9 @@ def to_dict(self) -> dict: "description": self.description, "options": [c.to_dict() for c in self.subcommands], } - if self.name_localizations: + if self.name_localizations is not MISSING: as_dict["name_localizations"] = self.name_localizations - if self.description_localizations: + if self.description_localizations is not MISSING: as_dict["description_localizations"] = self.description_localizations if self.parent is not None: @@ -1424,7 +1424,7 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: raise TypeError("Callback must be a coroutine.") self.callback = func - self.name_localizations: dict[str, str] = kwargs.get("name_localizations", {}) + self.name_localizations: dict[str, str] = kwargs.get("name_localizations", MISSING) # Discord API doesn't support setting descriptions for context menu commands, so it must be empty self.description = "" diff --git a/discord/commands/options.py b/discord/commands/options.py index d9e08d122a..c651de9f6d 100644 --- a/discord/commands/options.py +++ b/discord/commands/options.py @@ -38,6 +38,7 @@ Thread, VoiceChannel, ) +from ..utils import MISSING from ..enums import ChannelType from ..enums import Enum as DiscordEnum from ..enums import SlashCommandOptionType @@ -323,8 +324,8 @@ def __init__( self.autocomplete = kwargs.pop("autocomplete", None) - self.name_localizations = kwargs.pop("name_localizations", {}) - self.description_localizations = kwargs.pop("description_localizations", {}) + self.name_localizations = kwargs.pop("name_localizations", MISSING) + self.description_localizations = kwargs.pop("description_localizations", MISSING) def to_dict(self) -> dict: as_dict = { @@ -335,9 +336,9 @@ def to_dict(self) -> dict: "choices": [c.to_dict() for c in self.choices], "autocomplete": bool(self.autocomplete), } - if self.name_localizations: + if self.name_localizations is not MISSING: as_dict["name_localizations"] = self.name_localizations - if self.description_localizations: + if self.description_localizations is not MISSING: as_dict["description_localizations"] = self.description_localizations if self.channel_types: as_dict["channel_types"] = [t.value for t in self.channel_types] @@ -377,7 +378,7 @@ def __init__( self, name: str, value: str | int | float | None = None, - name_localizations: dict[str, str] = {}, + name_localizations: dict[str, str] = MISSING, ): self.name = str(name) self.value = value if value is not None else name @@ -385,7 +386,7 @@ def __init__( def to_dict(self) -> dict[str, str | int | float]: as_dict = {"name": self.name, "value": self.value} - if self.name_localizations: + if self.name_localizations is not MISSING: as_dict["name_localizations"] = self.name_localizations return as_dict From 3c59136fde617cb80f8490dcc5f9016acd85a8a5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 2 Apr 2023 08:39:04 +0000 Subject: [PATCH 6/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- discord/commands/core.py | 12 +++++++++--- discord/commands/options.py | 6 ++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/discord/commands/core.py b/discord/commands/core.py index 6a2bd6fd9b..2027271d8c 100644 --- a/discord/commands/core.py +++ b/discord/commands/core.py @@ -666,7 +666,9 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: raise TypeError("Callback must be a coroutine.") self.callback = func - self.name_localizations: dict[str, str] = kwargs.get("name_localizations", MISSING) + self.name_localizations: dict[str, str] = kwargs.get( + "name_localizations", MISSING + ) _validate_names(self) description = kwargs.get("description") or ( @@ -1142,7 +1144,9 @@ def __init__( self.guild_only: bool | None = kwargs.get("guild_only", None) self.nsfw: bool | None = kwargs.get("nsfw", None) - self.name_localizations: dict[str, str] = kwargs.get("name_localizations", MISSING) + self.name_localizations: dict[str, str] = kwargs.get( + "name_localizations", MISSING + ) self.description_localizations: dict[str, str] = kwargs.get( "description_localizations", MISSING ) @@ -1424,7 +1428,9 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: raise TypeError("Callback must be a coroutine.") self.callback = func - self.name_localizations: dict[str, str] = kwargs.get("name_localizations", MISSING) + self.name_localizations: dict[str, str] = kwargs.get( + "name_localizations", MISSING + ) # Discord API doesn't support setting descriptions for context menu commands, so it must be empty self.description = "" diff --git a/discord/commands/options.py b/discord/commands/options.py index c651de9f6d..5199f0beaf 100644 --- a/discord/commands/options.py +++ b/discord/commands/options.py @@ -38,10 +38,10 @@ Thread, VoiceChannel, ) -from ..utils import MISSING from ..enums import ChannelType from ..enums import Enum as DiscordEnum from ..enums import SlashCommandOptionType +from ..utils import MISSING if TYPE_CHECKING: from ..ext.commands import Converter @@ -325,7 +325,9 @@ def __init__( self.autocomplete = kwargs.pop("autocomplete", None) self.name_localizations = kwargs.pop("name_localizations", MISSING) - self.description_localizations = kwargs.pop("description_localizations", MISSING) + self.description_localizations = kwargs.pop( + "description_localizations", MISSING + ) def to_dict(self) -> dict: as_dict = { From 14b8920ff9a6ea8d99e994620ec91c9c1fbeee12 Mon Sep 17 00:00:00 2001 From: Middledot <78228142+Middledot@users.noreply.github.com> Date: Mon, 24 Apr 2023 10:46:00 -0400 Subject: [PATCH 7/7] Apply suggestions from code review adapt Co-authored-by: plun1331 <49261529+plun1331@users.noreply.github.com> Signed-off-by: Middledot <78228142+Middledot@users.noreply.github.com> --- discord/commands/core.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/discord/commands/core.py b/discord/commands/core.py index 2027271d8c..90a614a786 100644 --- a/discord/commands/core.py +++ b/discord/commands/core.py @@ -155,14 +155,16 @@ def unwrap_function(function: Callable[..., Any]) -> Callable[..., Any]: def _validate_names(obj): validate_chat_input_name(obj.name) - for locale, string in obj.name_localizations.items(): - validate_chat_input_name(string, locale=locale) + if obj.name_localizations: + for locale, string in obj.name_localizations.items(): + validate_chat_input_name(string, locale=locale) def _validate_descriptions(obj): validate_chat_input_description(obj.description) - for locale, string in obj.description_localizations.items(): - validate_chat_input_description(string, locale=locale) + if obj.description_localizations: + for locale, string in obj.description_localizations.items(): + validate_chat_input_description(string, locale=locale) class _BaseCommand: