Automatically generate a list of operator classes for bpy.utils.register_classes_factory?

Hi,

is there a way to create a list of operators contained in to a module ?

so I would be able to fee that list into bpy.utils.register_classes_factory ?

classes = ( some_module.SOMEOPEARATOR_OT_Opearator,...)

register, unregister = bpy.utils.register_classes_factory(classes)
	
if __name__ == "__main__":
	register()

thanks for your help

Hello,

I’m not sure to understand everything, the operators you want to seek are the ones you made ?
Or they’re operators built-in blender ?

If I understand correctly, you want to automatically register all the operators you’ve made without filling the classes manually ?

1 Like

yep my operators
I always forget to add new operators to that bloody array, I want it to be automatic

so far I found this

import sys, inspect
def print_classes():
    for name, obj in inspect.getmembers(sys.modules[__name__]):
        if inspect.isclass(obj):
            print(obj)

Ok, I didn’t look into this…
I’m not sure but maybe in animation node addon there is something similar.
I’m pretty sure I’ve seen it but I don’t recall where …
At least, if what you’ve found works maybe it’s not worth to keep investigating .

I am close but I get an error

TypeError: can only concatenate tuple (not "type") to tuple

anyone knows how to add the class to the tuple ?

def addModuleClasses(classes,name,prefix):
	for name, obj in inspect.getmembers(sys.modules[name]):
		if inspect.isclass(obj) and name.startswith(prefix):
			classes=classes+(obj.__class__) <------------------ error
	return classes

You can’t edit tuples… they’re immutable in Python…

but you can concat them to new tuples
besides it’s not the error is about AFAIK
image

You can look here in animation nodes for inspiration :

1 Like

oh nice, I’ll have a look
thanks m8

1 Like

Another useful reference is the Help > Operator Cheat Sheet built in to Blender:

class WM_OT_operator_cheat_sheet(Operator):
    """List all the operators in a text-block, useful for scripting"""
    bl_idname = "wm.operator_cheat_sheet"
    bl_label = "Operator Cheat Sheet"

    def execute(self, _context):
        op_strings = []
        tot = 0
        for op_module_name in dir(bpy.ops):
            op_module = getattr(bpy.ops, op_module_name)
            for op_submodule_name in dir(op_module):
                op = getattr(op_module, op_submodule_name)
                text = repr(op)
                if text.split("\n")[-1].startswith("bpy.ops."):
                    op_strings.append(text)
                    tot += 1

            op_strings.append('')

        textblock = bpy.data.texts.new("OperatorList.txt")
        textblock.write('# %d Operators\n\n' % tot)
        textblock.write('\n'.join(op_strings))
        self.report({'INFO'}, "See OperatorList.txt text block")
        return {'FINISHED'}

Blender/Contents/Resources/3.1/scripts/startup/bl_operators/wm.py

I use this in all my addons and I never have to worry about registering classes. You just have to remember to put a __init__.py file in all your package folders. Even if they’re empty files.

It’s great because it automatically takes care of dependencies when registering. (eg a panel that needs to draw an operator registers before it and it throws an error)

1 Like

nice but where do you put that code if not in the init.py ?

You can put it in __init__.py although I woudn’t recommend it since I think it’s better if it stays relatively lightweight. Or just put it at the root of your package and do

import auto_load
auto_load.init()
auto_load.register()

You can take a look at the structure of this addon for instance

The init file.

I dont know, I just cannot make it work

Exception in module register(): C:\Users\user\AppData\Roaming\Blender Foundation\Blender\2.91\scripts\addons\MyAddon\__init__.py
Traceback (most recent call last):
  File "P:\Program Files\Blender Foundation\Blender 2.91\2.91\scripts\modules\addon_utils.py", line 382, in enable
    mod.register()
  File "C:\Users\user\AppData\Roaming\Blender Foundation\Blender\2.91\scripts\addons\MyAddon\__init__.py", line 140, in register
    auto_load.register()
  File "C:\Users\user\AppData\Roaming\Blender Foundation\Blender\2.91\scripts\addons\MyAddon\auto_load.py", line 29, in register
    for cls in ordered_classes:
TypeError: 'NoneType' object is not iterable

I implemented it this way:

import auto_load

def register():
	auto_load.init()
	auto_load.register()

def unregister():
	auto_load.init()
	auto_load.unregister()

if __name__ == "__main__":
	if hasattr(bpy.types, "MYADDON_PT_Panel"):
		print("------------------ unregister --------------------")
		unregister()
	print("------------------ register --------------------")
	register()

[ADMIN can you set this thread as unresolved ? thanks]

What’s the file structure of your addon ?

ok I finaly made it work, but my panel does not appear, I’ll have to debug register() to find out the issue
no error message in the console so far

I have an issue with one of my class that usualy loads

`CollectionProperty(...): expected an RNA type, failed with: RuntimeError: , missing bl_rna attribute from 'RNAMetaPropGroup' instance (may not be registered)`
...
ValueError: bpy_struct "MyPreferences" registration error: materials could not register

maybe something is missing in this class

import bpy
import myaddon_ui_unreal_materials_list
import myaddon_ui_unreal_bones_list  

class MyPreferences(bpy.types.AddonPreferences):
    bl_idname = "MyAddon"
    angle: bpy.props.FloatProperty(name="Random angle",
                                    description="add rotation randomness",
                                    min=0.0, 
                                    max=90.0, 
                                    default=360.0)
    scale: bpy.props.FloatProperty(name="Random scale",
                                    description="add scale randomness",
                                    min=0.0, 
                                    max=1.0, 
                                    default=0.01)
    materials: bpy.props.CollectionProperty(type = myaddon_ui_unreal_materials_list.MaterialListItem)
    materials_index: bpy.props.IntProperty(name="ListBox index",
                                    description="ListBox index",
                                    min=0, 
                                    default=0)

    bones: bpy.props.CollectionProperty(type = myaddon_ui_unreal_bones_list.BoneListItem)
    bones_index: bpy.props.IntProperty(name="ListBox index",
                                       description="ListBox index",
                                       min=0, 
                                       default=0)

I got the feeling this class might not be registered

myaddon_ui_unreal_materials_list.MaterialListItem

when MyPreferences is getting registered

Yes it looks like it, what does the MaterialListItem class look like ?

class MaterialListItem(PropertyGroup):
    """Group of properties representing an item in the list."""

    unrealMaterialReference: StringProperty(
           name="Unreal Material Reference",
           description="Unreal Material Reference",
           default="Untitled")
    blenderMaterialName: StringProperty(
           name="Unreal Material Reference",
           description="Unreal Material Reference",
           default="Untitled")