@bdamay said:
OK i think i get it . I shouldn't try to reregister PropertyGroup - i will investigate why i get this class from inspecting submodule
Indeed there is no need to unregister the default Blender classes such as bpy.types.PropertyGroup, bpy.types.Operator, only their subclasses.
Sometimes they may get imported in module namespace, e.g. with from bpy.types import PropertyGroup.
Moving forward, i reduced the inspect scope to fit class definitions on the actual submodule inspected and got rid of most of errors i encountered so far, but not all if i widen the scope
I'm still having problems with some classes that fails to reregister . Here's one example with BIMProjectProperties from blenderbim.bim.module.project.prop module
>>> cl = blenderbim.bim.module.project.prop.BIMProjectProperties
>>> bpy.utils.unregister_class(cl)
>>> bpy.utils.register_class(cl)
TypeError: CollectionProperty(...): expected an RNA type, failed with: RuntimeError: , missing bl_rna attribute from 'RNAMetaPropGroup' instance (may not be registered)
Traceback (most recent call last):
File "<blender_console>", line 1, in <module>
ValueError: bpy_struct "BIMProjectProperties" registration error: 'library_elements' CollectionProperty could not register (see previous error)
I have to leave it for now, but i pushed the code on github here if you want to test it. (https://github.com/bdamay/bbim-reload-addon)
I added the hability to fill a custom basename for modules in case it is needed to reload from blenderbim.bim.tools.
@bdamay said:
I'm still having problems with some classes that fails to reregister . Here's one example with BIMProjectProperties from blenderbim.bim.module.project.prop module
Tried to run the code below in the fresh Blender session and there are no errors.
From your error description it seems there is a problem with library_elements ('library_elements' CollectionProperty could not register (see previous error)), I guess it's because it's a CollectionProperty that's using other PropertyGroup as it's type - LibraryElement. So, in that case LibraryElement should be reregistered first.
I ran it my self on fresh start and there is no errors, you're right.
But, it looks like something breaks into blenderbim anyway as the class doesn't seem to be properly registered.
Once the lines have been executed (without errors), i tried to start a fresh ifc project - and ther it fails with lots of errors regarding project property class.
To make Blender BIM work again i needed to unactivate reactivate the whole BlenderBIM add-on. Looks like i'm not really getting nowhere safe. :-(
@bdamay said:
I ran it my self on fresh start and there is no errors, you're right.
But, it looks like something breaks into blenderbim anyway as the class doesn't seem to be properly registered.
Once the lines have been executed (without errors), i tried to start a fresh ifc project - and ther it fails with lots of errors regarding project property class.
It's hard to tell what's the issue, need some isolated example to reproduce this.
Well the good thing is for 2 cases at least (demo, project.operator) the plugin looks like working fine. It might be useful anyway.
I might have been to hungry willing for more, there are sure things i don't understand enough yet to achieve this.
Thanks for your kind help
@bdamay I think there is a bug, the code below (from here) will never reload more than 1 class since during reloading of the 1st class it will reload the module and the next class will be retrieved from already reloaded module in cl = getattr(module, cn) and cl.is_registered will always be False, so no other classes will be reloaded.
# reregistering classes
for cn in class_names:
cl = getattr(module, cn)
if hasattr(cl, 'is_registered'):
if cl.is_registered and module_name == cl.__module__:
bpy.utils.unregister_class(cl)
importlib.reload(module)
cl = getattr(module, cn)
bpy.utils.register_class(cl)
print('- Registered Class', cn)
You can reproduce it by running the addon with basename blenderbim.bim.module and module cost.ui, the output will contain just 1 class though there are 11 Blender based classes present in this module (5 Panels and 6 UILists):
Well, you're trying to unregister classes that are not derived from a blender class. So it's missing a bunch of stuff the unregister function is looking for. That is my first guess.
Yes. That is for deregistering a Blender operator. i.e. something derived using for example: class ActivateModel(bpy.types.Operator):
In the svgwriter.py file are two classes: class SvgWriter:
and class External(svgwrite.container.Group):
Neither of these get registered with Blender, so you cannot unregister them. In the for class_name in classes: loop there should be a test to ensure the class is a blender class. This assumes you are wanting to refresh other things. If you're just refreshing svgwriter then you should just remove that for loop as it isn't appropriate. [Correction] Add the test in both for loops, or remove both for loops if just poking SvgWriter.
Is it just the SVGWriter you are changing? If so, just delete the two for loops - you don't need them. If you are wanting to do multiple modules that could contain items that are and are not blender types, then you'll need something like (warning! untested code ;-):
for class_name in classes:
class_obj = getattr(module, class_name)
if class_obj.__class__.__name__ == 'RNAMeta':
bpy.utils.unregister_class(class_obj)
and
for class_name in classes:
class_obj = getattr(module, class_name)
if class_obj.__class__.__name__ == 'RNAMeta':
bpy.utils.register_class(class_obj)
@theoryshaw said:
That kinda makes sense.
Not sure how to modify the script.
Basically looking to not have to restart blender every time. :)
@sjb007 is correct, SvgWriter is not Blender class, so there is no need to register/unregister it. You need to importlib.reloadsvgwriter module and reregister Blender operators that are going to use updated SvgWriter (operator CreateDrawing), so they can pick up reloaded class reference.
Thank you both! This shaves hours. :)
Tweaked with a little AI help...
import importlib
import bpy
# Dictionary of modules with Blender-specific classes to reregister
reregister_classes = {
"bonsai.bim.module.drawing.svgwriter": ("SvgWriter", ), # Update as needed
}
for module_name, classes in reregister_classes.items():
module = importlib.import_module(module_name)
# Only try to unregister/register classes that are Blender types
for class_name in classes:
class_obj = getattr(module, class_name)
if hasattr(class_obj, 'bl_rna'): # Check if it's a Blender class
bpy.utils.unregister_class(class_obj)
importlib.reload(module)
for class_name in classes:
class_obj = getattr(module, class_name)
if hasattr(class_obj, 'bl_rna'): # Check if it's a Blender class
bpy.utils.register_class(class_obj)
bl_info = {
"name": "Reload Multiple Modules Tool",
"blender": (2, 80, 0),
"category": "Development",
}
import bpy
import importlib
# Define a Property Group for each module-class pair
class ReloadModuleClassPair(bpy.types.PropertyGroup):
module_name: bpy.props.StringProperty(name="Module Name")
class_name: bpy.props.StringProperty(name="Class Name")
# Operator to reload the modules
class RELOADMULTIPLEMODULES_OT_ReloadModules(bpy.types.Operator):
"""Reload the specified modules and classes"""
bl_idname = "reloadmultiplemodules.reload_modules"
bl_label = "Reload Modules"
def execute(self, context):
props = context.scene.reload_multiple_modules_tool_props
for pair in props.module_class_pairs:
module_name = pair.module_name.strip()
class_name = pair.class_name.strip()
if not module_name or not class_name:
continue
try:
# Import the module
module = importlib.import_module(module_name)
# Get the class object from the module
class_obj = getattr(module, class_name)
# Unregister if it's a Blender type (e.g., bpy.types.Operator, Panel)
if hasattr(class_obj, 'bl_rna'):
bpy.utils.unregister_class(class_obj)
# Reload the module
importlib.reload(module)
# Get the refreshed class object
class_obj = getattr(module, class_name)
# Register if it's a Blender type
if hasattr(class_obj, 'bl_rna'):
bpy.utils.register_class(class_obj)
self.report({'INFO'}, f"Reloaded {class_name} from {module_name}")
except Exception as e:
self.report({'ERROR'}, f"Failed to reload {class_name} from {module_name}: {e}")
return {'FINISHED'}
# Panel to show the interface for adding modules and classes
class RELOADMULTIPLEMODULES_PT_Panel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Reload Multiple Modules Tool"
bl_idname = "RELOADMULTIPLEMODULES_PT_panel"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = 'Development'
def draw(self, context):
layout = self.layout
props = context.scene.reload_multiple_modules_tool_props
# Display the module-class pairs with a dynamic UI
for i, pair in enumerate(props.module_class_pairs):
row = layout.row()
row.prop(pair, "module_name")
row.prop(pair, "class_name")
# Add button to add a new pair
layout.operator("reloadmultiplemodules.add_module_class_pair", text="Add Module-Class Pair")
# Reload button
layout.operator("reloadmultiplemodules.reload_modules", text="Reload Modules")
# Operator to add a new module-class pair
class RELOADMULTIPLEMODULES_OT_AddModuleClassPair(bpy.types.Operator):
"""Add a new module-class pair"""
bl_idname = "reloadmultiplemodules.add_module_class_pair"
bl_label = "Add Module-Class Pair"
def execute(self, context):
props = context.scene.reload_multiple_modules_tool_props
# Add a new entry to the list
props.module_class_pairs.add()
return {'FINISHED'}
# The PropertyGroup for the scene to hold the list of module-class pairs
class ReloadMultipleModulesToolProperties(bpy.types.PropertyGroup):
module_class_pairs: bpy.props.CollectionProperty(type=ReloadModuleClassPair)
def register():
bpy.utils.register_class(ReloadModuleClassPair)
bpy.utils.register_class(RELOADMULTIPLEMODULES_OT_ReloadModules)
bpy.utils.register_class(RELOADMULTIPLEMODULES_PT_Panel)
bpy.utils.register_class(RELOADMULTIPLEMODULES_OT_AddModuleClassPair)
bpy.utils.register_class(ReloadMultipleModulesToolProperties)
bpy.types.Scene.reload_multiple_modules_tool_props = bpy.props.PointerProperty(type=ReloadMultipleModulesToolProperties)
def unregister():
bpy.utils.unregister_class(ReloadModuleClassPair)
bpy.utils.unregister_class(RELOADMULTIPLEMODULES_OT_ReloadModules)
bpy.utils.unregister_class(RELOADMULTIPLEMODULES_PT_Panel)
bpy.utils.unregister_class(RELOADMULTIPLEMODULES_OT_AddModuleClassPair)
bpy.utils.unregister_class(ReloadMultipleModulesToolProperties)
del bpy.types.Scene.reload_multiple_modules_tool_props
if __name__ == "__main__":
register()
@theoryshaw@Andrej730 said it, but maybe didn't emphasize enough... Order matters. Suggestion for your UI would be to add deletion of pairs, and the ability to order the classes. An alternative brute force would be to run the reload loop twice. That way order wouldn't matter, because everything would be up-to-date for the second go around.
@sjb007 said: @theoryshaw@Andrej730 said it, but maybe didn't emphasize enough... Order matters. Suggestion for your UI would be to add deletion of pairs, and the ability to order the classes. An alternative brute force would be to run the reload loop twice. That way order wouldn't matter, because everything would be up-to-date for the second go around.
Thanks @sjb007.
ping @bdamay. I wonder if this was the cause of some of the problems you were experiencing?
Comments
Indeed there is no need to unregister the default Blender classes such as
bpy.types.PropertyGroup
,bpy.types.Operator
, only their subclasses.Sometimes they may get imported in module namespace, e.g. with
from bpy.types import PropertyGroup
.Moving forward, i reduced the inspect scope to fit class definitions on the actual submodule inspected and got rid of most of errors i encountered so far, but not all if i widen the scope
I'm still having problems with some classes that fails to reregister . Here's one example with BIMProjectProperties from blenderbim.bim.module.project.prop module
@Andrej730 do you have an idea ?
I have to leave it for now, but i pushed the code on github here if you want to test it. (https://github.com/bdamay/bbim-reload-addon)

I added the hability to fill a custom basename for modules in case it is needed to reload from blenderbim.bim.tools.
Tried to run the code below in the fresh Blender session and there are no errors.
From your error description it seems there is a problem with
library_elements
('library_elements' CollectionProperty could not register (see previous error)), I guess it's because it's a CollectionProperty that's using other PropertyGroup as it's type - LibraryElement. So, in that case LibraryElement should be reregistered first.So, the way to reproduce this error is more like:
@Andrej730 said:
I ran it my self on fresh start and there is no errors, you're right.

But, it looks like something breaks into blenderbim anyway as the class doesn't seem to be properly registered.
Once the lines have been executed (without errors), i tried to start a fresh ifc project - and ther it fails with lots of errors regarding project property class.
To make Blender BIM work again i needed to unactivate reactivate the whole BlenderBIM add-on. Looks like i'm not really getting nowhere safe. :-(
It's hard to tell what's the issue, need some isolated example to reproduce this.
Well the good thing is for 2 cases at least (demo, project.operator) the plugin looks like working fine. It might be useful anyway.
I might have been to hungry willing for more, there are sure things i don't understand enough yet to achieve this.
Thanks for your kind help
@bdamay I think there is a bug, the code below (from here) will never reload more than 1 class since during reloading of the 1st class it will reload the module and the next class will be retrieved from already reloaded module in
cl = getattr(module, cn)
andcl.is_registered
will always beFalse
, so no other classes will be reloaded.You can reproduce it by running the addon with basename
blenderbim.bim.module
and modulecost.ui
, the output will contain just 1 class though there are 11 Blender based classes present in this module (5 Panels and 6 UILists):noobie alert.
ran...
got this error.
Well, you're trying to unregister classes that are not derived from a blender class. So it's missing a bunch of stuff the unregister function is looking for. That is my first guess.
Is relative to @Andrej730 nifty script. Probably botching how to use it.
Yes. That is for deregistering a Blender operator. i.e. something derived using for example:
class ActivateModel(bpy.types.Operator):
In the svgwriter.py file are two classes:
class SvgWriter:
and
class External(svgwrite.container.Group):
Neither of these get registered with Blender, so you cannot unregister them. In the
for class_name in classes:
loop there should be a test to ensure the class is a blender class. This assumes you are wanting to refresh other things. If you're just refreshing svgwriter then you should just remove that for loop as it isn't appropriate. [Correction] Add the test in both for loops, or remove both for loops if just poking SvgWriter.That kinda makes sense.
Not sure how to modify the script.
Basically looking to not have to restart blender every time. :)
Is it just the SVGWriter you are changing? If so, just delete the two for loops - you don't need them. If you are wanting to do multiple modules that could contain items that are and are not blender types, then you'll need something like (warning! untested code ;-):
and
@sjb007 is correct,
SvgWriter
is not Blender class, so there is no need to register/unregister it. You need toimportlib.reload
svgwriter
module and reregister Blender operators that are going to use updatedSvgWriter
(operatorCreateDrawing
), so they can pick up reloaded class reference.Thank you both! This shaves hours. :)
Tweaked with a little AI help...
Unabashed use of AI. :)
@theoryshaw @Andrej730 said it, but maybe didn't emphasize enough... Order matters. Suggestion for your UI would be to add deletion of pairs, and the ability to order the classes. An alternative brute force would be to run the reload loop twice. That way order wouldn't matter, because everything would be up-to-date for the second go around.
Thanks @sjb007.
ping @bdamay. I wonder if this was the cause of some of the problems you were experiencing?
I have a fork with some fixed issues, perhaps it can help - https://github.com/Andrej730/bbim-reload-addon

E.g. you can reload svgwriter and drawing operators like this: