Pass instance attribute as a decorator parameter

Question:

I am creating a class Encuesta to create multiple surveys via user commands for a discord bot using discord.py.
To achieve this, I have to pass the attribute "self.buttonid" as the ‘custom_id’ parameter for the decorator @discord.ui.button (already defined by discord.py).

class Encuesta(discord.ui.View):

    def __init__(self, pregunta, buttonid):
        super().__init__(timeout=None)
        self.pregunta = pregunta
        self.buttonid = buttonid

    @discord.ui.button(label="Realizar encuesta", style=discord.ButtonStyle.grey, custom_id=self.buttonid)
    async def encuesta(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.send_modal(await crear_modal(self.pregunta, interaction.user))

But I get the error "self is not defined", since ‘self’ only exists inside class methods, and cant access it from the decorator calling.

I just need to get access to self.buttonid while calling the decorator.

I tried directly calling self.buttonid, without success. Other answers rely on modifyng the decorator, and I would want to avoid that.

Asked By: Lautaro Scoflich

||

Answers:

Since a discord View class is meant to be instantiated only once, one viable workaround would be to use a class factory function to create a singleton class with buttonid preserved in the closure of the factory function rather than storing it as an instance attribute:

def Encuesta(pregunta, buttonid):
    class _Encuesta(discord.ui.View):
        def __init__(self):
            super().__init__(timeout=None)
    
        @discord.ui.button(
            label="Realizar encuesta",
            style=discord.ButtonStyle.grey,
            custom_id=buttonid)
        async def encuesta(self, interaction: discord.Interaction, button: discord.ui.Button):
            await interaction.response.send_modal(await crear_modal(pregunta, interaction.user))

    return _Encuesta()
Answered By: blhsing
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.