[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [30969] trunk/blender/release/scripts: update userpref's addon code to support new register/unregister, now the modules are parsed rather then being imported since it become quite tricky to import once without registering the classes , then again in a way that registered the existing modules classes without a reload () - which had problems too.

Campbell Barton ideasman42 at gmail.com
Mon Aug 2 09:50:59 CEST 2010


Revision: 30969
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=30969
Author:   campbellbarton
Date:     2010-08-02 09:50:58 +0200 (Mon, 02 Aug 2010)

Log Message:
-----------
update userpref's addon code to support new register/unregister, now the modules are parsed rather then being imported since it become quite tricky to import once without registering the classes, then again in a way that registered the existing modules classes without a reload() - which had problems too.

Modified Paths:
--------------
    trunk/blender/release/scripts/modules/bpy_types.py
    trunk/blender/release/scripts/ui/space_userpref.py

Modified: trunk/blender/release/scripts/modules/bpy_types.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy_types.py	2010-08-02 06:56:31 UTC (rev 30968)
+++ trunk/blender/release/scripts/modules/bpy_types.py	2010-08-02 07:50:58 UTC (rev 30969)
@@ -551,18 +551,18 @@
 # registers moduals instantly.
 _register_immediate = True
 
-def _unload_module(module):
+def _unload_module(module, free=True):
     for t in TypeMap.get(module, ()):
         bpy_types.unregister(t)
 
-    if module in TypeMap:
+    if free == True and module in TypeMap:
         del TypeMap[module]
 
 
     for t in PropertiesMap.get(module, ()):
         bpy_types.unregister(t)
 
-    if module in PropertiesMap:
+    if free == True and module in PropertiesMap:
         del PropertiesMap[module]
 
 def _load_module(module, force=False):

Modified: trunk/blender/release/scripts/ui/space_userpref.py
===================================================================
--- trunk/blender/release/scripts/ui/space_userpref.py	2010-08-02 06:56:31 UTC (rev 30968)
+++ trunk/blender/release/scripts/ui/space_userpref.py	2010-08-02 07:50:58 UTC (rev 30969)
@@ -814,13 +814,20 @@
     bl_label = "Addons"
     bl_region_type = 'WINDOW'
     bl_show_header = False
+    
+    _addons_fake_modules = {}
 
     def poll(self, context):
         userpref = context.user_preferences
         return (userpref.active_section == 'ADDONS')
 
     @staticmethod
+    def module_get(mod_name):
+        return USERPREF_PT_addons._addons_fake_modules[mod_name]
+
+    @staticmethod
     def _addon_list():
+        import os
         import sys
         import time
 
@@ -829,21 +836,99 @@
         paths = bpy.utils.script_paths("addons")
         # if folder addons_contrib/ exists, scripts in there will be loaded
         paths += bpy.utils.script_paths("addons_contrib")
-        
+
         if bpy.app.debug:
             t_main = time.time()
 
-        # sys.path.insert(0, None)
-        for path in paths:
-            # sys.path[0] = path
-            modules.extend(bpy.utils.modules_from_path(path, loaded_modules))
+        if 1:
+            # fake module importing
+            def fake_module(mod_name, mod_path):
+                import ast
+                ModuleType = type(ast)
+                data = open(mod_path, "r").read()
+                ast_data = ast.parse(data, filename=mod_path)
+                body_info = None
+                for body in ast_data.body:
+                    if body.__class__ == ast.Assign:
+                        if len(body.targets) == 1:
+                            if body.targets[0].id == "bl_addon_info":
+                                body_info = body
+                                break
+                
+                if body_info:
+                    mod = ModuleType(mod_name)
+                    mod.bl_addon_info = ast.literal_eval(body.value)
+                    mod.__file__ = mod_path
+                    mod.__time__ = os.path.getmtime(mod_path)
+                    return mod
+                else:
+                    return None
 
-        if bpy.app.debug:
-            print("Addon Script Load Time %.4f" % (time.time() - t_main))
 
-        # del sys.path[0]
-        return modules
+            modules_stale = set(USERPREF_PT_addons._addons_fake_modules.keys())
 
+            for path in paths:
+                for f in sorted(os.listdir(path)):
+                    if f.endswith(".py"):
+                        mod_name = f[0:-3]
+                        mod_path = os.path.join(path, f)
+                    elif ("." not in f) and (os.path.isfile(os.path.join(path, f, "__init__.py"))):
+                        mod_name = f
+                        mod_path = os.path.join(path, f, "__init__.py")
+                    else:
+                        mod_name = ""
+                        mod_path = ""
+
+                    if mod_name:
+                        if mod_name in modules_stale:
+                            modules_stale.remove(mod_name)
+                        mod = USERPREF_PT_addons._addons_fake_modules.get(mod_name)
+                        if mod:
+                            if mod.__time__ != os.path.getmtime(mod_path):
+                                print("Reloading", mod_name)
+                                del USERPREF_PT_addons._addons_fake_modules[mod_name]
+                                mod = None
+
+                        if mod is None:
+                            mod = fake_module(mod_name, mod_path)
+                            if mod:
+                                USERPREF_PT_addons._addons_fake_modules[mod_name] = mod
+                        
+            
+            # just incase we get stale modules, not likely
+            for mod_stale in modules_stale:
+                del USERPREF_PT_addons._addons_fake_modules[mod_stale]
+            del modules_stale
+            
+            return list(USERPREF_PT_addons._addons_fake_modules.values())
+        
+        else:
+            # never run this!, before it used ast
+            pass
+            '''
+            # note, this still gets added to _bpy_types.TypeMap
+            import bpy_types as _bpy_types
+            _bpy_types._register_override = True
+
+            # sys.path.insert(0, None)
+            for path in paths:
+                # sys.path[0] = path
+                modules.extend(bpy.utils.modules_from_path(path, loaded_modules))
+
+            if bpy.app.debug:
+                print("Addon Script Load Time %.4f" % (time.time() - t_main))
+
+            _bpy_types._register_override = False
+
+            # del sys.path[0]
+            return modules
+            '''
+        
+        
+        
+        
+        
+
     def draw(self, context):
         layout = self.layout
 
@@ -996,8 +1081,13 @@
     def execute(self, context):
         module_name = self.properties.module
 
+        # note, this still gets added to _bpy_types.TypeMap
+        import bpy_types as _bpy_types
+        _bpy_types._register_immediate = False
+
         try:
             mod = __import__(module_name)
+            bpy.utils._load_module(module_name)
             mod.register()
         except:
             import traceback
@@ -1012,7 +1102,9 @@
 
         if info.get("blender", (0, 0, 0)) > bpy.app.version:
             self.report("WARNING','This script was written for a newer version of Blender and might not function (correctly).\nThe script is enabled though.")
-
+        
+        _bpy_types._register_immediate = True
+        
         return {'FINISHED'}
 
 
@@ -1029,6 +1121,7 @@
 
         try:
             mod = __import__(module_name)
+            bpy.utils._unload_module(module_name, free=False) # dont free because we may want to enable again.
             mod.unregister()
         except:
             traceback.print_exc()
@@ -1118,7 +1211,8 @@
 
         # unlikely to fail, module should have already been imported
         try:
-            mod = __import__(module_name)
+            # mod = __import__(module_name)
+            mod = USERPREF_PT_addons.module_get(module_name)
         except:
             import traceback
             traceback.print_exc()





More information about the Bf-blender-cvs mailing list