[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [31823] trunk/blender/release/scripts: addon improvements/fixes

Campbell Barton ideasman42 at gmail.com
Wed Sep 8 09:30:20 CEST 2010


Revision: 31823
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=31823
Author:   campbellbarton
Date:     2010-09-08 09:30:20 +0200 (Wed, 08 Sep 2010)

Log Message:
-----------
addon improvements/fixes
- better error reporting when an addon fails to load
- upload an addon which loads partly but then fails (eg, module loads but class register fails)
- bugfix addon loading, failier to load would leave _bpy_types._register_immediate = False
- added which change on disk are reloaded when enabling.
- bpy.path.module_names() now returns (module_name, module_path) pairs.

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

Modified: trunk/blender/release/scripts/modules/bpy/path.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy/path.py	2010-09-08 04:55:37 UTC (rev 31822)
+++ trunk/blender/release/scripts/modules/bpy/path.py	2010-09-08 07:30:20 UTC (rev 31823)
@@ -183,7 +183,7 @@
     :type path: string
     :arg recursive: Also return submodule names for packages.
     :type recursive: bool
-    :return: a list of strings.
+    :return: a list of string pairs (module_name, module_file).
     :rtype: list
     """
 
@@ -193,13 +193,15 @@
 
     for filename in sorted(_os.listdir(path)):
         if filename.endswith(".py") and filename != "__init__.py":
-            modules.append(filename[0:-3])
+            fullpath = join(path, filename)
+            modules.append((filename[0:-3], fullpath))
         elif ("." not in filename):
             directory = join(path, filename)
-            if isfile(join(directory, "__init__.py")):
-                modules.append(filename)
+            fullpath = join(directory, "__init__.py")
+            if isfile(fullpath):
+                modules.append((filename, fullpath))
                 if recursive:
-                    for mod_name in module_names(directory, True):
-                        modules.append("%s.%s" % (filename, mod_name))
+                    for mod_name, mod_path in module_names(directory, True):
+                        modules.append(("%s.%s" % (filename, mod_name), mod_path))
 
     return modules

Modified: trunk/blender/release/scripts/modules/bpy/utils.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy/utils.py	2010-09-08 04:55:37 UTC (rev 31822)
+++ trunk/blender/release/scripts/modules/bpy/utils.py	2010-09-08 07:30:20 UTC (rev 31823)
@@ -70,7 +70,7 @@
 
     modules = []
 
-    for mod_name in _bpy.path.module_names(path):
+    for mod_name, mod_path in _bpy.path.module_names(path):
         mod = _test_import(mod_name, loaded_modules)
         if mod:
             modules.append(mod)

Modified: trunk/blender/release/scripts/modules/bpy_types.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy_types.py	2010-09-08 04:55:37 UTC (rev 31822)
+++ trunk/blender/release/scripts/modules/bpy_types.py	2010-09-08 07:30:20 UTC (rev 31823)
@@ -586,7 +586,8 @@
             bpy_types.register(t)
         except:
             import traceback
-            print("bpy.utils._register_module(): Module '%s' failed to register class '%s.%s'" % (module, t.__module__, t.__name__))
+            import sys
+            print("bpy.utils._register_module(): '%s' failed to register class '%s.%s'" % (sys.modules[module].__file__, t.__module__, t.__name__))
             traceback.print_exc()
 
 

Modified: trunk/blender/release/scripts/ui/space_userpref.py
===================================================================
--- trunk/blender/release/scripts/ui/space_userpref.py	2010-09-08 04:55:37 UTC (rev 31822)
+++ trunk/blender/release/scripts/ui/space_userpref.py	2010-09-08 07:30:20 UTC (rev 31823)
@@ -875,12 +875,12 @@
         modules_stale = set(USERPREF_PT_addons._addons_fake_modules.keys())
 
         for path in paths:
-            for mod_name in bpy.path.module_names(path):
+            for mod_name, mod_path in bpy.path.module_names(path):
                 modules_stale -= {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, mod.__time__, os.path.getmtime(mod_path), mod_path)
+                        print("reloading addon:", mod_name, mod.__time__, os.path.getmtime(mod_path), mod_path)
                         del USERPREF_PT_addons._addons_fake_modules[mod_name]
                         mod = None
 
@@ -1052,20 +1052,66 @@
         module_name = self.properties.module
 
         # note, this still gets added to _bpy_types.TypeMap
+
+        import sys
         import bpy_types as _bpy_types
+
+
         _bpy_types._register_immediate = False
 
+        def handle_error():
+            import traceback
+            traceback.print_exc()
+            _bpy_types._register_immediate = True
+
+
+        # reload if the mtime changes
+        mod = sys.modules.get(module_name)
+        if mod:
+            mtime_orig = getattr(mod, "__time__", 0)
+            mtime_new = os.path.getmtime(mod.__file__)
+            if mtime_orig != mtime_new:
+                print("module changed on disk:", mod.__file__, "reloading...")
+
+                try:
+                    reload(mod)
+                except:
+                    handle_error()
+                    del sys.modules[module_name]
+                    return {'CANCELLED'}
+
+        # Split registering up into 3 steps so we can undo if it fails par way through
+        # 1) try import
         try:
             mod = __import__(module_name)
+            mod.__time__ = os.path.getmtime(mod.__file__)
+        except:
+            handle_error()
+            return {'CANCELLED'}
+
+        # 2) try register collected modules
+        try:
             _bpy_types._register_module(module_name)
+        except:
+            handle_error()
+            del sys.modules[module_name]
+            return {'CANCELLED'}
+
+        # 3) try run the modules register function
+        try:
             mod.register()
         except:
-            import traceback
-            traceback.print_exc()
+            handle_error()
+            _bpy_types._unregister_module(module_name)
+            del sys.modules[module_name]
             return {'CANCELLED'}
 
-        ext = context.user_preferences.addons.new()
-        ext.module = module_name
+        # * OK loaded successfully! *
+        # just incase its enabled alredy
+        ext = context.user_preferences.addons.get(module_name)
+        if not ext:
+            ext = context.user_preferences.addons.new()
+            ext.module = module_name
 
         # check if add-on is written for current blender version, or raise a warning
         info = addon_info_get(mod)
@@ -1097,16 +1143,14 @@
             import traceback
             traceback.print_exc()
 
+        # could be in more then once, unlikely but better do this just incase.
         addons = context.user_preferences.addons
-        ok = True
-        while ok:  # incase its in more then once.
-            ok = False
-            for ext in addons:
-                if ext.module == module_name:
-                    addons.remove(ext)
-                    ok = True
-                    break
 
+        while module_name in addons:
+            addon = addons.get(module_name)
+            if addon:
+                addons.remove(addon)
+
         return {'FINISHED'}
 
 





More information about the Bf-blender-cvs mailing list