Repository: Rapptz/discord.py
File: discord/interactions.py (Python)

Code before:
                pass

    @property
    def channel(self) -> Optional[InteractionChannel]:
        """Optional[Union[:class:`abc.GuildChannel`, :class:`abc.PrivateChannel`, :class:`Thread`]]: The channel
        the interaction was sent from.

        .. versionadded:: 2.3
        """
        _ch_type = self._channel.get('type')
        if _ch_type is not None:
            factory, ch_type = _threaded_channel_factory(_ch_type)
            _channel_id = self._channel['id']
            if factory is None:
                raise InvalidData(f'Unknown channel type {_ch_type} for channel ID {_channel_id}.')

            if ch_type in (ChannelType.group, ChannelType.private):
                channel = factory(me=self._client.user, data=self._channel, state=self._state)  # type: ignore
            else:
                guild = self._state._get_guild(self.guild_id)
                channel = factory(guild=guild, state=self._state, data=self._channel)  # type: ignore

            return channel

        return None

    @property
    def client(self) -> ClientT:
        """:class:`Client`: The client that is handling this interaction.

        Note that :class:`AutoShardedClient`, :class:`~.commands.Bot`, and
        :class:`~.commands.AutoShardedBot` are all subclasses of client.
        """
        return self._client

    @property
    def guild(self) -> Optional[Guild]:
        """Optional[:class:`Guild`]: The guild the interaction was sent from."""
        return self._state and self._state._get_guild(self.guild_id)

    @property
    def permissions(self) -> Permissions:
        """:class:`Permissions`: The resolved permissions of the member in the channel, including overwrites.

        In a non-guild context where this doesn't apply, an empty permissions object is returned.
        """
        return Permissions(self._permissions)

    @property
    def app_permissions(self) -> Permissions:
        """:class:`Permissions`: The resolved permissions of the application or the bot, including overwrites."""

Review comment (performance):
None of this code belongs inside a `@property`. Removing the `_cs_channel` cached property was also a bizarre decision considering it would have made this more efficient on secondary access.

Code after:
            # Upgrade Message.guild in case it's missing with partial guild data
            if self.message is not None and self.message.guild is None:
                self.message.guild = guild

            try:
                member = data['member']  # type: ignore # The key is optional and handled
            except KeyError:
                pass
            else:
                self.user = Member(state=self._state, guild=guild, data=member)
                self._permissions = self.user._permissions or 0
        else:
            try:
                self.user = User(state=self._state, data=data['user'])  # type: ignore # The key is optional and handled
            except KeyError:
                pass

    @property
    def client(self) -> ClientT:
        """:class:`Client`: The client that is handling this interaction.

        Note that :class:`AutoShardedClient`, :class:`~.commands.Bot`, and
        :class:`~.commands.AutoShardedBot` are all subclasses of client.
        """
        return self._client

    @property
    def guild(self) -> Optional[Guild]:
        """Optional[:class:`Guild`]: The guild the interaction was sent from."""
        return self._state and self._state._get_guild(self.guild_id)

    @property
    def channel_id(self) -> Optional[int]:
        """Optional[:class:`int`]: The ID of the channel the interaction was sent from."""
        return self.channel.id if self.channel is not None else None

    @property
    def permissions(self) -> Permissions:
        """:class:`Permissions`: The resolved permissions of the member in the channel, including overwrites.

        In a non-guild context where this doesn't apply, an empty permissions object is returned.
        """
        return Permissions(self._permissions)

    @property
    def app_permissions(self) -> Permissions:
        """:class:`Permissions`: The resolved permissions of the application or the bot, including overwrites."""
        return Permissions(self._app_permissions)

    @utils.cached_slot_property('_cs_namespace')
    def namespace(self) -> Namespace: