Skip to content

Automatic module installation via pip, handling exceptions, configurable output printing in Blender addons.

License

Notifications You must be signed in to change notification settings

theres1/Dependency-Handler-for-Blender-Addons

Repository files navigation

Dependency-Handler-for-Blender-Addons

Automatic module installation via pip, handling exceptions, configurable output printing in Blender addons.

Real time logging

Dependency GUI

Module that allows easy handling of dependencies, created mainly for Blender add-ons.

Usage Examples:

Import output printing front-ends:

    from . dependency_handler.blender_printer import BlenderPrinter
    from . dependency_handler import FilePrinter

BlenderPrinter - creates a new Blender window with Text Editor and writes logs into text file. FilePrinter - writes logs into text file. By default, text file is created next to __file__.

    from . import dependency_handler
    from . dependency_handler import FROM, IMPORT

Initialise dependencies. Already installed modules will be imported during initialisation.

    dependency_handler.init([('PIL', 'Pillow'), 'AnyModule'], module_globals=globals(), printers=[BlenderPrinter("Dependency Log of My Addon"), FilePrinter()])
    FROM(('PIL', 'Pillow', ("9.2.0",))).IMPORT('Image', 'ImageCms')
    IMPORT('AnyModule2')
    IMPORT(('AnyModule3', ("1.0.1", "1.5.0")))

Dependencies can be initialised by init, FROM and IMPORT functions. Use tuple (module_name [ , pip_name ] [ , (min_version, max_version) ] ) for modules that need different names for pip installing and importing or specific version. Pass globals() as a module_globals parameter to import modules into global namespace. State of all dependencies can be tracked by dependency_handler.check_all_loaded() function returning True if all dependencies are imported.

    DEPS_IMPORTED = dependency_handler.check_all_loaded()

Another option is to track returns of initialisation functions:

    DEPS_IMPORTED = dependency_handler.init(['AnyModule'], module_globals=globals())
    DEPS_IMPORTED &= FROM(('PIL', 'Pillow')).IMPORT('ImageCms', 'Image')
    DEPS_IMPORTED &= IMPORT('Non-Existing-Module')

It is also possible to use dependency_handler.DEPENDENCIES_IMPORTED variable that is updated by install_all(), install_all_generator() and check_all_loaded() functions. Modules loaded into global namespace are freely available but are not visible to code completion. To make them accessible, import them once again like this:

    if dependency_handler.DEPENDENCIES_IMPORTED:
        import AnyModule
        from PIL import ImageCms, Image

Missing modules can be installed in a time of your choosing like this:

    DEPS_IMPORTED = dependency_handler.install_all()
    # or use a generator function
    for _ in dependency_handler.install_all_generator():
        do_something_between_lines()

install_all()/install_all_generator() function starts generating logs that will be presented in chosen front-ends.

Blender specific usage

Use blender_printer.install_operator_factory() to create an operator that will handle drawing logs in real time. Blender will be responsive during modules installation and pip logs will be printed immediately in new window. Use blender_printer.gui_operators_factory() and blender_printer.create_gui() to generate GUI.

class PREFS_PT_DepAddonExample(bpy.types.AddonPreferences):
    bl_idname = __package__
    
    # Add these optional properties to the addon preferences, if you want these functionalities turned on.
    # Check-for-updates-on-start and pop-up notification will be disabled without them.
    dependencies_check_on_start: bpy.props.BoolProperty(default=False, name="Check for module updates on start")
    dependencies_show_popup: bpy.props.BoolProperty(default=False, name="Show pop-up notification.")
    
    def draw(self, context):
        layout = self.layout
        layout.operator(OT_ThreadedInstall.bl_idname)
        blender_printer.create_gui(layout, *gui_ops)

# Create operator that will handle drawing logs in real time.
# Blender will be responsive during modules installation and pip logs will be printed immediately in new window.
OT_ThreadedInstall = install_operator_factory(bl_info['name'])

# If you want to use dependencies GUI, generate a tuple with operators
gui_ops = gui_operators_factory(bl_info['name'])

# Check for available updates to installed packages (for GUI).
# GUI operators tuple needs to be passed if aformentioned AddonPreferences properties are set
check_module_upgrades_thread(gui_ops_tuple=gui_ops)
Real time log

Pass BlenderPrinter object to init enable real time logging in new window. Logging

Update notification

Update notification

Add dependencies_check_on_start and dependencies_show_popup properties to the addon preferences to enable auto-update-check and update notification pop-up on start. Two switches to control these will also become available in the generated GUI.

class PREFS_PT_DepAddonExample(bpy.types.AddonPreferences):
    dependencies_check_on_start: bpy.props.BoolProperty(default=False, name="Check for module updates on start")
    dependencies_show_popup: bpy.props.BoolProperty(default=False, name="Show pop-up notification.")
Update

Update all or selected modules in non-blocking UI.

Search for updates Search for updates Update Update all or selected

Change version

Change installed version of choosen module in non-blocking UI.

Change version

Example addon

This repository can also function as an addon. Download it as a zip and install in Blender. Code of the example addon is in the __file__.py of the root dir.

==============================

Gifs on this page were edited and rendered in Blender using Styriam ICC Image Compressor addon.

About

Automatic module installation via pip, handling exceptions, configurable output printing in Blender addons.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages