# How can I dynamically generate operator classes?

I am trying to generate dynamically operator classes.

The code below is based on the code at the end of this link

cls.CustomOp = []
for i in ['a', 'b']:
idname = "object.operator_" + i

def func(self, context):
print("Hello World", self.bl_idname)
return {'FINISHED'}

opclass = type("DynOp" + i,
(bpy.types.Operator, ),
{"bl_idname": idname, "bl_label": "Test", "execute": func},
)
bpy.utils.register_class(opclass)
cls.CustomOp = cls.CustomOp + [opclass]


I have tried the code above in poll and draw contexts, but always the same :

"RuntimeError: register_class(...): can't run in readonly state 'DynOpa'".

What does readonly context mean? How to do it (and from where) in a non-readonly context?

• The question for me is what is behind needing to dynamically generate operator classes? – Ray Mairlot Jun 27 '16 at 18:17
• @RayMairlot at the base this is related to solve this blender.stackexchange.com/questions/56727/…. But that can be a more general question – lemon Jun 27 '16 at 18:25
• You can not run any commands that change properties whithin a poll or a draw function. As far as i know the only context where you can change something is when an operator actually runs or within a callback function that is started "on property change" when you for example set an option in a panel. – Gaia Clary Jun 27 '16 at 19:52
• ok @GaiaClary, so this kind of approach cannot work in the context of your question ? or is it possible to apply this in another context (before a poll or a draw) ? – lemon Jun 27 '16 at 19:56

As you found, you can't register operators during some actions such as drawing or polling. We can define custom operators within an addons register() or within an operators execute() method, you can also manually run your script from blender's text editor without any issue.

For brevity I'll replace your for loop with a function called create_custom_operator()

def create_custom_operator(i):
idname = "object.operator_" + i
.... # rest as above


You can then use it in an addons register() -

def register():
for n in ['a','b','c']:
create_custom_operator(n)


Or you could use it in an operator's execute(). Note that I use a file list to define the operators here, we can do this in an operator's execute but not while registering an addon as we can't access the filesystem during addon registration.

class MakeCustomOperators(bpy.types.Operator):
"""Create custom operators"""