diff --git a/changes/1574.feature.md b/changes/1574.feature.md new file mode 100644 index 0000000000..96466240f1 --- /dev/null +++ b/changes/1574.feature.md @@ -0,0 +1,8 @@ +Added several set methods for required values to the builders: + +* `CommandBuilder.set_name` +* `SlashCommandBuilder.set_description` +* `InteractiveButtonBuilder.set_custom_id` +* `SelectOptionBuilder.set_label` +* `SelectOptionBuilder.set_value` +* `SelectMenuBuilder.set_custom_id` diff --git a/hikari/api/special_endpoints.py b/hikari/api/special_endpoints.py index 446ea9a4ab..3007afe237 100644 --- a/hikari/api/special_endpoints.py +++ b/hikari/api/special_endpoints.py @@ -958,7 +958,7 @@ def set_title(self, title: str, /) -> Self: @abc.abstractmethod def set_custom_id(self, custom_id: str, /) -> Self: - """Set the developer set custom ID used for identifying interactions with this modal. + """Set the custom ID used for identifying interactions with this modal. Parameters ---------- @@ -1029,6 +1029,21 @@ def is_nsfw(self) -> undefined.UndefinedOr[bool]: def name_localizations(self) -> typing.Mapping[typing.Union[locales.Locale, str], str]: """Name localizations set for this command.""" + @abc.abstractmethod + def set_name(self, name: str, /) -> Self: + """Set the name of this command. + + Parameters + ---------- + name : str + The name to set for this command. + + Returns + ------- + CommandBuilder + Object of this command builder to allow for chained calls. + """ + @abc.abstractmethod def set_id(self, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) -> Self: """Set the ID of this command. @@ -1177,6 +1192,26 @@ def description(self) -> str: def description_localizations(self) -> typing.Mapping[typing.Union[locales.Locale, str], str]: """Command's localised descriptions.""" + @property + @abc.abstractmethod + def options(self) -> typing.Sequence[commands.CommandOption]: + """Sequence of up to 25 of the options set for this command.""" + + @abc.abstractmethod + def set_description(self, description: str, /) -> Self: + """Set the description for this command. + + Parameters + ---------- + description : str + The description to set for this command. + + Returns + ------- + SlashCommandBuilder + Object of this command builder. + """ + @abc.abstractmethod def set_description_localizations( self, description_localizations: typing.Mapping[typing.Union[locales.Locale, str], str], / @@ -1190,15 +1225,10 @@ def set_description_localizations( Returns ------- - CommandBuilder + SlashCommandBuilder Object of this command builder. """ - @property - @abc.abstractmethod - def options(self) -> typing.Sequence[commands.CommandOption]: - """Sequence of up to 25 of the options set for this command.""" - @abc.abstractmethod def add_option(self, option: commands.CommandOption) -> Self: """Add an option to this command. @@ -1213,7 +1243,7 @@ def add_option(self, option: commands.CommandOption) -> Self: Returns ------- - CommandBuilder + SlashCommandBuilder Object of this command builder to allow for chained calls. """ @@ -1421,6 +1451,21 @@ class InteractiveButtonBuilder(ButtonBuilder, abc.ABC): def custom_id(self) -> str: """Developer set custom ID used for identifying interactions with this button.""" + @abc.abstractmethod + def set_custom_id(self, custom_id: str, /) -> Self: + """Set the custom ID used for identifying this button. + + Parameters + ---------- + custom_id : str + Developer set custom ID used for identifying this button. + + Returns + ------- + InteractiveButtonBuilder + The builder object to enable chained calls. + """ + class SelectOptionBuilder(abc.ABC): """Builder class for select menu options.""" @@ -1452,6 +1497,38 @@ def emoji(self) -> typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, unde def is_default(self) -> bool: """Whether this option should be marked as selected by default.""" + @abc.abstractmethod + def set_label(self, label: str, /) -> Self: + """Set the option's label. + + Parameters + ---------- + label : str + Label to set for this option. This can be up to 100 characters + long. + + Returns + ------- + SelectOptionBuilder + The builder object to enable chained calls. + """ + + @abc.abstractmethod + def set_value(self, value: str, /) -> Self: + """Set the option's value. + + Parameters + ---------- + value : str + Value to set for this option. This can be up to 100 characters + long. + + Returns + ------- + SelectOptionBuilder + The builder object to enable chained calls. + """ + @abc.abstractmethod def set_description(self, value: undefined.UndefinedOr[str], /) -> Self: """Set the option's description. @@ -1552,6 +1629,21 @@ def max_values(self) -> int: less than or equal to 25. """ + @abc.abstractmethod + def set_custom_id(self, custom_id: str, /) -> Self: + """Set the custom ID used for identifying this menu. + + Parameters + ---------- + custom_id : str + Developer set custom ID used for identifying this menu. + + Returns + ------- + SelectMenuBuilder + The builder object to enable chained calls. + """ + @abc.abstractmethod def set_is_disabled(self, state: bool, /) -> Self: """Set whether this option is disabled. @@ -1777,7 +1869,7 @@ def set_style(self, style: typing.Union[components_.TextInputStyle, int], /) -> @abc.abstractmethod def set_custom_id(self, custom_id: str, /) -> Self: - """Set the developer set custom ID used for identifying this text input. + """Set the custom ID used for identifying this text input. Parameters ---------- diff --git a/hikari/impl/special_endpoints.py b/hikari/impl/special_endpoints.py index e1df47f0e7..e743224267 100644 --- a/hikari/impl/special_endpoints.py +++ b/hikari/impl/special_endpoints.py @@ -1335,6 +1335,10 @@ def is_nsfw(self) -> undefined.UndefinedOr[bool]: def name(self) -> str: return self._name + def set_name(self, name: str, /) -> Self: + self._name = name + return self + def set_id(self, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) -> Self: self._id = snowflakes.Snowflake(id_) if id_ is not undefined.UNDEFINED else undefined.UNDEFINED return self @@ -1399,10 +1403,6 @@ def description(self) -> str: def type(self) -> commands.CommandType: return commands.CommandType.SLASH - def add_option(self, option: commands.CommandOption) -> Self: - self._options.append(option) - return self - @property def options(self) -> typing.Sequence[commands.CommandOption]: return self._options.copy() @@ -1411,12 +1411,20 @@ def options(self) -> typing.Sequence[commands.CommandOption]: def description_localizations(self) -> typing.Mapping[typing.Union[locales.Locale, str], str]: return self._description_localizations + def set_description(self, description: str, /) -> Self: + self._description = description + return self + def set_description_localizations( self, description_localizations: typing.Mapping[typing.Union[locales.Locale, str], str], / ) -> Self: self._description_localizations = description_localizations return self + def add_option(self, option: commands.CommandOption) -> Self: + self._options.append(option) + return self + def build(self, entity_factory: entity_factory_.EntityFactory, /) -> typing.MutableMapping[str, typing.Any]: data = super().build(entity_factory) # Under this context we know this'll always be a JSONObjectBuilder but @@ -1607,6 +1615,10 @@ class InteractiveButtonBuilder(_ButtonBuilder, special_endpoints.InteractiveButt def custom_id(self) -> str: return self._custom_id + def set_custom_id(self, custom_id: str, /) -> Self: + self._custom_id = custom_id + return self + @attrs_extensions.with_copy @attrs.define(weakref_slot=False) @@ -1648,6 +1660,14 @@ def emoji(self) -> typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, unde def is_default(self) -> bool: return self._is_default + def set_label(self, label: str, /) -> Self: + self._label = label + return self + + def set_value(self, value: str, /) -> Self: + self._value = value + return self + def set_description(self, value: undefined.UndefinedOr[str], /) -> Self: self._description = value return self @@ -1716,6 +1736,10 @@ def min_values(self) -> int: def max_values(self) -> int: return self._max_values + def set_custom_id(self, custom_id: str, /) -> Self: + self._custom_id = custom_id + return self + def set_is_disabled(self, state: bool, /) -> Self: self._is_disabled = state return self diff --git a/tests/hikari/impl/test_special_endpoints.py b/tests/hikari/impl/test_special_endpoints.py index 39f54b8ce5..24a7601f99 100644 --- a/tests/hikari/impl/test_special_endpoints.py +++ b/tests/hikari/impl/test_special_endpoints.py @@ -1045,43 +1045,57 @@ def test_build(self): assert attachments == () -class TestSlashCommandBuilder: - def test_description_property(self): - builder = special_endpoints.SlashCommandBuilder("ok", "NO") +class TestCommandBuilder: + @pytest.fixture() + def stub_command(self) -> typing.Type[special_endpoints.CommandBuilder]: + return hikari_test_helpers.mock_class_namespace(special_endpoints.CommandBuilder) - assert builder.description == "NO" + def test_name_property(self, stub_command): + builder = stub_command("NOOOOO").set_name("aaaaa") - def test_name_property(self): - builder = special_endpoints.SlashCommandBuilder("NOOOOO", "OKKKK") + assert builder.name == "aaaaa" - assert builder.name == "NOOOOO" + def test_id_property(self, stub_command): + builder = stub_command("OKSKDKSDK").set_id(3212123) - def test_options_property(self): - builder = special_endpoints.SlashCommandBuilder("OKSKDKSDK", "inmjfdsmjiooikjsa") - mock_option = object() + assert builder.id == 3212123 - assert builder.options == [] + def test_default_member_permissions(self, stub_command): + builder = stub_command("oksksksk").set_default_member_permissions(permissions.Permissions.ADMINISTRATOR) - builder.add_option(mock_option) + assert builder.default_member_permissions == permissions.Permissions.ADMINISTRATOR - assert builder.options == [mock_option] + def test_is_dm_enabled(self, stub_command): + builder = stub_command("oksksksk").set_is_dm_enabled(True) - def test_id_property(self): - builder = special_endpoints.SlashCommandBuilder("OKSKDKSDK", "inmjfdsmjiooikjsa").set_id(3212123) + assert builder.is_dm_enabled is True - assert builder.id == 3212123 + def test_is_nsfw_property(self, stub_command): + builder = stub_command("oksksksk").set_is_nsfw(True) - def test_default_member_permissions(self): - builder = special_endpoints.SlashCommandBuilder("oksksksk", "kfdkodfokfd").set_default_member_permissions( - permissions.Permissions.ADMINISTRATOR - ) + assert builder.is_nsfw is True - assert builder.default_member_permissions == permissions.Permissions.ADMINISTRATOR + def test_name_localizations_property(self, stub_command): + builder = stub_command("oksksksk").set_name_localizations({"aaa": "bbb", "ccc": "DDd"}) - def test_is_dm_enabled(self): - builder = special_endpoints.SlashCommandBuilder("oksksksk", "kfdkodfokfd").set_is_dm_enabled(True) + assert builder.name_localizations == {"aaa": "bbb", "ccc": "DDd"} - assert builder.is_dm_enabled is True + +class TestSlashCommandBuilder: + def test_description_property(self): + builder = special_endpoints.SlashCommandBuilder("ok", "NO").set_description("meow") + + assert builder.description == "meow" + + def test_options_property(self): + builder = special_endpoints.SlashCommandBuilder("OKSKDKSDK", "inmjfdsmjiooikjsa") + mock_option = object() + + assert builder.options == [] + + builder.add_option(mock_option) + + assert builder.options == [mock_option] def test_build_with_optional_data(self): mock_entity_factory = mock.Mock() @@ -1401,10 +1415,10 @@ def test_url_property(self): class TestInteractiveButtonBuilder: def test_custom_id_property(self): button = special_endpoints.InteractiveButtonBuilder( - style=components.ButtonStyle.DANGER, label="no u", custom_id="ooga booga", is_disabled=True - ) + style=components.ButtonStyle.DANGER, custom_id="oogie" + ).set_custom_id("eeeeee") - assert button.custom_id == "ooga booga" + assert button.custom_id == "eeeeee" class TestSelectOptionBuilder: @@ -1413,10 +1427,14 @@ def option(self): return special_endpoints.SelectOptionBuilder(label="ok", value="ok2") def test_label_property(self, option): - assert option.label == "ok" + option.set_label("new_label") + + assert option.label == "new_label" def test_value_property(self, option): - assert option.value == "ok2" + option.set_value("aaaaaaaaaaaa") + + assert option.value == "aaaaaaaaaaaa" def test_emoji_property(self, option): option._emoji = 123321 @@ -1499,7 +1517,9 @@ def test_type_property(self): assert menu.type == 123 def test_custom_id_property(self, menu): - assert menu.custom_id == "o2o2o2" + menu.set_custom_id("ooooo") + + assert menu.custom_id == "ooooo" def test_set_is_disabled(self, menu): assert menu.set_is_disabled(True) is menu