Access Class Properties From Poll Function

Is there a way to access class properties from the poll function. For Example:

class OPS_some_operator(Operator):
    bl_idname = "object.some_operator"
    bl_label = "Some Operator"
    
    object_name = StringProperty(name="Object Name",default="Hello World")  
    
    @classmethod
    def poll(cls, context):
        print(self.object_name)

Since the classmethod decorator is being used, self is not the first parameter passed into the function. Is there anyway to access these properties from the poll function.

Any help would be appreciated. Thanks!

But that doesn’t make sense(to me I guess). The poll decides if the operator can be called and the property depends on the operator being called, so it seems you’re putting the cart before the horse unless I’m misunderstanding. Maybe elaborate on what you’re trying to do.

Sometimes I want to operate on an object that is not selected, so i pass in the object name to the operator and retrieve it in the invoke or execute function. So i add the operator to the interface like this:

layout.operator('object.some_operator').object_name = "My Object Name"

This works just fine, but in some instances the object might not be created yet, or i might want to check a property of the object before i determine if the operator can be run. So in the poll function it would be nice to check if it exists like this.

if self.object_name in bpy.data.objects:
    return True
else:
    return False

There are several ways around this, but it sure would be handy if i can access the class properties in the poll function. I don’t work with the @classmethod decorator much, so i just wanted to check and see if anyone knew a way around.

1 Like

Not that I know of. Personally, I would just have a string property outside of the class and just feed that into that class properties and in the poll. But like you said, there are many ways.

Met the similar issue. You can disable operator from the UI like this:

        row = layout.row()
        row.operator('object.some_operator').object_name = "My Object Name"
        row.enabled = False

Downside of this approach you’re still not able to set poll message with cls.poll_message_set("Provide object name") to let user know what’s the issue.

You may use layout.context_pointer_set but it’s not explicitely passing around variables so it can make debugging extra hard, and I don’t know if it bodes really well with executing operators directly in code (without clicking on a button in the UI) with bpy.ops.my_operator().

Animation3

import bpy


class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

    @classmethod
    def poll(cls, context):
        if not hasattr(context, "my_condition") or context.my_condition is None:
            cls.poll_message_set("Please select an object")
            return False
        return True

    def execute(self, context):
        print(context.my_condition.name)
        return {'FINISHED'}
    

class HelloWorldPanel(bpy.types.Panel):
    bl_label = "Hello World Panel"
    bl_idname = "SCENE_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "scene"

    def draw(self, context):
        layout = self.layout
        layout.context_pointer_set("my_condition", context.active_object)
        layout.operator("object.simple_operator")


def register():
    bpy.utils.register_class(HelloWorldPanel)
    bpy.utils.register_class(SimpleOperator)



if __name__ == "__main__":
    register()

1 Like

I guess another downside of this approach is similar to trying to figure out for default blender operators what context attribute they’re using - when you’re not sure either “context.object” or “context.active_object” this time and the only way to know is to look up the operator’s code.

So you won’t be able to call operator simply with bpy.ops.object.simple_operator(my_condition=True) only with

with context.temp_override(my_condition=True): 
    bpy.ops.object.simple_operator()

I’m not even sure you can use temp override with context_pointer_set. Also you can’t set plain old python objects, they have to be pointers to Blender data or property groups so you won’t be able to set layout.context_pointer_set("my_condition", True) or layout.context_pointer_set("my_float", 3.14) for example.

Is it possible to somehow add new context property after operator ui element is already added? That way it would be possible to just pass operator’s properties.

I mean something like this:

import bpy


class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

    @classmethod
    def poll(cls, context):
        if not hasattr(context, "my_condition") or context.my_condition is None:
            cls.poll_message_set("Please select an object")
            return False
        return True

    def execute(self, context):
        print(context.my_condition.name)
        return {'FINISHED'}
    

class HelloWorldPanel(bpy.types.Panel):
    bl_label = "Hello World Panel"
    bl_idname = "SCENE_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "scene"

    def draw(self, context):
        layout = self.layout
        op = layout.operator("object.simple_operator")
        layout.context_pointer_set("my_condition", context.active_object)
        # which would make possible
        # layout.context_pointer_set("my_condition", op)


def register():
    bpy.utils.register_class(HelloWorldPanel)
    bpy.utils.register_class(SimpleOperator)



if __name__ == "__main__":
    register()

It’s unfortunate that we can’t access operator properties in poll. I think it is not possible because at the time poll is queried, the operator construct hasnt been created yet (note use of cls and not self) so the operator properties aren’t available. I agree that they should be since op is a construct that stores the operator properties and it is available in the UI, but it’s not possible to add it the layout context after initialization.

Interesting read on the subject checking properties in poll - #2 by guy_lateur