diff --git a/hikari/api/event_manager.py b/hikari/api/event_manager.py index 90a0c2c2b9..126fd43b63 100644 --- a/hikari/api/event_manager.py +++ b/hikari/api/event_manager.py @@ -97,7 +97,7 @@ def dispatch(self, event: EventT_inv) -> asyncio.Future[typing.Any]: from hikari.users import User from hikari.snowflakes import Snowflake - @attr.define() + @attr.frozen() class EveryoneMentionedEvent(Event): app: RESTAware = attr.field() diff --git a/hikari/applications.py b/hikari/applications.py index c5eedfd4c5..fb4bf5556c 100644 --- a/hikari/applications.py +++ b/hikari/applications.py @@ -344,10 +344,6 @@ def flags(self) -> users.UserFlag: def id(self) -> snowflakes.Snowflake: return self.user.id - @id.setter - def id(self, value: snowflakes.Snowflake) -> typing.NoReturn: - raise TypeError("Cannot mutate the ID of a member") - @property def is_bot(self) -> bool: return self.user.is_bot diff --git a/hikari/channels.py b/hikari/channels.py index 6cfc6389ee..208016b676 100644 --- a/hikari/channels.py +++ b/hikari/channels.py @@ -715,12 +715,8 @@ def shard_id(self) -> typing.Optional[int]: This may be `builtins.None` if the shard count is not known. """ - try: - shard_count = getattr(self.app, "shard_count") - assert isinstance(shard_count, int), f"shard_count attr was expected to be int, but got {shard_count}" - return snowflakes.calculate_shard_id(shard_count, self.guild_id) - except (TypeError, AttributeError, NameError): - pass + if isinstance(self.app, traits.ShardAware): + return snowflakes.calculate_shard_id(self.app, self.guild_id) return None diff --git a/hikari/events/shard_events.py b/hikari/events/shard_events.py index d133fe9afc..0398a97939 100644 --- a/hikari/events/shard_events.py +++ b/hikari/events/shard_events.py @@ -70,8 +70,7 @@ def shard(self) -> gateway_shard.GatewayShard: """ -@attr_extensions.with_copy -@attr.define(kw_only=True, weakref_slot=False) +@attr.frozen(kw_only=True, weakref_slot=False) class ShardPayload(ShardEvent): """Event fired for most shard events with their raw payload. @@ -80,10 +79,10 @@ class ShardPayload(ShardEvent): Discord and not artificial events like the `ShardStateEvent` events. """ - app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True}) + app: traits.RESTAware = attr.field() # <>. - shard: gateway_shard.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True}) + shard: gateway_shard.GatewayShard = attr.field() # <>. name: str = attr.field() diff --git a/hikari/guilds.py b/hikari/guilds.py index 4b056661f6..d3cf7e04d0 100644 --- a/hikari/guilds.py +++ b/hikari/guilds.py @@ -360,10 +360,6 @@ def flags(self) -> users.UserFlag: def id(self) -> snowflakes.Snowflake: return self.user.id - @id.setter - def id(self, value: snowflakes.Snowflake) -> None: - raise TypeError("Cannot mutate the ID of a member") - @property def is_bot(self) -> bool: return self.user.is_bot diff --git a/hikari/impl/entity_factory.py b/hikari/impl/entity_factory.py index e158a15f71..fe558363de 100644 --- a/hikari/impl/entity_factory.py +++ b/hikari/impl/entity_factory.py @@ -277,7 +277,7 @@ def deserialize_application(self, payload: data_binding.JSONObject) -> applicati for member_payload in team_payload["members"]: team_member = application_models.TeamMember( membership_state=application_models.TeamMembershipState(member_payload["membership_state"]), - permissions=member_payload["permissions"], + permissions=tuple(member_payload["permissions"]), team_id=snowflakes.Snowflake(member_payload["team_id"]), user=self.deserialize_user(member_payload["user"]), ) @@ -1274,7 +1274,7 @@ def deserialize_guild_preview(self, payload: data_binding.JSONObject) -> guild_m id=guild_id, name=payload["name"], icon_hash=payload["icon"], - features=[guild_models.GuildFeature(feature) for feature in payload["features"]], + features=tuple(guild_models.GuildFeature(feature) for feature in payload["features"]), splash_hash=payload["splash"], discovery_splash_hash=payload["discovery_splash"], emojis=emojis, @@ -1509,7 +1509,7 @@ def _set_invite_attributes(self, payload: data_binding.JSONObject) -> _InviteFie app=self._app, id=snowflakes.Snowflake(guild_payload["id"]), name=guild_payload["name"], - features=[guild_models.GuildFeature(feature) for feature in guild_payload["features"]], + features=tuple(guild_models.GuildFeature(feature) for feature in guild_payload["features"]), icon_hash=guild_payload["icon"], splash_hash=guild_payload["splash"], banner_hash=guild_payload["banner"], diff --git a/hikari/impl/event_factory.py b/hikari/impl/event_factory.py index a0cdd76a2e..64115aed40 100644 --- a/hikari/impl/event_factory.py +++ b/hikari/impl/event_factory.py @@ -275,10 +275,10 @@ def deserialize_guild_emojis_update_event( old_emojis: typing.Optional[typing.Sequence[emojis_models.KnownCustomEmoji]], ) -> guild_events.EmojisUpdateEvent: guild_id = snowflakes.Snowflake(payload["guild_id"]) - emojis = [ + emojis = tuple( self._app.entity_factory.deserialize_known_custom_emoji(emoji, guild_id=guild_id) for emoji in payload["emojis"] - ] + ) return guild_events.EmojisUpdateEvent( app=self._app, shard=shard, guild_id=guild_id, emojis=emojis, old_emojis=old_emojis ) @@ -670,7 +670,7 @@ def deserialize_guild_member_chunk_event( for m in payload["members"] } # Note, these IDs may be returned as ints or strings based on whether they're over a certain value. - not_found = [snowflakes.Snowflake(sn) for sn in payload["not_found"]] if "not_found" in payload else [] + not_found = tuple(snowflakes.Snowflake(sn) for sn in payload["not_found"]) if "not_found" in payload else () if presence_payloads := payload.get("presences"): presences = { diff --git a/hikari/internal/cache.py b/hikari/internal/cache.py index d6319bb48e..36c6ba6a3f 100644 --- a/hikari/internal/cache.py +++ b/hikari/internal/cache.py @@ -620,7 +620,7 @@ def build_from_entity( typing.Mapping[snowflakes.Snowflake, "channels_.PartialChannel"] ] = undefined.UNDEFINED if mentions.channels is not undefined.UNDEFINED: - channels = {channel_id: channel for channel_id, channel in mentions.channels.items()} + channels = dict(mentions.channels.items()) return cls( users=users, diff --git a/hikari/messages.py b/hikari/messages.py index fbf877d092..f7ab4908a0 100644 --- a/hikari/messages.py +++ b/hikari/messages.py @@ -314,14 +314,14 @@ def channels_ids(self) -> undefined.UndefinedOr[typing.Sequence[snowflakes.Snowf if self.channels is undefined.UNDEFINED: return undefined.UNDEFINED - return list(self.channels.keys()) + return tuple(self.channels.keys()) @property def user_ids(self) -> undefined.UndefinedOr[typing.Sequence[snowflakes.Snowflake]]: if self.users is undefined.UNDEFINED: return undefined.UNDEFINED - return list(self.users.keys()) + return tuple(self.users.keys()) @property def members(self) -> undefined.UndefinedOr[typing.Mapping[snowflakes.Snowflake, guilds.Member]]: diff --git a/hikari/snowflakes.py b/hikari/snowflakes.py index 19d90c1bab..e26bc928db 100644 --- a/hikari/snowflakes.py +++ b/hikari/snowflakes.py @@ -124,11 +124,6 @@ def id(self) -> Snowflake: The snowflake ID of this object. """ - # TODO: make immutable interface, as this is a major risk to consistent hash codes. - @id.setter - def id(self, value: Snowflake) -> None: - """Set the ID on this entity.""" - @property def created_at(self) -> datetime.datetime: """When the object was created.""" diff --git a/hikari/users.py b/hikari/users.py index 9996912de0..86c63a967f 100644 --- a/hikari/users.py +++ b/hikari/users.py @@ -605,7 +605,7 @@ def __str__(self) -> str: return f"{self.username}#{self.discriminator}" -@attr.define(hash=True, kw_only=True, weakref_slot=False) +@attr.frozen(hash=True, kw_only=True, weakref_slot=False) class UserImpl(PartialUserImpl, User): """Concrete implementation of user information.""" @@ -632,7 +632,7 @@ class UserImpl(PartialUserImpl, User): """The public flags for this user.""" -@attr.define(hash=True, kw_only=True, weakref_slot=False) +@attr.frozen(hash=True, kw_only=True, weakref_slot=False) class OwnUser(UserImpl): """Represents a user with extended OAuth2 information.""" diff --git a/tests/hikari/events/test_message_events.py b/tests/hikari/events/test_message_events.py index 0a0a8f6cf8..ae6b7802b5 100644 --- a/tests/hikari/events/test_message_events.py +++ b/tests/hikari/events/test_message_events.py @@ -182,8 +182,8 @@ def event(self): def test_guild_id_property(self, event): assert event.guild_id == snowflakes.Snowflake(342123123) - def test_channel_property_when_no_cache_trait(self, event): - event.app = object() + def test_channel_property_when_no_cache_trait(self): + event = message_events.GuildMessageCreateEvent(app=None, message=None, shard=None) assert event.channel is None @@ -195,8 +195,8 @@ def test_channel_property(self, event, guild_channel_impl): assert result is event.app.cache.get_guild_channel.return_value event.app.cache.get_guild_channel.assert_called_once_with(9121234) - def test_guild_property_when_no_cache_trait(self, event): - event.app = object() + def test_guild_property_when_no_cache_trait(self): + event = message_events.GuildMessageCreateEvent(app=None, message=None, shard=None) assert event.guild is None @@ -259,8 +259,8 @@ def test_author_property_when_member_none_and_uncached_but_author_defined(self, def test_guild_id_property(self, event): assert event.guild_id == snowflakes.Snowflake(54123123123) - def test_channel_property_when_no_cache_trait(self, event): - event.app = object() + def test_channel_property_when_no_cache_trait(self): + event = message_events.GuildMessageUpdateEvent(app=None, message=None, old_message=None, shard=None) assert event.channel is None @@ -272,8 +272,8 @@ def test_channel_property(self, event, guild_channel_impl): assert result is event.app.cache.get_guild_channel.return_value event.app.cache.get_guild_channel.assert_called_once_with(800001066) - def test_guild_property_when_no_cache_trait(self, event): - event.app = object() + def test_guild_property_when_no_cache_trait(self): + event = message_events.GuildMessageUpdateEvent(app=None, message=None, old_message=None, shard=None) assert event.guild is None @@ -326,8 +326,10 @@ def event(self): is_bulk=True, ) - def test_channel_property_when_no_cache_trait(self, event): - event.app = object() + def test_channel_property_when_no_cache_trait(self): + event = message_events.GuildMessageDeleteEvent( + guild_id=None, channel_id=None, app=None, shard=None, message_ids=None, is_bulk=None + ) assert event.channel is None @@ -339,8 +341,10 @@ def test_channel_property(self, event, guild_channel_impl): assert result is event.app.cache.get_guild_channel.return_value event.app.cache.get_guild_channel.assert_called_once_with(54213123123) - def test_guild_property_when_no_cache_trait(self, event): - event.app = object() + def test_guild_property_when_no_cache_trait(self): + event = message_events.GuildMessageDeleteEvent( + guild_id=None, channel_id=None, app=None, shard=None, message_ids=None, is_bulk=None + ) assert event.guild is None diff --git a/tests/hikari/events/test_shard_events.py b/tests/hikari/events/test_shard_events.py index 769c66a5be..c5d49e4569 100644 --- a/tests/hikari/events/test_shard_events.py +++ b/tests/hikari/events/test_shard_events.py @@ -38,6 +38,7 @@ def event(self): snowflakes.Snowflake(55): mock.Mock(), snowflakes.Snowflake(99): mock.Mock(), snowflakes.Snowflake(455): mock.Mock(), + snowflakes.Snowflake(55555): mock.Mock(), }, chunk_count=1, chunk_index=1, @@ -47,11 +48,7 @@ def event(self): ) def test___getitem___with_slice(self, event): - mock_member_0 = object() - mock_member_1 = object() - event.members = {1: object(), 55: object(), 99: mock_member_0, 455: object(), 5444: mock_member_1} - - assert event[2:5:2] == (mock_member_0, mock_member_1) + assert event[2:5:2] == (event.members[99], event.members[55555]) def test___getitem___with_valid_index(self, event): mock_member = object() @@ -66,17 +63,13 @@ def test___getitem___with_invalid_index(self, event): assert event[123] def test___iter___(self, event): - member_0 = mock.Mock() - member_1 = mock.Mock() - member_2 = mock.Mock() - - event.members = { - snowflakes.Snowflake(1): member_0, - snowflakes.Snowflake(2): member_1, - snowflakes.Snowflake(3): member_2, - } - - assert list(event) == [member_0, member_1, member_2] + assert list(event) == [ + event.members[1], + event.members[55], + event.members[99], + event.members[455], + event.members[55555], + ] def test___len___(self, event): - assert len(event) == 4 + assert len(event) == 5 diff --git a/tests/hikari/events/test_typing_events.py b/tests/hikari/events/test_typing_events.py index 6f557d061e..55cb6b2bee 100644 --- a/tests/hikari/events/test_typing_events.py +++ b/tests/hikari/events/test_typing_events.py @@ -65,8 +65,10 @@ def event(self): user=mock.Mock(id=456), ) - def test_channel_when_no_cache(self, event): - event.app = object() + def test_channel_when_no_cache(self): + event = typing_events.GuildTypingEvent( + channel_id=None, timestamp=None, shard=None, app=None, guild_id=None, user=None + ) assert event.channel is None @@ -78,8 +80,10 @@ def test_channel(self, event, guild_channel_impl): assert result is event.app.cache.get_guild_channel.return_value event.app.cache.get_guild_channel.assert_called_once_with(123) - async def test_guild_when_no_cache(self, event): - event.app = object() + async def test_guild_when_no_cache(self): + event = typing_events.GuildTypingEvent( + channel_id=None, timestamp=None, shard=None, app=None, guild_id=None, user=None + ) assert event.guild is None @@ -139,8 +143,8 @@ def event(self): user_id=456, ) - async def test_user_when_no_cache(self, event): - event.app = object() + async def test_user_when_no_cache(self): + event = typing_events.DMTypingEvent(app=None, shard=None, user_id=None, timestamp=None, channel_id=None) assert event.user is None diff --git a/tests/hikari/events/test_voice_events.py b/tests/hikari/events/test_voice_events.py index f8eb3e915f..5afd3f7b5b 100644 --- a/tests/hikari/events/test_voice_events.py +++ b/tests/hikari/events/test_voice_events.py @@ -53,6 +53,6 @@ def event(self): def test_endpoint_property(self, event): assert event.endpoint == "wss://voice.discord.com:123" - def test_endpoint_property_when_raw_endpoint_is_None(self, event): - event.raw_endpoint = None + def test_endpoint_property_when_raw_endpoint_is_None(self): + event = voice_events.VoiceServerUpdateEvent(app=None, shard=None, guild_id=None, token=None, raw_endpoint=None) assert event.endpoint is None diff --git a/tests/hikari/impl/test_cache.py b/tests/hikari/impl/test_cache.py index 716f511719..df4c0b8e14 100644 --- a/tests/hikari/impl/test_cache.py +++ b/tests/hikari/impl/test_cache.py @@ -597,7 +597,7 @@ def test_delete_guild_for_unknown_record(self, cache_impl): assert cache_impl._guild_entries == {snowflakes.Snowflake(354123): cache_utilities.GuildRecord()} def test_get_guild_first_tries_get_available_guilds(self, cache_impl): - mock_guild = mock.MagicMock(guilds.GatewayGuild) + mock_guild = object() cache_impl._guild_entries = collections.FreezableDict( { snowflakes.Snowflake(54234123): cache_utilities.GuildRecord(), @@ -607,11 +607,10 @@ def test_get_guild_first_tries_get_available_guilds(self, cache_impl): cached_guild = cache_impl.get_guild(StubModel(543123)) - assert cached_guild == mock_guild - assert cache_impl is not mock_guild + assert cached_guild is mock_guild def test_get_guild_then_tries_get_unavailable_guilds(self, cache_impl): - mock_guild = mock.MagicMock(guilds.GatewayGuild) + mock_guild = object() cache_impl._guild_entries = collections.FreezableDict( { snowflakes.Snowflake(543123): cache_utilities.GuildRecord(is_available=True), @@ -621,11 +620,10 @@ def test_get_guild_then_tries_get_unavailable_guilds(self, cache_impl): cached_guild = cache_impl.get_guild(StubModel(54234123)) - assert cached_guild == mock_guild - assert cache_impl is not mock_guild + assert cached_guild is mock_guild def test_get_available_guild_for_known_guild_when_available(self, cache_impl): - mock_guild = mock.MagicMock(guilds.GatewayGuild) + mock_guild = object() cache_impl._guild_entries = collections.FreezableDict( { snowflakes.Snowflake(54234123): cache_utilities.GuildRecord(), @@ -635,8 +633,7 @@ def test_get_available_guild_for_known_guild_when_available(self, cache_impl): cached_guild = cache_impl.get_available_guild(StubModel(543123)) - assert cached_guild == mock_guild - assert cache_impl is not mock_guild + assert cached_guild is mock_guild def test_get_available_guild_for_known_guild_when_unavailable(self, cache_impl): mock_guild = mock.Mock(guilds.GatewayGuild) @@ -673,7 +670,7 @@ def test_get_available_guild_for_unknown_guild_record(self, cache_impl): assert result is None def test_get_unavailable_guild_for_known_guild_when_unavailable(self, cache_impl): - mock_guild = mock.MagicMock(guilds.GatewayGuild) + mock_guild = object() cache_impl._guild_entries = collections.FreezableDict( { snowflakes.Snowflake(54234123): cache_utilities.GuildRecord(), @@ -683,8 +680,7 @@ def test_get_unavailable_guild_for_known_guild_when_unavailable(self, cache_impl cached_guild = cache_impl.get_unavailable_guild(StubModel(452131)) - assert cached_guild == mock_guild - assert cache_impl is not mock_guild + assert cached_guild is mock_guild def test_get_unavailable_guild_for_known_guild_when_available(self, cache_impl): mock_guild = mock.Mock(guilds.GatewayGuild) @@ -806,13 +802,12 @@ def test_get_unavailable_guilds_view_when_no_guilds_cached(self, cache_impl): assert result == {} def test_set_guild(self, cache_impl): - mock_guild = mock.MagicMock(guilds.GatewayGuild, id=snowflakes.Snowflake(5123123)) + mock_guild = mock.Mock(guilds.GatewayGuild, id=snowflakes.Snowflake(5123123)) cache_impl.set_guild(mock_guild) assert 5123123 in cache_impl._guild_entries - assert cache_impl._guild_entries[snowflakes.Snowflake(5123123)].guild == mock_guild - assert cache_impl._guild_entries[snowflakes.Snowflake(5123123)].guild is not mock_guild + assert cache_impl._guild_entries[snowflakes.Snowflake(5123123)].guild is mock_guild assert cache_impl._guild_entries[snowflakes.Snowflake(5123123)].is_available is True def test_set_guild_availability_for_cached_guild(self, cache_impl): @@ -1398,7 +1393,7 @@ def test_delete_me_for_unknown_me(self, cache_impl): assert cache_impl._me is None def test_get_me_for_known_me(self, cache_impl): - mock_own_user = object() + mock_own_user = object() cache_impl._me = mock_own_user cached_me = cache_impl.get_me() @@ -1409,7 +1404,7 @@ def test_get_me_for_unknown_me(self, cache_impl): assert cache_impl.get_me() is None def test_set_me(self, cache_impl): - mock_own_user = object() + mock_own_user = object() cache_impl.set_me(mock_own_user) @@ -1806,7 +1801,7 @@ def test_set_member(self, cache_impl): assert member_entry.object.user is mock_user_ref assert member_entry.object.guild_id == 67345234 assert member_entry.object.nickname == "A NICK LOL" - assert member_entry.object.role_ids is member_model.role_ids + assert member_entry.object.role_ids == (65345234, 123123) assert member_entry.object.joined_at == datetime.datetime( 2020, 7, 15, 23, 30, 59, 501602, tzinfo=datetime.timezone.utc ) @@ -2320,7 +2315,7 @@ def test_update_voice_state(self, cache_impl): ) def test__build_message(self, cache_impl): - mock_author = mock.MagicMock(users.User) + mock_author = object() mock_member = object() member_data = mock.Mock(build_entity=mock.Mock(return_value=mock_member)) mock_channel = mock.MagicMock() @@ -2331,14 +2326,14 @@ def test__build_message(self, cache_impl): channels={snowflakes.Snowflake(4444): mock_channel}, everyone=True, ) - mock_attachment = mock.MagicMock(messages.Attachment) - mock_embed_field = mock.MagicMock(embeds.EmbedField) - mock_embed = mock.MagicMock(embeds.Embed, fields=(mock_embed_field,)) - mock_sticker = mock.MagicMock(messages.Sticker) - mock_reaction = mock.MagicMock(messages.Reaction) - mock_activity = mock.MagicMock(messages.MessageActivity) - mock_applcation = mock.MagicMock(messages.MessageApplication) - mock_reference = mock.MagicMock(messages.MessageReference) + mock_attachment = object() + mock_embed_field = object() + mock_embed = mock.Mock(embeds.Embed, fields=(mock_embed_field,)) + mock_sticker = object() + mock_reaction = object() + mock_activity = object() + mock_applcation = object() + mock_reference = object() mock_referenced_message = object() mock_referenced_message_data = mock.Mock( cache_utilities.MessageData, build_entity=mock.Mock(return_value=mock_referenced_message) @@ -2375,8 +2370,7 @@ def test__build_message(self, cache_impl): assert result.id == 32123123 assert result.channel_id == 3123123123 assert result.guild_id == 5555555 - assert result.author == mock_author - assert result.author is not mock_author + assert result.author is mock_author assert result.member is mock_member assert result.content == "OKOKOK" assert result.timestamp == datetime.datetime(2020, 7, 30, 7, 10, 9, 550233, tzinfo=datetime.timezone.utc) @@ -2413,12 +2407,9 @@ def test__build_message(self, cache_impl): assert result.is_pinned is False assert result.webhook_id == 3123123 assert result.type is messages.MessageType.REPLY - assert result.activity == mock_activity - assert result.activity is not mock_activity - assert result.application == mock_applcation - assert result.application is not mock_applcation - assert result.message_reference == mock_reference - assert result.message_reference is not mock_reference + assert result.activity is mock_activity + assert result.application is mock_applcation + assert result.message_reference is mock_reference assert result.flags == messages.MessageFlag.CROSSPOSTED assert result.stickers == (mock_sticker,) assert result.nonce == "aNonce" diff --git a/tests/hikari/impl/test_entity_factory.py b/tests/hikari/impl/test_entity_factory.py index df2bcc494a..1c64e3c072 100644 --- a/tests/hikari/impl/test_entity_factory.py +++ b/tests/hikari/impl/test_entity_factory.py @@ -125,7 +125,9 @@ def test_deserialize_own_connection(self, entity_factory_impl, own_connection_pa assert own_connection.name == "FS" assert own_connection.type == "twitter" assert own_connection.is_revoked is False - assert own_connection.integrations == [entity_factory_impl.deserialize_partial_integration(partial_integration)] + assert own_connection.integrations == ( + entity_factory_impl.deserialize_partial_integration(partial_integration), + ) assert own_connection.is_verified is True assert own_connection.is_friend_sync_enabled is False assert own_connection.is_activity_visible is True @@ -139,7 +141,7 @@ def test_deserialize_own_connection_when_integrations_is_None(self, entity_facto assert own_connection.name == "FS" assert own_connection.type == "twitter" assert own_connection.is_revoked is False - assert own_connection.integrations == [] + assert own_connection.integrations == () assert own_connection.is_verified is True assert own_connection.is_friend_sync_enabled is False assert own_connection.is_activity_visible is True @@ -162,7 +164,7 @@ def test_deserialize_own_guild(self, entity_factory_impl, mock_app, own_guild_pa assert own_guild.id == 152559372126519269 assert own_guild.name == "Isopropyl" assert own_guild.icon_hash == "d4a983885dsaa7691ce8bcaaf945a" - assert own_guild.features == [guild_models.GuildFeature.DISCOVERABLE, "FORCE_RELAY"] + assert own_guild.features == (guild_models.GuildFeature.DISCOVERABLE, "FORCE_RELAY") assert own_guild.is_owner is False assert own_guild.my_permissions == permission_models.Permissions(2147483647) @@ -224,7 +226,7 @@ def test_deserialize_application( assert application.is_bot_public is True assert application.is_bot_code_grant_required is False assert application.owner == entity_factory_impl.deserialize_user(owner_payload) - assert application.rpc_origins == ["127.0.0.0"] + assert application.rpc_origins == ("127.0.0.0",) assert application.summary == "not a blank string" assert ( application.public_key @@ -243,7 +245,7 @@ def test_deserialize_application( assert len(application.team.members) == 1 member = application.team.members[115590097100865541] assert member.membership_state == application_models.TeamMembershipState.INVITED - assert member.permissions == ["*"] + assert member.permissions == ("*",) assert member.team_id == 209333111222 assert member.user == entity_factory_impl.deserialize_user(user_payload) assert isinstance(member, application_models.TeamMember) @@ -336,7 +338,7 @@ def test_deserialize_authorization_information( assert authorization_information.expires_at == datetime.datetime( 2021, 2, 1, 18, 3, 20, 888000, tzinfo=datetime.timezone.utc ) - assert authorization_information.scopes == ["identify", "guilds", "applications.commands.update"] + assert authorization_information.scopes == ("identify", "guilds", "applications.commands.update") assert authorization_information.user == entity_factory_impl.deserialize_user(user_payload) def test_deserialize_authorization_information_with_unset_fields( @@ -374,10 +376,10 @@ def test_deserialize_partial_token(self, entity_factory_impl, client_credentials assert partial_token.access_token == "6qrZcUqja7812RVdnEKjpzOL4CvHBFG" assert partial_token.token_type is application_models.TokenType.BEARER assert partial_token.expires_in == datetime.timedelta(weeks=1) - assert partial_token.scopes == [ + assert partial_token.scopes == ( application_models.OAuth2Scope.IDENTIFY, application_models.OAuth2Scope.CONNECTIONS, - ] + ) assert isinstance(partial_token, application_models.PartialOAuth2Token) @pytest.fixture() @@ -400,10 +402,10 @@ def test_deserialize_authorization_token( assert access_token.token_type is application_models.TokenType.BEARER assert access_token.guild == entity_factory_impl.deserialize_rest_guild(deserialize_rest_guild_payload) assert access_token.access_token == "zMndOe7jFLXGawdlxMOdNvXjjOce5X" - assert access_token.scopes == [ + assert access_token.scopes == ( application_models.OAuth2Scope.BOT, application_models.OAuth2Scope.WEBHOOK_INCOMING, - ] + ) assert access_token.expires_in == datetime.timedelta(weeks=4) assert access_token.refresh_token == "mgp8qnvBwJcmadwgCYKyYD5CAzGAX4" assert access_token.webhook == entity_factory_impl.deserialize_webhook(webhook_payload) @@ -433,7 +435,7 @@ def test_deserialize_implicit_token(self, entity_factory_impl, implicit_token_pa assert implicit_token.access_token == "RTfP0OK99U3kbRtHOoKLmJbOn45PjL" assert implicit_token.token_type is application_models.TokenType.BASIC assert implicit_token.expires_in == datetime.timedelta(weeks=2) - assert implicit_token.scopes == [application_models.OAuth2Scope.IDENTIFY] + assert implicit_token.scopes == (application_models.OAuth2Scope.IDENTIFY,) assert implicit_token.state == "15773059ghq9183habn" assert isinstance(implicit_token, application_models.OAuth2ImplicitToken) @@ -664,7 +666,7 @@ def test_deserialize_audit_log_with_unset_or_unknown_fields(self, entity_factory assert len(audit_log.entries) == 1 entry = audit_log.entries[694026906592477214] - assert entry.changes == [] + assert entry.changes == () assert entry.target_id is None assert entry.user_id is None assert entry.action_type == 69 @@ -682,8 +684,12 @@ def test_deserialize_audit_log_with_unhandled_change_key(self, entity_factory_im assert len(entry.changes) == 1 change = entry.changes[0] assert change.key == audit_log_models.AuditLogChangeKey.NAME - assert change.new_value == [{"id": "568651298858074123", "name": "Casual"}] - assert change.old_value == [{"id": "123123123312312", "name": "aRole"}] + assert change.new_value == [ + {"id": "568651298858074123", "name": "Casual"}, + ] + assert change.old_value == [ + {"id": "123123123312312", "name": "aRole"}, + ] def test_deserialize_audit_log_with_change_key_unknown(self, entity_factory_impl, audit_log_payload): # Unset fields @@ -1671,7 +1677,7 @@ def test_deserialize_known_custom_emoji( assert emoji.guild_id == 1235123 assert emoji.name == "testing" assert emoji.is_animated is False - assert emoji.role_ids == [123, 456] + assert emoji.role_ids == (123, 456) assert emoji.user == entity_factory_impl.deserialize_user(user_payload) assert emoji.is_colons_required is True assert emoji.is_managed is False @@ -1826,7 +1832,7 @@ def test_deserialize_member(self, entity_factory_impl, mock_app, member_payload, assert member.guild_id == 76543325 assert member.user == entity_factory_impl.deserialize_user(user_payload) assert member.nickname == "foobarbaz" - assert member.role_ids == [11111, 22222, 33333, 44444, 76543325] + assert member.role_ids == (11111, 22222, 33333, 44444, 76543325) assert member.joined_at == datetime.datetime(2015, 4, 26, 6, 26, 56, 936000, tzinfo=datetime.timezone.utc) assert member.premium_since == datetime.datetime(2019, 5, 17, 6, 26, 56, 936000, tzinfo=datetime.timezone.utc) assert member.is_deaf is False @@ -1846,7 +1852,7 @@ def test_deserialize_member_when_guild_id_already_in_role_array( assert member.guild_id == 76543325 assert member.user == entity_factory_impl.deserialize_user(user_payload) assert member.nickname == "foobarbaz" - assert member.role_ids == [11111, 22222, 76543325, 33333, 44444] + assert member.role_ids == (11111, 22222, 76543325, 33333, 44444) assert member.joined_at == datetime.datetime(2015, 4, 26, 6, 26, 56, 936000, tzinfo=datetime.timezone.utc) assert member.premium_since == datetime.datetime(2019, 5, 17, 6, 26, 56, 936000, tzinfo=datetime.timezone.utc) assert member.is_deaf is False @@ -2123,7 +2129,7 @@ def test_deserialize_guild_preview( assert guild_preview.id == 152559372126519269 assert guild_preview.name == "Isopropyl" assert guild_preview.icon_hash == "d4a983885dsaa7691ce8bcaaf945a" - assert guild_preview.features == [guild_models.GuildFeature.DISCOVERABLE, "FORCE_RELAY"] + assert guild_preview.features == (guild_models.GuildFeature.DISCOVERABLE, "FORCE_RELAY") assert guild_preview.splash_hash == "dsa345tfcdg54b" assert guild_preview.discovery_splash_hash == "lkodwaidi09239uid" assert guild_preview.emojis == { @@ -2214,12 +2220,12 @@ def test_deserialize_rest_guild( assert guild.id == 265828729970753537 assert guild.name == "L33t guild" assert guild.icon_hash == "1a2b3c4d" - assert guild.features == [ + assert guild.features == ( guild_models.GuildFeature.ANIMATED_ICON, guild_models.GuildFeature.MORE_EMOJI, guild_models.GuildFeature.NEWS, "SOME_UNDOCUMENTED_FEATURE", - ] + ) assert guild.splash_hash == "0ff0ff0ff" assert guild.discovery_splash_hash == "famfamFAMFAMfam" assert guild.owner_id == 6969696 @@ -2433,12 +2439,12 @@ def test_deserialize_gateway_guild( assert guild.id == 265828729970753537 assert guild.name == "L33t guild" assert guild.icon_hash == "1a2b3c4d" - assert guild.features == [ + assert guild.features == ( guild_models.GuildFeature.ANIMATED_ICON, guild_models.GuildFeature.MORE_EMOJI, guild_models.GuildFeature.NEWS, "SOME_UNDOCUMENTED_FEATURE", - ] + ) assert guild.splash_hash == "0ff0ff0ff" assert guild.discovery_splash_hash == "famfamFAMFAMfam" assert guild.owner_id == 6969696 @@ -2688,7 +2694,7 @@ def test_deserialize_invite( assert invite.guild.id == 56188492224814744 assert invite.guild.name == "Testin' Your Scene" assert invite.guild.icon_hash == "bb71f469c158984e265093a81b3397fb" - assert invite.guild.features == ["FORCE_RELAY"] + assert invite.guild.features == ("FORCE_RELAY",) assert invite.guild.splash_hash == "aSplashForSure" assert invite.guild.banner_hash == "aBannerForSure" assert invite.guild.description == "Describe me cute kitty." @@ -2804,7 +2810,7 @@ def test_deserialize_invite_with_metadata( assert invite_with_metadata.guild.id == 56188492224814744 assert invite_with_metadata.guild.name == "Testin' Your Scene" assert invite_with_metadata.guild.icon_hash == "bb71f469c158984e265093a81b3397fb" - assert invite_with_metadata.guild.features == ["FORCE_RELAY"] + assert invite_with_metadata.guild.features == ("FORCE_RELAY",) assert invite_with_metadata.guild.splash_hash == "aSplashForSure" assert invite_with_metadata.guild.banner_hash == "aBannerForSure" assert invite_with_metadata.guild.description == "Describe me cute kitty." @@ -2979,9 +2985,9 @@ def test_deserialize_partial_message( ) assert partial_message.is_tts is True assert partial_message.mentions.everyone is True - assert partial_message.mentions.user_ids == [5678] - assert partial_message.mentions.role_ids == [987] - assert partial_message.mentions.channels_ids == [456] + assert partial_message.mentions.user_ids == (5678,) + assert partial_message.mentions.role_ids == (987,) + assert partial_message.mentions.channels_ids == (456,) # Attachment assert len(partial_message.attachments) == 1 attachment = partial_message.attachments[0] @@ -2996,7 +3002,7 @@ def test_deserialize_partial_message( assert isinstance(attachment, message_models.Attachment) expected_embed = entity_factory_impl.deserialize_embed(embed_payload) - assert partial_message.embeds == [expected_embed] + assert partial_message.embeds == (expected_embed,) # Reaction reaction = partial_message.reactions[0] assert reaction.count == 100 @@ -3233,18 +3239,18 @@ def test_deserialize_message_with_null_and_unset_fields( assert message.member is None assert message.edited_timestamp is None assert message.mentions.everyone is True - assert message.mentions.user_ids == [] - assert message.mentions.role_ids == [] - assert message.mentions.channels_ids == [] - assert message.attachments == [] - assert message.embeds == [] - assert message.reactions == [] + assert message.mentions.user_ids == () + assert message.mentions.role_ids == () + assert message.mentions.channels_ids == () + assert message.attachments == () + assert message.embeds == () + assert message.reactions == () assert message.webhook_id is None assert message.activity is None assert message.application is None assert message.message_reference is None assert message.referenced_message is undefined.UNDEFINED - assert message.stickers == [] + assert message.stickers == () assert message.nonce is None def test_deserialize_message_with_other_unset_fields(self, entity_factory_impl, message_payload): @@ -3355,7 +3361,7 @@ def test_deserialize_member_presence( assert presence.client_status.web == presence_models.Status.DO_NOT_DISTURB assert isinstance(presence.client_status, presence_models.ClientStatus) - assert activity.buttons == ["owo", "no"] + assert activity.buttons == ("owo", "no") assert isinstance(presence, presence_models.MemberPresence) def test_deserialize_member_presence_with_unset_fields( @@ -3407,7 +3413,7 @@ def test_deserialize_member_presence_with_unset_activity_fields(self, entity_fac assert activity.secrets is None assert activity.is_instance is None assert activity.flags is None - assert activity.buttons == [] + assert activity.buttons == () def test_deserialize_member_presence_with_null_activity_fields(self, entity_factory_impl, user_payload): presence = entity_factory_impl.deserialize_member_presence( diff --git a/tests/hikari/impl/test_event_factory.py b/tests/hikari/impl/test_event_factory.py index 9eee34915c..e493d6e051 100644 --- a/tests/hikari/impl/test_event_factory.py +++ b/tests/hikari/impl/test_event_factory.py @@ -331,7 +331,7 @@ def test_deserialize_guild_emojis_update_event(self, event_factory, mock_app, mo assert isinstance(event, guild_events.EmojisUpdateEvent) assert event.app is mock_app assert event.shard is mock_shard - assert event.emojis == [mock_app.entity_factory.deserialize_known_custom_emoji.return_value] + assert event.emojis == (mock_app.entity_factory.deserialize_known_custom_emoji.return_value,) assert event.guild_id == 123431 assert event.old_emojis is mock_old_emojis @@ -897,7 +897,7 @@ def test_deserialize_guild_member_chunk_event_with_optional_fields(self, event_f assert event.members == {4222222: mock_app.entity_factory.deserialize_member.return_value} assert event.chunk_count == 54 assert event.chunk_index == 3 - assert event.not_found == [34212312312, 323123123] + assert event.not_found == (34212312312, 323123123) assert event.presences == {43123123: mock_app.entity_factory.deserialize_member_presence.return_value} assert event.nonce == "OKOKOKOK" @@ -912,7 +912,7 @@ def test_deserialize_guild_member_chunk_event_without_optional_fields(self, even event = event_factory.deserialize_guild_member_chunk_event(mock_shard, mock_payload) - assert event.not_found == [] + assert event.not_found == () assert event.presences == {} assert event.nonce is None diff --git a/tests/hikari/internal/test_routes.py b/tests/hikari/internal/test_routes.py index 9783105a50..71e24179b6 100644 --- a/tests/hikari/internal/test_routes.py +++ b/tests/hikari/internal/test_routes.py @@ -300,10 +300,9 @@ def test_compile_generates_expected_url(self, base_url, template, format, size_k @pytest.mark.parametrize("size", [64, 256, 2048]) def test_compile_to_file_calls_compile(self, format, size): with mock.patch.object(files, "URL", autospec=files.URL): - route = hikari_test_helpers.mock_class_namespace(routes.CDNRoute, slots_=False)( + route = hikari_test_helpers.mock_class_namespace(routes.CDNRoute, slots_=False, compile=mock.Mock())( "/hello/world", {"png", "jpg"}, sizable=True ) - route.compile = mock.Mock(spec_set=route.compile) route.compile_to_file("https://blep.com", file_format=format, size=size, boop="oyy lumo", nya="weeb") route.compile.assert_called_once_with( "https://blep.com", file_format=format, size=size, boop="oyy lumo", nya="weeb" @@ -313,10 +312,9 @@ def test_compile_to_file_passes_compile_result_to_URL_and_returns_constructed_ur resultant_url_str = "http://blep.com/hello/world/weeb/oyy%20lumo" resultant_url = files.URL("http://blep.com/hello/world/weeb/oyy%20lumo") with mock.patch.object(files, "URL", autospec=files.URL, return_value=resultant_url) as URL: - route = hikari_test_helpers.mock_class_namespace(routes.CDNRoute, slots_=False)( - "/hello/world/{nya}/{boop}", {"png", "jpg"}, sizable=True - ) - route.compile = mock.Mock(spec_set=route.compile, return_value=resultant_url_str) + route = hikari_test_helpers.mock_class_namespace( + routes.CDNRoute, slots_=False, compile=mock.Mock(return_value=resultant_url_str) + )("/hello/world/{nya}/{boop}", {"png", "jpg"}, sizable=True) result = route.compile_to_file("https://blep.com", file_format="png", size=64, boop="oyy lumo", nya="weeb") URL.assert_called_once_with(resultant_url_str) diff --git a/tests/hikari/test_applications.py b/tests/hikari/test_applications.py index 327409f302..17a15b30c8 100644 --- a/tests/hikari/test_applications.py +++ b/tests/hikari/test_applications.py @@ -57,10 +57,6 @@ def test_flags_property(self, model): def test_id_property(self, model): assert model.id is model.user.id - def test_id_setter(self, model): - with pytest.raises(TypeError, match="Cannot mutate the ID of a member"): - model.id = 42 - def test_is_bot_property(self, model): assert model.is_bot is model.user.is_bot @@ -99,15 +95,17 @@ def test_str_operator(self): team = applications.Team(id=696969, app=object(), name="test", icon_hash="", members=[], owner_id=0) assert str(team) == "Team test (696969)" - def test_icon_url_property(self, model): - model.make_icon_url = mock.Mock(return_value="url") + def test_icon_url_property(self): + model = hikari_test_helpers.mock_class_namespace( + applications.Team, init_=False, make_icon_url=mock.Mock(return_value="url") + )() assert model.icon_url == "url" model.make_icon_url.assert_called_once_with() - def test_make_icon_url_when_hash_is_None(self, model): - model.icon_hash = None + def test_make_icon_url_when_hash_is_None(self): + model = applications.Team(app=None, id=None, name=None, icon_hash=None, members=None, owner_id=None) with mock.patch.object( routes, "CDN_TEAM_ICON", new=mock.Mock(compile_to_file=mock.Mock(return_value="file")) @@ -139,15 +137,21 @@ def model(self): cover_image_hash="ahashcover", )() - def test_cover_image_url_property(self, model): - model.make_cover_image_url = mock.Mock(return_value="url") + def test_cover_image_url_property(self): + model = hikari_test_helpers.mock_class_namespace( + applications.Application, init_=False, make_cover_image_url=mock.Mock(return_value="url") + )() assert model.cover_image_url == "url" model.make_cover_image_url.assert_called_once_with() - def test_make_cover_image_url_when_hash_is_None(self, model): - model.cover_image_hash = None + def test_make_cover_image_url_when_hash_is_None(self): + model = hikari_test_helpers.mock_class_namespace( + applications.Application, + init_=False, + cover_image_hash=None, + )() with mock.patch.object( routes, "CDN_APPLICATION_COVER", new=mock.Mock(compile_to_file=mock.Mock(return_value="file")) diff --git a/tests/hikari/test_channels.py b/tests/hikari/test_channels.py index 2682a46f90..5c20172587 100644 --- a/tests/hikari/test_channels.py +++ b/tests/hikari/test_channels.py @@ -87,10 +87,11 @@ def test_channel_when_no_cache_trait(self): class TestPermissionOverwrite: def test_unset(self): overwrite = channels.PermissionOverwrite( - type=channels.PermissionOverwriteType.MEMBER, id=snowflakes.Snowflake(1234321) + type=channels.PermissionOverwriteType.MEMBER, + id=snowflakes.Snowflake(1234321), + allow=permissions.Permissions.CREATE_INSTANT_INVITE, + deny=permissions.Permissions.CHANGE_NICKNAME, ) - overwrite.allow = permissions.Permissions.CREATE_INSTANT_INVITE - overwrite.deny = permissions.Permissions.CHANGE_NICKNAME assert overwrite.unset == permissions.Permissions(-67108866) @@ -107,8 +108,10 @@ def model(self, mock_app): def test_str_operator(self, model): assert str(model) == "foo" - def test_str_operator_when_name_is_None(self, model): - model.name = None + def test_str_operator_when_name_is_None(self): + model = hikari_test_helpers.mock_class_namespace( + channels.PartialChannel, init_=False, rename_impl_=False, name=None, id=1234567 + )() assert str(model) == "Unnamed PartialChannel ID 1234567" @@ -137,7 +140,7 @@ def model(self, mock_app): return channels.GroupDMChannel( app=mock_app, id=snowflakes.Snowflake(136134), - name="super cool group dm", + name=None, type=channels.ChannelType.DM, last_message_id=snowflakes.Snowflake(3232), owner_id=snowflakes.Snowflake(1066), @@ -154,11 +157,13 @@ def model(self, mock_app): application_id=None, ) - def test_str_operator(self, model): + def test_str_operator(self): + model = hikari_test_helpers.mock_class_namespace( + channels.GroupDMChannel, init_=False, name="super cool group dm" + )() assert str(model) == "super cool group dm" def test_str_operator_when_name_is_None(self, model): - model.name = None assert str(model) == "GroupDMChannel with: snoop#0420, yeet#1012, nice#6969" def test_icon_url(self): @@ -178,8 +183,8 @@ def test_make_icon_url_without_optional_params(self, model): "https://cdn.discordapp.com/channel-icons/136134/1a2b3c.png?size=4096" ) - def test_make_icon_url_when_hash_is_None(self, model): - model.icon_hash = None + def test_make_icon_url_when_hash_is_None(self): + model = hikari_test_helpers.mock_class_namespace(channels.GroupDMChannel, init_=False, icon_hash=None)() assert model.make_icon_url() is None @@ -269,18 +274,11 @@ def model(self, mock_app): parent_id=None, ) - @pytest.mark.parametrize("error", [TypeError, AttributeError, NameError]) - def test_shard_id_property_when_guild_id_error_raised(self, model, error): - class BrokenApp: - def __getattr__(self, name): - if name == "shard_count": - raise error - return mock.Mock() - - model.app = BrokenApp() + def test_shard_id_property_when_not_shard_aware(self): + model = hikari_test_helpers.mock_class_namespace(channels.GuildChannel, init_=False, app=None)() assert model.shard_id is None - def test_shard_id_property_when_guild_id_is_not_None(self, model): + def test_shard_id_property_when_shard_aware(self, model): model.app.shard_count = 3 assert model.shard_id == 2 diff --git a/tests/hikari/test_embeds.py b/tests/hikari/test_embeds.py index d4d23eb441..656477de1f 100644 --- a/tests/hikari/test_embeds.py +++ b/tests/hikari/test_embeds.py @@ -52,13 +52,13 @@ def resource_with_proxy(self): def test_proxy_url(self, resource_with_proxy): assert resource_with_proxy.proxy_url is resource_with_proxy.proxy_resource.url - def test_proxy_url_when_resource_is_none(self, resource_with_proxy): - resource_with_proxy.proxy_resource = None + def test_proxy_url_when_resource_is_none(self): + resource_with_proxy = embeds.EmbedResourceWithProxy(resource=mock.Mock(), proxy_resource=None) assert resource_with_proxy.proxy_url is None def test_proxy_filename(self, resource_with_proxy): assert resource_with_proxy.proxy_filename is resource_with_proxy.proxy_resource.filename - def test_proxy_filename_when_resource_is_none(self, resource_with_proxy): - resource_with_proxy.proxy_resource = None + def test_proxy_filename_when_resource_is_none(self): + resource_with_proxy = embeds.EmbedResourceWithProxy(resource=mock.Mock(), proxy_resource=None) assert resource_with_proxy.proxy_filename is None diff --git a/tests/hikari/test_errors.py b/tests/hikari/test_errors.py index 299e523798..7e53caaf01 100644 --- a/tests/hikari/test_errors.py +++ b/tests/hikari/test_errors.py @@ -79,12 +79,11 @@ def test_str(self, error): assert str(error) == "Bad Request 400: 'raw body' for https://some.url" def test_str_when_status_is_not_HTTPStatus(self, error): - error.status = "SOME STATUS" + error = errors.HTTPResponseError("https://some.url", "SOME STATUS", {}, "raw body") assert str(error) == "Some Status: 'raw body' for https://some.url" - def test_str_when_message_is_not_None(self, error): - error.status = "SOME STATUS" - error.message = "Some message" + def test_str_when_message_is_not_None(self): + error = errors.HTTPResponseError("https://some.url", "SOME STATUS", {}, "raw body", "Some message") assert str(error) == "Some Status: 'Some message' for https://some.url" diff --git a/tests/hikari/test_guilds.py b/tests/hikari/test_guilds.py index e179cad1e8..416c6d0394 100644 --- a/tests/hikari/test_guilds.py +++ b/tests/hikari/test_guilds.py @@ -70,15 +70,17 @@ def model(self): icon_hash="ahashicon", )() - def test_icon_url_property(self, model): - model.make_icon_url = mock.Mock(return_value="url") + def test_icon_url_property(self): + model = hikari_test_helpers.mock_class_namespace( + guilds.PartialApplication, init_=False, make_icon_url=mock.Mock(return_value="url") + )() assert model.icon_url == "url" model.make_icon_url.assert_called_once_with() def test_make_icon_url_when_hash_is_None(self, model): - model.icon_hash = None + model = hikari_test_helpers.mock_class_namespace(guilds.PartialApplication, init_=False, icon_hash=None)() with mock.patch.object( routes, "CDN_APPLICATION_ICON", new=mock.Mock(compile_to_file=mock.Mock(return_value="file")) @@ -175,10 +177,6 @@ def test_app_property(self, model, mock_user): def test_id_property(self, model, mock_user): assert model.id is mock_user.id - def test_id_setter_property(self, model): - with pytest.raises(TypeError): - model.id = 456 - def test_username_property(self, model, mock_user): assert model.username is mock_user.username @@ -234,23 +232,22 @@ def test_default_avatar_url_property(self, model, mock_user): def test_display_name_property_when_nickname(self, model): assert model.display_name == "davb" - def test_display_name_property_when_no_nickname(self, model, mock_user): - model.nickname = None + def test_display_name_property_when_no_nickname(self, mock_user): + model = hikari_test_helpers.mock_class_namespace(guilds.Member, nickname=None, user=mock_user, init_=False)() assert model.display_name is mock_user.username def test_mention_property_when_nickname(self, model): assert model.mention == "<@!123>" - def test_mention_property_when_no_nickname(self, model, mock_user): - model.nickname = None + def test_mention_property_when_no_nickname(self, mock_user): + model = hikari_test_helpers.mock_class_namespace(guilds.Member, nickname=None, user=mock_user, init_=False)() assert model.mention == mock_user.mention def test_roles(self, model): - role1 = mock.Mock(id=321, position=2) - role2 = mock.Mock(id=654, position=1) - mock_cache_view = {321: role1, 654: role2} + role1 = mock.Mock(id=456, position=2) + role2 = mock.Mock(id=1234, position=1) + mock_cache_view = {456: role1, 1234: role2} model.user.app.cache.get_roles_view_for_guild.return_value = mock_cache_view - model.role_ids = [321, 654] assert model.roles == [role1, role2] @@ -258,10 +255,9 @@ def test_roles(self, model): def test_roles_when_role_ids_not_in_cache(self, model): role1 = mock.Mock(id=123, position=2) - role2 = mock.Mock(id=456, position=1) - mock_cache_view = {123: role1, 456: role2} + role2 = mock.Mock(id=1234, position=1) + mock_cache_view = {123: role1, 1234: role2} model.user.app.cache.get_roles_view_for_guild.return_value = mock_cache_view - model.role_ids = [321, 456] assert model.roles == [role2] @@ -317,7 +313,7 @@ def test_shard_id_property(self, model): assert model.shard_id == 0 def test_shard_id_when_not_shard_aware(self, model): - model.app = object() + model = hikari_test_helpers.mock_class_namespace(guilds.PartialGuild, init_=False, app=None)() assert model.shard_id is None @@ -327,14 +323,15 @@ def test_icon_url(self, model): with mock.patch.object(guilds.PartialGuild, "make_icon_url", return_value=icon): assert model.icon_url is icon - def test_make_icon_url_when_no_hash(self, model): - model.icon_hash = None + def test_make_icon_url_when_no_hash(self): + model = hikari_test_helpers.mock_class_namespace(guilds.PartialGuild, init_=False, icon_hash=None)() assert model.make_icon_url(ext="png", size=2048) is None - def test_make_icon_url_when_format_is_None_and_avatar_hash_is_for_gif(self, model): - model.icon_hash = "a_yeet" - + def test_make_icon_url_when_format_is_None_and_avatar_hash_is_for_gif(self): + model = hikari_test_helpers.mock_class_namespace( + guilds.PartialGuild, init_=False, icon_hash="a_yeet", id=90210 + )() with mock.patch.object( routes, "CDN_GUILD_ICON", new=mock.Mock(compile_to_file=mock.Mock(return_value="file")) ) as route: @@ -387,7 +384,7 @@ def model(self, mock_app): icon_hash="dis is mah icon hash", name="DAPI", splash_hash="dis is also mah splash hash", - discovery_splash_hash=None, + discovery_splash_hash="okokokok", emojis={}, approximate_active_member_count=12, approximate_member_count=999_283_252_124_633, @@ -401,8 +398,6 @@ def test_splash_url(self, model): assert model.splash_url is splash def test_make_splash_url_when_hash(self, model): - model.splash_hash = "18dnf8dfbakfdh" - with mock.patch.object( routes, "CDN_GUILD_SPLASH", new=mock.Mock(compile_to_file=mock.Mock(return_value="file")) ) as route: @@ -411,13 +406,13 @@ def test_make_splash_url_when_hash(self, model): route.compile_to_file.assert_called_once_with( urls.CDN_URL, guild_id=123, - hash="18dnf8dfbakfdh", + hash="dis is also mah splash hash", size=1024, file_format="url", ) def test_make_splash_url_when_no_hash(self, model): - model.splash_hash = None + model = hikari_test_helpers.mock_class_namespace(guilds.GuildPreview, splash_hash=None, init_=False)() assert model.make_splash_url(ext="png", size=512) is None def test_discovery_splash_url(self, model): @@ -427,8 +422,6 @@ def test_discovery_splash_url(self, model): assert model.discovery_splash_url is discovery_splash def test_make_discovery_splash_url_when_hash(self, model): - model.discovery_splash_hash = "18dnf8dfbakfdh" - with mock.patch.object( routes, "CDN_GUILD_DISCOVERY_SPLASH", new=mock.Mock(compile_to_file=mock.Mock(return_value="file")) ) as route: @@ -437,13 +430,13 @@ def test_make_discovery_splash_url_when_hash(self, model): route.compile_to_file.assert_called_once_with( urls.CDN_URL, guild_id=123, - hash="18dnf8dfbakfdh", + hash="okokokok", size=2048, file_format="url", ) - def test_make_discovery_splash_url_when_no_hash(self, model): - model.discovery_splash_hash = None + def test_make_discovery_splash_url_when_no_hash(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GuildPreview, init_=False, discovery_splash_hash=None)() assert model.make_discovery_splash_url(ext="png", size=4096) is None @@ -489,8 +482,6 @@ def test_splash_url(self, model): assert model.splash_url is splash def test_make_splash_url_when_hash(self, model): - model.splash_hash = "18dnf8dfbakfdh" - with mock.patch.object( routes, "CDN_GUILD_SPLASH", new=mock.Mock(compile_to_file=mock.Mock(return_value="file")) ) as route: @@ -499,13 +490,13 @@ def test_make_splash_url_when_hash(self, model): route.compile_to_file.assert_called_once_with( urls.CDN_URL, guild_id=123, - hash="18dnf8dfbakfdh", + hash="splash_hash", size=2, file_format="url", ) - def test_make_splash_url_when_no_hash(self, model): - model.splash_hash = None + def test_make_splash_url_when_no_hash(self): + model = hikari_test_helpers.mock_class_namespace(guilds.Guild, splash_hash=None, init_=False)() assert model.make_splash_url(ext="png", size=1024) is None def test_discovery_splash_url(self, model): @@ -515,8 +506,6 @@ def test_discovery_splash_url(self, model): assert model.discovery_splash_url is discovery_splash def test_make_discovery_splash_url_when_hash(self, model): - model.discovery_splash_hash = "18dnf8dfbakfdh" - with mock.patch.object( routes, "CDN_GUILD_DISCOVERY_SPLASH", new=mock.Mock(compile_to_file=mock.Mock(return_value="file")) ) as route: @@ -525,13 +514,13 @@ def test_make_discovery_splash_url_when_hash(self, model): route.compile_to_file.assert_called_once_with( urls.CDN_URL, guild_id=123, - hash="18dnf8dfbakfdh", + hash="discovery_splash_hash", size=1024, file_format="url", ) - def test_make_discovery_splash_url_when_no_hash(self, model): - model.discovery_splash_hash = None + def test_make_discovery_splash_url_when_no_hash(self): + model = hikari_test_helpers.mock_class_namespace(guilds.Guild, init_=False, discovery_splash_hash=None)() assert model.make_discovery_splash_url(ext="png", size=2048) is None def test_banner_url(self, model): @@ -555,7 +544,7 @@ def test_make_banner_url_when_hash(self, model): ) def test_make_banner_url_when_no_hash(self, model): - model.banner_hash = None + model = hikari_test_helpers.mock_class_namespace(guilds.Guild, init_=False, banner_hash=None)() assert model.make_banner_url(ext="png", size=2048) is None @@ -600,15 +589,19 @@ def model(self, mock_app): max_members=100, ) - def test_get_emoji(self, model): + def test_get_emoji(self): emoji = object() - model._emojis = {snowflakes.Snowflake(123): emoji} + model = hikari_test_helpers.mock_class_namespace( + guilds.RESTGuild, _emojis={snowflakes.Snowflake(123): emoji}, init_=False + )() assert model.get_emoji(123) is emoji - def test_get_role(self, model): + def test_get_role(self): role = object() - model._roles = {snowflakes.Snowflake(123): role} + model = hikari_test_helpers.mock_class_namespace( + guilds.RESTGuild, _roles={snowflakes.Snowflake(123): role}, init_=False + )() assert model.get_role(123) is role @@ -655,104 +648,104 @@ def test_channels(self, model): assert model.channels is model.app.cache.get_guild_channels_view_for_guild.return_value model.app.cache.get_guild_channels_view_for_guild.assert_called_once_with(123) - def test_channels_when_no_cache_trait(self, model): - model.app = object() + def test_channels_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.channels == {} def test_emojis(self, model): assert model.emojis is model.app.cache.get_emojis_view_for_guild.return_value model.app.cache.get_emojis_view_for_guild.assert_called_once_with(123) - def test_emojis_when_no_cache_trait(self, model): - model.app = object() + def test_emojis_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.emojis == {} def test_members(self, model): assert model.members is model.app.cache.get_members_view_for_guild.return_value model.app.cache.get_members_view_for_guild.assert_called_once_with(123) - def test_members_when_no_cache_trait(self, model): - model.app = object() + def test_members_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.members == {} def test_presences(self, model): assert model.presences is model.app.cache.get_presences_view_for_guild.return_value model.app.cache.get_presences_view_for_guild.assert_called_once_with(123) - def test_presences_when_no_cache_trait(self, model): - model.app = object() + def test_presences_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.presences == {} def test_roles(self, model): assert model.roles is model.app.cache.get_roles_view_for_guild.return_value model.app.cache.get_roles_view_for_guild.assert_called_once_with(123) - def test_roles_when_no_cache_trait(self, model): - model.app = object() + def test_roles_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.roles == {} def test_voice_states(self, model): assert model.voice_states is model.app.cache.get_voice_states_view_for_guild.return_value model.app.cache.get_voice_states_view_for_guild.assert_called_once_with(123) - def test_voice_states_when_no_cache_trait(self, model): - model.app = object() + def test_voice_states_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.voice_states == {} def test_get_channel(self, model): assert model.get_channel(456) is model.app.cache.get_guild_channel.return_value model.app.cache.get_guild_channel.assert_called_once_with(456) - def test_get_channel_when_no_cache_trait(self, model): - model.app = object() + def test_get_channel_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.get_channel(456) is None def test_get_emoji(self, model): assert model.get_emoji(456) is model.app.cache.get_emoji.return_value model.app.cache.get_emoji.assert_called_once_with(456) - def test_get_emoji_when_no_cache_trait(self, model): - model.app = object() + def test_get_emoji_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.get_emoji(456) is None def test_get_member(self, model): assert model.get_member(456) is model.app.cache.get_member.return_value model.app.cache.get_member.assert_called_once_with(123, 456) - def test_get_member_when_no_cache_trait(self, model): - model.app = object() + def test_get_member_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.get_member(456) is None def test_get_presence(self, model): assert model.get_presence(456) is model.app.cache.get_presence.return_value model.app.cache.get_presence.assert_called_once_with(123, 456) - def test_get_presence_when_no_cache_trait(self, model): - model.app = object() + def test_get_presence_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.get_presence(456) is None def test_get_role(self, model): assert model.get_role(456) is model.app.cache.get_role.return_value model.app.cache.get_role.assert_called_once_with(456) - def test_get_role_when_no_cache_trait(self, model): - model.app = object() + def test_get_role_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.get_role(456) is None def test_get_voice_state(self, model): assert model.get_voice_state(456) is model.app.cache.get_voice_state.return_value model.app.cache.get_voice_state.assert_called_once_with(123, 456) - def test_get_voice_state_when_no_cache_trait(self, model): - model.app = object() + def test_get_voice_state_when_no_cache_trait(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.get_voice_state(456) is None - def test_get_my_member_when_not_shardaware(self, model): - model.app = object() + def test_get_my_member_when_not_shardaware(self): + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=None)() assert model.get_my_member() is None def test_get_my_member_when_no_me(self, model): - model.app.me = None + model = hikari_test_helpers.mock_class_namespace(guilds.GatewayGuild, init_=False, app=mock.Mock(me=None))() assert model.get_my_member() is None def test_get_my_member(self, model): diff --git a/tests/hikari/test_messages.py b/tests/hikari/test_messages.py index 7e06568369..c19624b092 100644 --- a/tests/hikari/test_messages.py +++ b/tests/hikari/test_messages.py @@ -31,6 +31,7 @@ from hikari import urls from hikari import users from hikari.internal import routes +from tests.hikari import hikari_test_helpers class TestAttachment: @@ -71,8 +72,10 @@ def test_cover_image_url(self, message_application): with mock.patch.object(messages.MessageApplication, "make_cover_image_url") as mock_cover_image: assert message_application.cover_image_url is mock_cover_image() - def test_make_cover_image_url_when_hash_is_none(self, message_application): - message_application.cover_image_hash = None + def test_make_cover_image_url_when_hash_is_none(self): + message_application = hikari_test_helpers.mock_class_namespace( + messages.MessageApplication, init_=False, cover_image_hash=None + )() assert message_application.make_cover_image_url() is None @@ -90,7 +93,7 @@ def test_make_cover_image_url_when_hash_is_not_none(self, message_application): @pytest.fixture() def message(): return messages.Message( - app=None, + app=mock.Mock(rest=mock.AsyncMock()), id=snowflakes.Snowflake(1234), channel_id=snowflakes.Snowflake(5678), guild_id=snowflakes.Snowflake(910112), @@ -125,25 +128,18 @@ def message(): class TestMessage: def test_make_link_when_guild_is_not_none(self, message): - message.id = 789 - message.channel_id = 456 - assert message.make_link(123) == "https://discord.com/channels/123/456/789" + assert message.make_link(123) == "https://discord.com/channels/123/5678/1234" def test_make_link_when_guild_is_none(self, message): - message.app = mock.Mock() - message.id = 789 - message.channel_id = 456 - assert message.make_link(None) == "https://discord.com/channels/@me/456/789" + assert message.make_link(None) == "https://discord.com/channels/@me/5678/1234" def test_guild_id_when_guild_is_not_none(self, message): - message._guild_id = 123 + assert message.guild_id == 910112 - assert message.guild_id == 123 - - def test_guild_id_when_guild_is_none(self, message): - message.app = mock.Mock() - message._guild_id = None - message.channel_id = 890 + def test_guild_id_when_guild_is_none(self): + message = hikari_test_helpers.mock_class_namespace( + messages.Message, init_=False, _guild_id=None, channel_id=890, app=mock.Mock() + )() message.app.cache.get_guild_channel = mock.Mock(return_value=mock.Mock(guild_id=456)) assert message.guild_id == 456 @@ -154,15 +150,10 @@ def test_guild_id_when_guild_is_none(self, message): @pytest.mark.asyncio() class TestAsyncMessage: async def test_fetch_channel(self, message): - message.app = mock.AsyncMock() - message.channel_id = 123 await message.fetch_channel() - message.app.rest.fetch_channel.assert_awaited_once_with(123) + message.app.rest.fetch_channel.assert_awaited_once_with(5678) async def test_edit(self, message): - message.app = mock.AsyncMock() - message.id = 123 - message.channel_id = 456 embed = object() attachment = object() roles = [object()] @@ -179,8 +170,8 @@ async def test_edit(self, message): flags=messages.MessageFlag.URGENT, ) message.app.rest.edit_message.assert_awaited_once_with( - message=123, - channel=456, + message=1234, + channel=5678, content="test content", embed=embed, attachment=attachment, @@ -194,9 +185,6 @@ async def test_edit(self, message): ) async def test_respond(self, message): - message.app = mock.AsyncMock() - message.id = 123 - message.channel_id = 456 embed = object() roles = [object()] attachment = object() @@ -216,7 +204,7 @@ async def test_respond(self, message): mentions_reply=True, ) message.app.rest.create_message.assert_awaited_once_with( - channel=456, + channel=5678, content="test content", embed=embed, attachment=attachment, @@ -231,9 +219,6 @@ async def test_respond(self, message): ) async def test_respond_when_reply_is_True(self, message): - message.app = mock.AsyncMock() - message.id = 123 - message.channel_id = 456 embed = object() roles = [object()] attachment = object() @@ -252,7 +237,7 @@ async def test_respond_when_reply_is_True(self, message): mentions_reply=True, ) message.app.rest.create_message.assert_awaited_once_with( - channel=456, + channel=5678, content="test content", embed=embed, attachment=attachment, @@ -267,44 +252,26 @@ async def test_respond_when_reply_is_True(self, message): ) async def test_delete(self, message): - message.app = mock.AsyncMock() - message.id = 123 - message.channel_id = 456 await message.delete() - message.app.rest.delete_message.assert_awaited_once_with(456, 123) + message.app.rest.delete_message.assert_awaited_once_with(5678, 1234) async def test_add_reaction(self, message): - message.app = mock.AsyncMock() - message.id = 123 - message.channel_id = 456 await message.add_reaction("👌") - message.app.rest.add_reaction.assert_awaited_once_with(channel=456, message=123, emoji="👌") + message.app.rest.add_reaction.assert_awaited_once_with(channel=5678, message=1234, emoji="👌") async def test_remove_reaction(self, message): - message.app = mock.AsyncMock() - message.id = 123 - message.channel_id = 456 await message.remove_reaction("👌") - message.app.rest.delete_my_reaction.assert_awaited_once_with(channel=456, message=123, emoji="👌") + message.app.rest.delete_my_reaction.assert_awaited_once_with(channel=5678, message=1234, emoji="👌") async def test_remove_reaction_with_user(self, message): - message.app = mock.AsyncMock() user = object() - message.id = 123 - message.channel_id = 456 await message.remove_reaction("👌", user=user) - message.app.rest.delete_reaction.assert_awaited_once_with(channel=456, message=123, emoji="👌", user=user) + message.app.rest.delete_reaction.assert_awaited_once_with(channel=5678, message=1234, emoji="👌", user=user) async def test_remove_all_reactions(self, message): - message.app = mock.AsyncMock() - message.id = 123 - message.channel_id = 456 await message.remove_all_reactions() - message.app.rest.delete_all_reactions.assert_awaited_once_with(channel=456, message=123) + message.app.rest.delete_all_reactions.assert_awaited_once_with(channel=5678, message=1234) async def test_remove_all_reactions_with_emoji(self, message): - message.app = mock.AsyncMock() - message.id = 123 - message.channel_id = 456 await message.remove_all_reactions("👌") - message.app.rest.delete_all_reactions_for_emoji.assert_awaited_once_with(channel=456, message=123, emoji="👌") + message.app.rest.delete_all_reactions_for_emoji.assert_awaited_once_with(channel=5678, message=1234, emoji="👌") diff --git a/tests/hikari/test_sessions.py b/tests/hikari/test_sessions.py index 031e2fc51d..8c39d05882 100644 --- a/tests/hikari/test_sessions.py +++ b/tests/hikari/test_sessions.py @@ -23,6 +23,7 @@ import datetime from hikari import sessions +from tests.hikari import hikari_test_helpers def test_SessionStartLimit_used_property(): @@ -33,12 +34,10 @@ def test_SessionStartLimit_used_property(): def test_SessionStartLimit_reset_at_property(): - obj = sessions.SessionStartLimit( - total=100, - remaining=2, + obj = hikari_test_helpers.mock_class_namespace( + sessions.SessionStartLimit, + init_=False, + _created_at=datetime.datetime(2020, 7, 22, 22, 22, 36, 988017, tzinfo=datetime.timezone.utc), reset_after=datetime.timedelta(hours=1, days=10), - max_concurrency=1, - ) - obj._created_at = datetime.datetime(2020, 7, 22, 22, 22, 36, 988017, tzinfo=datetime.timezone.utc) - + )() assert obj.reset_at == datetime.datetime(2020, 8, 1, 23, 22, 36, 988017, tzinfo=datetime.timezone.utc) diff --git a/tests/hikari/test_users.py b/tests/hikari/test_users.py index f04e081019..10ae503b63 100644 --- a/tests/hikari/test_users.py +++ b/tests/hikari/test_users.py @@ -195,8 +195,10 @@ def obj(self): def test_str_operator(self, obj): assert str(obj) == "thomm.o#8637" - def test_str_operator_when_partial(self, obj): - obj.username = undefined.UNDEFINED + def test_str_operator_when_partial(self): + obj = hikari_test_helpers.mock_class_namespace( + users.PartialUserImpl, username=undefined.UNDEFINED, id=123, rename_impl_=False, init_=False + )() assert str(obj) == "Partial user ID 123" def test_mention_property(self, obj): diff --git a/tests/hikari/test_webhooks.py b/tests/hikari/test_webhooks.py index 00363693a9..ee3677ea05 100644 --- a/tests/hikari/test_webhooks.py +++ b/tests/hikari/test_webhooks.py @@ -23,6 +23,7 @@ import pytest from hikari import webhooks +from tests.hikari import hikari_test_helpers class TestWebhook: @@ -46,8 +47,9 @@ def webhook(self): def test_str(self, webhook): assert str(webhook) == "not a webhook" - def test_str_when_name_is_None(self, webhook): - webhook.name = None + def test_str_when_name_is_None(self): + webhook = hikari_test_helpers.mock_class_namespace(webhooks.Webhook, init_=False, name=None, id=987654321)() + assert str(webhook) == "Unnamed webhook ID 987654321" @pytest.mark.asyncio @@ -63,8 +65,8 @@ async def test_fetch_message(self, webhook): webhook.app.rest.fetch_webhook_message.assert_called_once_with(987654321, token="abc123bca", message=message) @pytest.mark.asyncio - async def test_fetch_message_when_no_token(self, webhook): - webhook.token = None + async def test_fetch_message_when_no_token(self): + webhook = hikari_test_helpers.mock_class_namespace(webhooks.Webhook, init_=False, token=None)() with pytest.raises(ValueError, match=r"Cannot fetch a message using a webhook where we don't know the token"): await webhook.fetch_message(987) @@ -107,8 +109,8 @@ async def test_edit_message(self, webhook): ) @pytest.mark.asyncio - async def test_edit_message_when_no_token(self, webhook): - webhook.token = None + async def test_edit_message_when_no_token(self): + webhook = hikari_test_helpers.mock_class_namespace(webhooks.Webhook, init_=False, token=None)() with pytest.raises(ValueError, match=r"Cannot edit a message using a webhook where we don't know the token"): await webhook.edit_message(987) @@ -122,7 +124,7 @@ async def test_delete_message(self, webhook): webhook.app.rest.delete_webhook_message.assert_called_once_with(987654321, token="abc123bca", message=message) @pytest.mark.asyncio - async def test_delete_message_when_no_token(self, webhook): - webhook.token = None + async def test_delete_message_when_no_token(self): + webhook = hikari_test_helpers.mock_class_namespace(webhooks.Webhook, init_=False, token=None)() with pytest.raises(ValueError, match=r"Cannot delete a message using a webhook where we don't know the token"): assert await webhook.delete_message(987)