Ok, here’s how I would do it:
import importlib
import inspect
from pathlib import Path
import bpy
from bpy.props import BoolProperty
from bpy.types import AddonPreferences
bl_info = {
"name": "auto_load_prefs",
"author": "Andrew Stevenson",
"description": "",
"blender": (2, 80, 0),
"version": (0, 0, 1),
"location": "",
"warning": "",
"category": "Generic"
}
def get_preferences_classes():
"""Return a list of all addon preferences classes defined in files in the current directory."""
prefs_classes = []
# Iterate through all files in the current directory
directory = Path(__file__).parent
for file in directory.iterdir():
# Don't include this file, or non python files
if file == Path(__file__) or file.suffix != ".py":
continue
# Import the module, the same syntax as 'import .module'
module = importlib.import_module("." + file.stem, package=__package__)
# Iterate through all of the attributes in that module, check if they are addon preferences, and if so, append them.
for attr in dir(module):
attr = getattr(module, attr)
if inspect.isclass(attr) and issubclass(attr, AddonPreferences):
prefs_classes.append(attr)
return prefs_classes
prefs_classes = get_preferences_classes()
# Inherit from all of the gathered classes into a single preferences class, combining all of their attributes.
# This will error if there are no prefs classes, so you might want to account for that.
class AllPrefs(*prefs_classes):
bl_idname = __package__
all_prefs_prop: BoolProperty(name="This property is only in all preferences")
def draw(self, context):
# Iterate through the classes and draw them
# Turns out you don't need super here, you can just use the list of classes
for cls in prefs_classes:
if hasattr(cls, "draw"):
cls.draw(self, context)
def register():
bpy.utils.register_class(AllPrefs)
def unregister():
bpy.utils.unregister_class(AllPrefs)
And in another module with it’s own preferences:
import bpy
from bpy.props import StringProperty
class PrefsA(bpy.types.AddonPreferences):
bl_idname = __name__
prop_a: StringProperty(name="Prefs A",)
def draw(self, context):
self.layout.label(text="PrefsA")
def register():
bpy.utils.register_class(PrefsA)
def unregister():
bpy.utils.unregister_class(PrefsA)
I’m not sure for certain what’s going wrong with your version, but It looks like it’s probably something to do with the fact that the class is being defined before the list of addon preferences has been populated by the init function, and so it’s not technically a preferences class itself when it gets registered.
Hope that helps!