3

Using the information from this answer and this answer, I wrote a very simple script to enable rigify if it it wasn't already enabled

import bpy
import addon_utils

addon = bpy.context.preferences.addons.get('rigify')

if not addon: addon_utils.enable('Rigify')

When it failed to work I expanded it to get some diagnostic input and so I extended it to this:

import bpy
import addon_utils

for addon in bpy.context.preferences.addons: print(addon.module)

for module in addon_utils.modules(): print(module.bl_info.get('name'))

addon = bpy.context.preferences.addons.get('rigify')

if not addon: for module in addon_utils.modules(): if module.bl_info.get('name') == 'Rigify': print(module) addon_utils.enable(module.name)

but it fails with the traceback:

<module 'rigify' from 'C:\\Program Files\\Blender Foundation\\Blender 2.93\\2.93\\scripts\\addons\\rigify\\__init__.py'>
Exception in module register(): C:\Program Files\Blender Foundation\Blender 2.93\2.93\scripts\addons\rigify\__init__.py
Traceback (most recent call last):
  File "C:\Program Files\Blender Foundation\Blender 2.93\2.93\scripts\modules\addon_utils.py", line 386, in enable
    mod.register()
  File "C:\Program Files\Blender Foundation\Blender 2.93\2.93\scripts\addons\rigify\__init__.py", line 622, in register
    if legacy_loaded or bpy.context.preferences.addons['rigify'].preferences.legacy_mode:
KeyError: 'bpy_prop_collection[key]: key "rigify" not found'

after which it is impossible to even manually enable rigify, for a different error that seems to imply that the first attempt partially succeeded.

I have manually verified that rigify is installed, and that if I manually enable it it works fine.

I have also looked at the output of the first two for loops and found rigify in the first output when it is enabled, but not when it is disabled, as expected. It also appears in the second output as expected.

This is probably a bug in addon_utils, but if so, my question is: how do I work around the bug and enable rigify from python? And if it's not a bug, then my question is: why doesn't the second script work?

I'll file a bug report, but addon_utils isn't a supported API, so it will probably be closed.

Marty Fouts
  • 33,070
  • 10
  • 35
  • 79

2 Answers2

3

addon_utils.enable by default runs the addon code as if you pasted it in the text editor and hit run: it runs the register function and you can use the addon, but it doesn't change the check boxes in Preferences>Addons or create an entry in bpy.context.preferences.addons or anything.

However, it appears that Rigify cannot be run like this. It always assumes it has an entry in bpy.context.preferences.addons['rigify']. That means the only way to enable it is to enable it by default in the preferences. You can ask addon_utils.enable to do this for you by passing default_set=True.

So this works (also note that the name to pass is rigify, not Rigify):

import bpy
import addon_utils

addon = bpy.context.preferences.addons.get('rigify')

if not addon: # Rigify requires default_set=True addon_utils.enable('rigify', default_set=True)

So this is actually caused by Rigify, not addon_utils.

scurest
  • 10,349
  • 13
  • 31
3

Why not use bpy.ops.preferences.addon_enable(module="") ?

import bpy

addon = bpy.context.preferences.addons.get('rigify')

if not addon: bpy.ops.preferences.addon_enable(module="rigify") else: bpy.ops.preferences.addon_disable(module="rigify")

relaxed
  • 2,267
  • 6
  • 15
  • The only reason not to do it this way is probably a weak one: bpy.ops can be slower than other approaches. It probably doesn't matter in this case. – Marty Fouts Nov 11 '21 at 14:41