Run op while addon registers.

How can I run an operator right at the addon register function? The operator’s context will be very generic not for scene or object, more like to window manager or at a similar level.

There should be a way the operator is called, perhaps the window manager itself can do it? I still try to find how to do it, if you have any ideas please drop a comment, thanks.

What exactly do you want to execute?

It’s basically not supported, you’re supposed to let the user click a button to run an operation.

It’s possible to circumvent restrictions by using a one-shot scene update handler.

This thing with operators confuses me a bit. :slight_smile:

I was interested about doing some sort of operating system checks at this time, so I won’t need any access to scene or bpy data or scene context.


bl_info = {
    "name": "Test",
    "category": "Development"
}


import bpy


def operator1():print("Operator 1 work.")
def operator2():print("Operator 2 work.")


class TestPreferences(bpy.types.AddonPreferences):
    bl_idname = __name__
    def draw(self, context): self.layout.label("Test OK")


def register(): bpy.utils.register_module(__name__); operator1(); operator2()
def unregister(): bpy.utils.unregister_module(__name__)

Update I have found a working solution!

CoDEmanX I have looked into your suggestion about using a scene handler and no more no less I went for Python’s task scheduling instead since it looks more straight forward.
https://docs.python.org/2/library/sched.html

Now I change again my code to support this new way of invoking the operator and it works fine.


bl_info = {
    "name": "Test",
    "category": "Development"
}


import bpy
import time
from threading import Timer


def pseudo_operator():
    print("Operator runs ", time.time())
    # Surpisingly this works!!!
    bpy.ops.wm.test_operator()
    # This also works: access to scene context 
    print(bpy.context.scene)


class TestOperator(bpy.types.Operator):
    bl_idname = "wm.test_operator"
    bl_label = "Test Operator"
    def execute(self, context):
        print("Hello from test operator")
        return {'FINISHED'}


def register():
    bpy.utils.register_module(__name__)
    # addon = bpy.context.user_preferences.addons[__name__]


    # This line here fails due to invalid context:
    # bpy.ops.wm.test_operator()
    
    # This line here fails due to invalid context:
    # print(bpy.context.scene)


    Timer(1, pseudo_operator, ()).start()


def unregister():
    bpy.utils.unregister_module(__name__)


It is a a bit odd to use this hack, but if it is a valid and safe practice then I guess that everything should be fine. :yes: Any comments about it?

EDIT: From what I found, it’s that the context while the register function is called, does not contain the full context set (such as scene, e.t.c.), it is specifically dedicated to addons.

If you want to check OS things, why do you want these checks to be wrapped in an operator? Why not call a regular python function and store the results e.g. in a global variable?

The “official” would be to check OS or that kinda things during each operator execution, so within the execute() method. Using a global function and some kind of cache can make it more efficient, i.e. remember the results of the first run and don’t do all the probing again.

The user would have to run operator normally, though if Blender do it automatically is just an additional benefit for me to to enhance usability.

But apart from operator itself (say that I won’t use it), I will still need access to scene properties so this also brings another roadblock. It’s only that this exact register() function is very strict and it’s context is limited.

P.S. Your initial suggestion with a app handler called only once, seems solid and won’t get out of Blender’s guidelines.