Example #1
0
 def _dyn_owner_apply(draw_func):
     from _bpy import _bl_owner_id_get
     owner_id = _bl_owner_id_get()
     if owner_id is not None:
         draw_func._owner = owner_id
Example #2
0
 def _dyn_owner_apply(draw_func):
     from _bpy import _bl_owner_id_get
     owner_id = _bl_owner_id_get()
     if owner_id is not None:
         draw_func._owner = owner_id
Example #3
0
def enable(module_name,
           *,
           default_set=False,
           persistent=False,
           handle_error=None):
    """
    Enables an addon by name.

    :arg module_name: the name of the addon and module.
    :type module_name: string
    :arg default_set: Set the user-preference.
    :type default_set: bool
    :arg persistent: Ensure the addon is enabled for the entire session (after loading new files).
    :type persistent: bool
    :arg handle_error: Called in the case of an error, taking an exception argument.
    :type handle_error: function
    :return: the loaded module or None on failure.
    :rtype: module
    """

    import os
    import sys
    from bpy_restrict_state import RestrictBlend

    if handle_error is None:

        def handle_error(_ex):
            import traceback
            traceback.print_exc()

    # reload if the mtime changes
    mod = sys.modules.get(module_name)
    # chances of the file _not_ existing are low, but it could be removed
    if mod and os.path.exists(mod.__file__):

        if getattr(mod, "__addon_enabled__", False):
            # This is an unlikely situation,
            # re-register if the module is enabled.
            # Note: the UI doesn't allow this to happen,
            # in most cases the caller should 'check()' first.
            try:
                mod.unregister()
            except Exception as ex:
                print(
                    "Exception in module unregister():",
                    repr(getattr(mod, "__file__", module_name)),
                )
                handle_error(ex)
                return None

        mod.__addon_enabled__ = False
        mtime_orig = getattr(mod, "__time__", 0)
        mtime_new = os.path.getmtime(mod.__file__)
        if mtime_orig != mtime_new:
            import importlib
            print("module changed on disk:", repr(mod.__file__),
                  "reloading...")

            try:
                importlib.reload(mod)
            except Exception as ex:
                handle_error(ex)
                del sys.modules[module_name]
                return None
            mod.__addon_enabled__ = False

    # add the addon first it may want to initialize its own preferences.
    # must remove on fail through.
    if default_set:
        _addon_ensure(module_name)

    # Split registering up into 3 steps so we can undo
    # if it fails par way through.

    # Disable the context: using the context at all
    # while loading an addon is really bad, don't do it!
    with RestrictBlend():

        # 1) try import
        try:
            mod = __import__(module_name)
            if mod.__file__ is None:
                # This can happen when the addon has been removed but there are
                # residual `.pyc` files left behind.
                raise ImportError(name=module_name)
            mod.__time__ = os.path.getmtime(mod.__file__)
            mod.__addon_enabled__ = False
        except Exception as ex:
            # if the addon doesn't exist, don't print full traceback
            if type(ex) is ImportError and ex.name == module_name:
                print("addon not found:", repr(module_name))
            else:
                handle_error(ex)

            if default_set:
                _addon_remove(module_name)
            return None

        # 1.1) Fail when add-on is too old.
        # This is a temporary 2.8x migration check, so we can manage addons that are supported.

        if mod.bl_info.get("blender", (0, 0, 0)) < (2, 80, 0):
            if _bpy.app.debug:
                print(
                    "Warning: Add-on '%s' was not upgraded for 2.80, ignoring"
                    % module_name)
            return None

        # 2) Try register collected modules.
        # Removed register_module, addons need to handle their own registration now.

        from _bpy import _bl_owner_id_get, _bl_owner_id_set
        owner_id_prev = _bl_owner_id_get()
        _bl_owner_id_set(module_name)

        # 3) Try run the modules register function.
        try:
            mod.register()
        except Exception as ex:
            print(
                "Exception in module register():",
                getattr(mod, "__file__", module_name),
            )
            handle_error(ex)
            del sys.modules[module_name]
            if default_set:
                _addon_remove(module_name)
            return None
        finally:
            _bl_owner_id_set(owner_id_prev)

    # * OK loaded successfully! *
    mod.__addon_enabled__ = True
    mod.__addon_persistent__ = persistent

    if _bpy.app.debug_python:
        print("\taddon_utils.enable", mod.__name__)

    return mod