1
$\begingroup$

I am developing an add-on, which only works if some specific conditions are satisfied (e.g. some other add-on is installed). Hence, I want the user to be unable to register this add-on if the conditions are not satisfied.

I thought I can ensure the conditions during the register() function. If the conditions are not satisfied, I want Blender to cancel the add-on registering, while displaying a message, saying what the user has to do.

I figured out how to display the message following https://blender.stackexchange.com/a/118183/117198

def display_error(message):
    display_text = lambda self, context: self.layout.label(text = message)
    bpy.context.window_manager.popup_menu(display_text, title='Error', icon='ERROR')

However, I don't know how to properly cancel the add-on registering. I figured that raising an error would cancel registering, but it displays the traceback, which is not user-friendly.

def register():
    if not my_conditions:
        raise Exception("The conditions were not met.")
    else:
        # Continue register
Traceback (most recent call last):
  File "C:\Program Files\Blender Foundation\Blender 2.90\2.90\scripts\modules\addon_utils.py", line 382, in enable
    mod.register()
  File "C:\Users\VirtualUser\AppData\Roaming\Blender Foundation\Blender\2.90\scripts\addons\my_addon.py", line 116, in register
    raise Exception("The conditions were not met.")
Exception: The conditions were not met.

Is there a proper way to cancel add-on registering? Alternatively, is there a way to hide the traceback?

$\endgroup$
3
  • 1
    $\begingroup$ Why not silently close the registration if it fails ? if not my_conditions: pass else: register() $\endgroup$ – Gorgious Feb 25 at 12:52
  • $\begingroup$ @Gorgious this way Blender shows the module as registered/enabled, but I want it to stay disabled. $\endgroup$ – Dominykas Ruibys Feb 26 at 10:14
  • $\begingroup$ There is an operator bpy.ops.preferences.addon_disable(module="module_name"), but you can't call it from register function. Best I can think of is running this when you try to use the addon, but don't meet the required condition. $\endgroup$ – Roki Podpecan Feb 28 at 21:06
2
$\begingroup$

Some alternatives.

I am not sure what you ask is possible without some serious dicking around.

If these are bundled addons can simply enable and disable them as required in your code https://blender.stackexchange.com/a/58208/15543 In that you can enable an addon when required eg https://blender.stackexchange.com/a/189435/15543

Use a different Preferences if missing dependencies.

enter image description here

As it happens, am currently writing an addon prefs class to display any missing import dependencies.

Here is a "fudge-together" to show the warning message and suggest that the user investigate the addon on prefs. The addon checks if the cell fracture addon is present and enabled, if present but not enabled puts a button in prefs to enable it.

Could add a big "Retry" button to check again.

bl_info = {
    "name": "Test Deps",
    "author": "Your Name Here",
    "version": (1, 0),
    "blender": (2, 80, 0),
    "location": "View3D > Add > Mesh > New Object",
    "description": "Adds a new Mesh Object",
    "warning": "",
    "doc_url": "",
    "category": "Add Mesh",
}

import bpy
import addon_utils
from bpy.types import AddonPreferences

deps = ["object_fracture_cell"]   

class AddonDepsPrefs(AddonPreferences):
    bl_idname = __name__
    bl_label = "Missing Deps"
    def draw(self, context):
        layout = self.layout
        layout.label(text="Errors Registerning")
        fake_mods = addon_utils.addons_fake_modules
        for dep in deps:
            if dep in fake_mods:
                if not addon_utils.check(dep)[1]:
                    op = layout.operator("preferences.addon_enable")
                    op.module = dep                 

def register():

    fake_modules = addon_utils.fake_modules
    all_exist = all((dep in fake_modules) for dep in deps)
    all_enabled = all(addon_utils.check(dep)[1] for dep in deps)
    satisfied = all_exist and all_enabled
    if not satisfied:
        bpy.utils.register_class(AddonDepsPrefs)
        #unregister()    
        def display_error(message):
            display_text = lambda self, context: self.layout.label(text = message)
            bpy.context.window_manager.popup_menu(display_text, title='Error', icon='ERROR')
        display_error("Expand Addon Prefs for Details")
        

def unregister():
    if AddonDepsPrefs.is_registered:
        bpy.utils.unregister_class(AddonDepsPrefs)



if __name__ == "__main__":
    register()
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.