OSArch Community

VScode and JacquesLucke's blender_vscode

  1. B

    Hi @Andrej730 ,

    Thank you very much for your help. I suspected something like this but didn't have time to dig further, (and i'm not yet very much familiar with blender api). What you say is insightful.

    I already made a try with the is_registered attribute but still have errors i have to investigate. (I guess it's because i'm unregistering the class, not blender name ?)

    If i may summarize the way i understand it:

    • I inspect all submodules and find submodules and finally classes with their 'python' Class names.

    • i can check if the class is Blender registered by evaluating "is_registered" attribute

    • if it is registered i should the then call unregister followed by register on that Class

    What i may not be sure is that if i call bpy.utils.unregister_class(class_obj) with a reference to the "python" class, will the api unregister the class properly ? or is there a way for me to get to the "Blender" name coming from "python" Class name ?

    (bl_name may be?

    I can't test this right away, as i'm not home, and don't have blender, but hopefully i'll do it tonight )

  2. A

    @bdamay said:

    What i may not be sure is that if i call bpy.utils.unregister_class(class_obj) with a reference to the "python" class, will the api unregister the class properly ? or is there a way for me to get to the "Blender" name coming from "python" Class name ?

    (bl_name may be?

    I can't test this right away, as i'm not home, and don't have blender, but hopefully i'll do it tonight )

    Either way if you do unregister(blenderbim.CreateProject) or unregister(bpy.types.BlenderPostProcesedName) it will do exactly the same as blenderbim.CreateProject is the same class object as bpy.types.BlenderPostProcesedName, just stored in different modules - one in blenderbim and other in bpy.types.

  3. B

    Hi @Andrej730 , i took a look on the reload script feature. I still have issues on certain classes, that i appear to unregister right but can't register again. with a 'missing bl_rna attribute... ' message. (see below)

    That, i don't know what to do with, as it makes the all script really unsafe (as in the end Classes are not available anymore at all).

    I surely misunderstand something, but may be you have a clue on what's happening here ?

    
    unregistering Class <class 'blenderbim.bim.module.demo.prop.BIMDemoProperties'>
    
    Reregistering Class <class 'blenderbim.bim.module.demo.prop.BIMDemoProperties'>
    
    Error: Python: Traceback (most recent call last):
    
      File "\bbim_reload_recursive.py", line 42, in <module>
    
      File "\bbim_reload_recursive.py", line 34, in reregister_modules_recursive
    
      File "\bbim_reload_recursive.py", line 19, in reregister_modules_recursive
    
    RuntimeError: register_class(...):, missing bl_rna attribute from 'RNAMetaPropGroup' instance (may not be registered)
    

    The code i run is this one:

    
    import bpy
    
    import importlib
    
    import inspect
    
    
    reregister_modules = ["blenderbim.bim.module.demo"]
    
    
    def reregister_modules_recursive(module_name):
    
        print('Module ', module_name)
    
        module = importlib.import_module(module_name)
    
        # retrieving registered classes with inspect
    
        classes = [c[1] for c in inspect.getmembers(module, inspect.isclass)] 
    
        # reregistering classes        
    
        for c in classes:            
    
            if hasattr(c, 'is_registered') and c.is_registered:
    
                print('unregistering Class', c , 'is_registered', c.is_registered)
    
                bpy.utils.unregister_class(c)
    
                print('Reregistering Class', c)
    
                bpy.utils.register_class(c)
    
    
    
        try:
    
            print('reloading ', module)
    
            importlib.reload(module)
    
        except Exception as e:
    
            print('error reimporting ', module, e)
    
    
        sub_modules=[]
    
        for n, sm in inspect.getmembers(module, inspect.ismodule): 
    
            # We should avoid reparsing upper modules here like bpy. so i check if sub module contains module name 
    
            if module_name in sm.__name__:                           
    
                sub_modules.append(sm.__name__) 
    
    
    
        for module_name in sub_modules:          
    
            reregister_modules_recursive(module_name)
    
    
    
    for module_name in reregister_modules:                   
    
        print('-'*60)
    
        print('Reregistering utility')
    
    
    
        reregister_modules_recursive(module_name)
    
        print('done')
    
        print('-'*60)
    
    
    
  4. A

    @bdamay said:

    Hi @Andrej730 , i took a look on the reload script feature. I still have issues on certain classes, that i appear to unregister right but can't register again. with a 'missing bl_rna attribute... ' message. (see below)

    Can you please narrow it down to some simple way to reproduce the issue? Something like this:

    
    import blenderbim.bim.module.demo.prop
    
    cl = blenderbim.bim.module.demo.prop.BIMDemoProperties
    
    bpy.utils.unregister_class(cl)
    
    bpy.utils.register_class(cl)
    
  5. B

    @Andrej730 said:

    import blenderbim.bim.module.demo.prop

    cl = blenderbim.bim.module.demo.prop.BIMDemoProperties

    bpy.utils.unregister_class(cl)

    bpy.utils.register_class(cl)

    I ran this in console and i don't get no error on BIMDemoProperties class, but i have on PropertyGroup one

    
    cl = blenderbim.bim.module.demo.prop.PropertyGroup
    
    bpy.utils.unregister_class(cl)
    
    bpy.utils.register_class(cl)
    

    gives

    
    Traceback (most recent call last):
    
      File "<blender_console>", line 1, in <module>
    
    RuntimeError: register_class(...):, missing bl_rna attribute from 'RNAMetaPropGroup' instance (may not be registered)
    
  6. B

    OK i think i get it . I shouldn't try to reregister PropertyGroup - i will investigate why i get this class from inspecting submodule

  7. A

    @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.

  8. B

    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) 
    

    @Andrej730 do you have an idea ?

  9. B

    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.

  10. A

    @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.

    
    import bpy
    
    import blenderbim
    
    cl = blenderbim.bim.module.project.prop.BIMProjectProperties
    
    bpy.utils.unregister_class(cl)
    
    bpy.utils.register_class(cl)
    

    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:

    
    import bpy
    
    import blenderbim
    
    cl = blenderbim.bim.module.project.prop.BIMProjectProperties
    
    bpy.utils.unregister_class(cl)
    
    bpy.utils.unregister_class(blenderbim.bim.module.project.prop.LibraryElement)
    
    bpy.utils.register_class(cl)
    
  11. B

    @Andrej730 said:

    Tried to run the code below in the fresh Blender session and there are no errors.

    import bpy

    import blenderbim

    cl = blenderbim.bim.module.project.prop.BIMProjectProperties

    bpy.utils.unregister_class(cl)

    bpy.utils.register_class(cl)

    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. :-(

  12. A

    @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.

  13. B

    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

  14. A

    @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):

    
    ------------------------------------------------------------
    
    Reregistering BBIM utility
    
    Module blenderbim.bim.module.cost.ui
    
    - Registered Class BIM_PT_Costing_Tools
    
    done
    
    ------------------------------------------------------------
    
  15. T

    noobie alert.

    ran...

    
    import importlib
    
    import bpy
    
    
    reregister_classes = {
    
        "bonsai.bim.module.drawing.svgwriter": ("SvgWriter", ),
    
    }
    
    
    for module_name, classes in reregister_classes.items():
    
        module = importlib.import_module(module_name)
    
        for class_name in classes:
    
            class_obj = getattr(module, class_name)
    
            bpy.utils.unregister_class(class_obj)
    
    
        importlib.reload(module)
    
    
        for class_name in classes:
    
            class_obj = getattr(module, class_name)
    
            bpy.utils.register_class(class_obj)
    

    got this error.

    
    Python: Traceback (most recent call last):
    
      File "D:\Dropbox\Troubleshooting\20241107 - fill-bg raster\20241107 - fill-bg raster.blend\Text", line 12, in <module>
    
    RuntimeError: unregister_class(...):, missing bl_rna attribute from 'type' instance (may not be registered)
    
    
  16. S

    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.

  17. T

    Is relative to @Andrej730 nifty script. Probably botching how to use it.

  18. S

    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.

  19. T

    That kinda makes sense.

    Not sure how to modify the script.

    Basically looking to not have to restart blender every time. :)

  20. S

    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)
    
  21. A

    @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.reload svgwriter module and reregister Blender operators that are going to use updated SvgWriter (operator CreateDrawing), so they can pick up reloaded class reference.

  22. T

    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)
    
    
  23. T

    Unabashed use of AI. :)

    
    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()
    
    
  24. S

    @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.

  25. T

    @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?

  1. Page 1
  2. 2
  3. 3

Login or Register to reply.