py/rna update, reload works again.
authorCampbell Barton <ideasman42@gmail.com>
Tue, 3 Aug 2010 03:53:36 +0000 (03:53 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 3 Aug 2010 03:53:36 +0000 (03:53 +0000)
- fix for reload (f8) crashing, missing incref when creating the script namespace.
- store the module names rather then the modules for reloading incase the modules get out of date.

release/scripts/modules/bpy/utils.py
release/scripts/modules/bpy_types.py
release/scripts/op/console_python.py
source/blender/python/intern/bpy_interface.c

index c138d5752344b1da944926f83a360919b85c5869..3f3eab2ac2a8cfcaf61b283a650f7220012c6290 100644 (file)
@@ -29,8 +29,6 @@ import sys as _sys
 
 from _bpy import blend_paths
 from _bpy import script_paths as _bpy_script_paths
-from _bpy import _load_module, _unload_module
-
 
 def _test_import(module_name, loaded_modules):
     import traceback
@@ -86,8 +84,8 @@ def modules_from_path(path, loaded_modules):
 
     return modules
             
-_loaded = [] # store loaded modules for reloading.
-_bpy_types = __import__("bpy_types") # keep for comparisons, never ever reload this.
+_global_loaded_modules = [] # store loaded module names for reloading.
+import bpy_types as _bpy_types # keep for comparisons, never ever reload this.
 
 
 def load_scripts(reload_scripts=False, refresh_scripts=False):
@@ -111,16 +109,31 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
 
     if refresh_scripts:
         original_modules = _sys.modules.values()
+    
+    if reload_scripts:
+        _bpy_types.TypeMap.clear()
+        _bpy_types.PropertiesMap.clear()
 
-    def unload_module(mod):
-        _unload_module(mod.__name__)
+    def register_module_call(mod):
+        _bpy_types._register_module(mod.__name__)
+        register = getattr(mod, "register", None)
+        if register:
+            try:
+                register()
+            except:
+                traceback.print_exc()
+        else:
+            print("\nWarning! '%s' has no register function, this is now a requirement for registerable scripts." % mod.__file__)
+
+    def unregister_module_call(mod):
+        _bpy_types._unregister_module(mod.__name__)
         unregister = getattr(mod, "unregister", None)
         if unregister:
             try:
                 unregister()
             except:
                 traceback.print_exc()
-                
+
     def sys_path_ensure(path):
         if path not in _sys.path: # reloading would add twice
             _sys.path.insert(0, path)
@@ -147,44 +160,23 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
             mod = test_reload(mod)
 
         if mod:
-            _load_module(mod.__name__, reload_scripts)
-            register = getattr(mod, "register", None)
-            if register:
-                try:
-                    register()
-                except:
-                    traceback.print_exc()
-            else:
-                print("\nWarning! '%s' has no register function, this is now a requirement for registerable scripts." % mod.__file__)
-            _loaded.append(mod)
+            register_module_call(mod)
+            _global_loaded_modules.append(mod.__name__)
 
     if reload_scripts:
 
-        # TODO, this is broken but should work, needs looking into
-        '''
-        # reload modules that may not be directly included
-        for type_class_name in dir(_bpy.types):
-            type_class = getattr(_bpy.types, type_class_name)
-            module_name = getattr(type_class, "__module__", "")
-
-            if module_name and module_name != "bpy.types": # hard coded for C types
-                loaded_modules.add(module_name)
-
-        # sorting isnt needed but rather it be pradictable
-        for module_name in sorted(loaded_modules):
-            print("Reloading:", module_name)
-            test_reload(_sys.modules[module_name])
-        '''
+        # module names -> modules
+        _global_loaded_modules[:] = [_sys.modules[mod_name] for mod_name in _global_loaded_modules]
 
         # loop over and unload all scripts
-        _loaded.reverse()
-        for mod in _loaded:
-            unload_module(mod)
+        _global_loaded_modules.reverse()
+        for mod in _global_loaded_modules:
+            unregister_module_call(mod)
 
-        for mod in _loaded:
-            reload(mod)
+        for mod in _global_loaded_modules:
+            test_reload(mod)
 
-        _loaded[:] = []
+        _global_loaded_modules[:] = []
 
     user_path = user_script_path()
 
@@ -206,7 +198,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
 
     # load addons
     used_ext = {ext.module for ext in _bpy.context.user_preferences.addons}
-    paths = script_paths("addons")
+    paths = script_paths("addons") + script_paths("addons_contrib")
     for path in paths:
         sys_path_ensure(path)
 
index db89983744e1ead984d47f46ba9b7bb14c7466b8..c5f7ee150c937aea10d646e11fb6dc7d7cc1d404 100644 (file)
@@ -551,13 +551,13 @@ PropertiesMap = {}
 # registers moduals instantly.
 _register_immediate = True
 
-def _unload_module(module, free=True):
+def _unregister_module(module, free=True):
     for t in TypeMap.get(module, ()):
         try:
             bpy_types.unregister(t)
         except:
             import traceback
-            print("bpy.utils._unload_module(): Module '%s' failed to unregister class '%s.%s'" % (module, t.__module__, t.__name__))
+            print("bpy.utils._unregister_module(): Module '%s' failed to unregister class '%s.%s'" % (module, t.__module__, t.__name__))
             traceback.print_exc()
 
     if free == True and module in TypeMap:
@@ -575,17 +575,16 @@ def _unload_module(module, free=True):
     if free == True and module in PropertiesMap:
         del PropertiesMap[module]
 
-def _load_module(module, force=False):
+
+def _register_module(module):
     for t in TypeMap.get(module, ()):
         try:
             bpy_types.register(t)
         except:
             import traceback
-            print("bpy.utils._load_module(): Module '%s' failed to register class '%s.%s'" % (module, t.__module__, t.__name__))
+            print("bpy.utils._register_module(): Module '%s' failed to register class '%s.%s'" % (module, t.__module__, t.__name__))
             traceback.print_exc()
 
-_bpy._load_module = _load_module
-_bpy._unload_module = _unload_module
 
 class RNAMeta(type):
     @classmethod
index 8c7f543db36e19fd65a860ea19d722731c969655..cc0f3673e5c6fa14546d93493bf893c7db2ed560 100644 (file)
@@ -44,17 +44,17 @@ def get_console(console_id):
     from code import InteractiveConsole
 
     consoles = getattr(get_console, "consoles", None)
+    hash_next = hash(bpy.context.manager)
 
     if consoles is None:
         consoles = get_console.consoles = {}
-        get_console.consoles_namespace_hash = hash(bpy.context.manager)
+        get_console.consoles_namespace_hash = hash_next
     else:
         # check if clearning the namespace is needed to avoid a memory leak.
         # the window manager is normally loaded with new blend files
         # so this is a reasonable way to deal with namespace clearing.
         # bpy.data hashing is reset by undo so cant be used.
         hash_prev = getattr(get_console, "consoles_namespace_hash", 0)
-        hash_next = hash(bpy.context.manager)
 
         if hash_prev != hash_next:
             get_console.consoles_namespace_hash = hash_next
index 375bf20797bde4898a07f7a6a2e3b1c528f49bd1..5fe755747d33fa775c2167a20193418a1685f6dd 100644 (file)
@@ -160,11 +160,10 @@ static PyObject *CreateGlobalDictionary(bContext *C, const char *filename)
        PyObject *mod_main= PyModule_New("__main__");   
        PyDict_SetItemString(interp->modules, "__main__", mod_main);
        Py_DECREF(mod_main); /* sys.modules owns now */
-
-       PyModule_AddObject(mod_main, "__builtins__", interp->builtins);
        PyModule_AddStringConstant(mod_main, "__name__", "__main__");
        PyModule_AddStringConstant(mod_main, "__file__", filename); /* __file__ only for nice UI'ness */
-
+       PyModule_AddObject(mod_main, "__builtins__", interp->builtins);
+       Py_INCREF(interp->builtins); /* AddObject steals a reference */
        return PyModule_GetDict(mod_main);
 }