Get bpy.context access inside a class outside the execute function

Hi all, can someone please show me an example for this question? I have already asked on StackExchange, but unfortunately I was not given an example.

It’s about how I get access to bpy.context when creating the lists for a preset system as seen in the link.
https://blender.stackexchange.com/questions/207322/how-to-get-values-from-bpy-context-inside-a-class/223043?noredirect=1#comment377100_223043

Now I have been able to do something myself to determine which blender version is being used. But this only works when blender starts up.

As written by batFINGER, it is also possible to get context via def poll(cls, context), which is always taken into account, not only when blender starts.

But I just can’t get it to work! I’m afraid I don’t quite understand his answer.

Can someone please give me an example?

Instead of extending the list when the class is defined, you should instead dynamically generate preset_values when it’s actually needed by the preset operator, and check for use_multiview there.

Consider that the user might change use_multiview after your class was defined. How would you check against this?

Thank you, that would have been my first idea too. But unfortunately I don’t have access to the operator in the preset system, which is integrated in blender. That’s the reason why I need access to bpy.context from the class, not from the operator.

This is how a preset menu works:
https://docs.blender.org/api/current/bpy.types.Menu.html?highlight=preset#preset-menus

You do have access to the preset operator. You’re subclassing from it.

Define an execute method and return super().execute(context) to call the preset operator. But before doing that, set up your preset_values list.


    def execute(self, context):
        self.preset_values = [
            ...
        ]
        
        if context.scene.render.use_multiview:
            self.preset_values.extend([
                ...
            ])
        return super().execute(context)

1 Like

That looks great! Will test it next Monday. Thank you very much!

1 Like

Yes! Thank you very much. It works as expected.

May I ask: How did you know it works using return super().execute(context) ? I would like to educate myself so that I have to ask less questions, but I don’t really know what to learn for this.

1 Like

Python is object oriented.

When you subclass another type, your class automatically gets access to the methods of the base class, also commonly referred to as the superclass.

If the superclass has an execute method, which it does (see AddPresetBase in scripts/startup/bl_operators/presets.py), you can override it by defining your own method of the same name, which has the same parameters. This is a key aspect of polymorphism, and we do it every time we create an operator (by subclassing bpy.types.Operator and defining our own execute).

When your operator is called, only your own execute will run - not the superclass’. But say you want to call the superclass’ execute as well as your own, that’s when you can use super().

super() in python is syntactic sugar to saying “reinterpret my instance as if i were my superclass”. What you get in return from super(), is not a new instance of AddPresetBase, but an instance of your own class dressed as AddPresetBase.

You could also have written AddPresetBase.execute(self, context) to call the method, and manually pass self and context, too. Semantically there’s no difference, the results are the same, except for the fact that here we hard-code a call to AddPresetBase. super(), however, tends to be convenient and easier to maintain, because we’re not hard-coding anything in case the inheritance changes sometime in the future.

1 Like