py/rna update, reload works again.
- 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.
This commit is contained in:
@@ -29,8 +29,6 @@ import sys as _sys
|
|||||||
|
|
||||||
from _bpy import blend_paths
|
from _bpy import blend_paths
|
||||||
from _bpy import script_paths as _bpy_script_paths
|
from _bpy import script_paths as _bpy_script_paths
|
||||||
from _bpy import _load_module, _unload_module
|
|
||||||
|
|
||||||
|
|
||||||
def _test_import(module_name, loaded_modules):
|
def _test_import(module_name, loaded_modules):
|
||||||
import traceback
|
import traceback
|
||||||
@@ -86,8 +84,8 @@ def modules_from_path(path, loaded_modules):
|
|||||||
|
|
||||||
return modules
|
return modules
|
||||||
|
|
||||||
_loaded = [] # store loaded modules for reloading.
|
_global_loaded_modules = [] # store loaded module names for reloading.
|
||||||
_bpy_types = __import__("bpy_types") # keep for comparisons, never ever reload this.
|
import bpy_types as _bpy_types # keep for comparisons, never ever reload this.
|
||||||
|
|
||||||
|
|
||||||
def load_scripts(reload_scripts=False, refresh_scripts=False):
|
def load_scripts(reload_scripts=False, refresh_scripts=False):
|
||||||
@@ -112,8 +110,23 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
|
|||||||
if refresh_scripts:
|
if refresh_scripts:
|
||||||
original_modules = _sys.modules.values()
|
original_modules = _sys.modules.values()
|
||||||
|
|
||||||
def unload_module(mod):
|
if reload_scripts:
|
||||||
_unload_module(mod.__name__)
|
_bpy_types.TypeMap.clear()
|
||||||
|
_bpy_types.PropertiesMap.clear()
|
||||||
|
|
||||||
|
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)
|
unregister = getattr(mod, "unregister", None)
|
||||||
if unregister:
|
if unregister:
|
||||||
try:
|
try:
|
||||||
@@ -147,44 +160,23 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
|
|||||||
mod = test_reload(mod)
|
mod = test_reload(mod)
|
||||||
|
|
||||||
if mod:
|
if mod:
|
||||||
_load_module(mod.__name__, reload_scripts)
|
register_module_call(mod)
|
||||||
register = getattr(mod, "register", None)
|
_global_loaded_modules.append(mod.__name__)
|
||||||
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)
|
|
||||||
|
|
||||||
if reload_scripts:
|
if reload_scripts:
|
||||||
|
|
||||||
# TODO, this is broken but should work, needs looking into
|
# module names -> modules
|
||||||
'''
|
_global_loaded_modules[:] = [_sys.modules[mod_name] for mod_name in _global_loaded_modules]
|
||||||
# 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])
|
|
||||||
'''
|
|
||||||
|
|
||||||
# loop over and unload all scripts
|
# loop over and unload all scripts
|
||||||
_loaded.reverse()
|
_global_loaded_modules.reverse()
|
||||||
for mod in _loaded:
|
for mod in _global_loaded_modules:
|
||||||
unload_module(mod)
|
unregister_module_call(mod)
|
||||||
|
|
||||||
for mod in _loaded:
|
for mod in _global_loaded_modules:
|
||||||
reload(mod)
|
test_reload(mod)
|
||||||
|
|
||||||
_loaded[:] = []
|
_global_loaded_modules[:] = []
|
||||||
|
|
||||||
user_path = user_script_path()
|
user_path = user_script_path()
|
||||||
|
|
||||||
@@ -206,7 +198,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
|
|||||||
|
|
||||||
# load addons
|
# load addons
|
||||||
used_ext = {ext.module for ext in _bpy.context.user_preferences.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:
|
for path in paths:
|
||||||
sys_path_ensure(path)
|
sys_path_ensure(path)
|
||||||
|
|
||||||
|
|||||||
@@ -551,13 +551,13 @@ PropertiesMap = {}
|
|||||||
# registers moduals instantly.
|
# registers moduals instantly.
|
||||||
_register_immediate = True
|
_register_immediate = True
|
||||||
|
|
||||||
def _unload_module(module, free=True):
|
def _unregister_module(module, free=True):
|
||||||
for t in TypeMap.get(module, ()):
|
for t in TypeMap.get(module, ()):
|
||||||
try:
|
try:
|
||||||
bpy_types.unregister(t)
|
bpy_types.unregister(t)
|
||||||
except:
|
except:
|
||||||
import traceback
|
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()
|
traceback.print_exc()
|
||||||
|
|
||||||
if free == True and module in TypeMap:
|
if free == True and module in TypeMap:
|
||||||
@@ -575,17 +575,16 @@ def _unload_module(module, free=True):
|
|||||||
if free == True and module in PropertiesMap:
|
if free == True and module in PropertiesMap:
|
||||||
del PropertiesMap[module]
|
del PropertiesMap[module]
|
||||||
|
|
||||||
def _load_module(module, force=False):
|
|
||||||
|
def _register_module(module):
|
||||||
for t in TypeMap.get(module, ()):
|
for t in TypeMap.get(module, ()):
|
||||||
try:
|
try:
|
||||||
bpy_types.register(t)
|
bpy_types.register(t)
|
||||||
except:
|
except:
|
||||||
import traceback
|
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()
|
traceback.print_exc()
|
||||||
|
|
||||||
_bpy._load_module = _load_module
|
|
||||||
_bpy._unload_module = _unload_module
|
|
||||||
|
|
||||||
class RNAMeta(type):
|
class RNAMeta(type):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -44,17 +44,17 @@ def get_console(console_id):
|
|||||||
from code import InteractiveConsole
|
from code import InteractiveConsole
|
||||||
|
|
||||||
consoles = getattr(get_console, "consoles", None)
|
consoles = getattr(get_console, "consoles", None)
|
||||||
|
hash_next = hash(bpy.context.manager)
|
||||||
|
|
||||||
if consoles is None:
|
if consoles is None:
|
||||||
consoles = get_console.consoles = {}
|
consoles = get_console.consoles = {}
|
||||||
get_console.consoles_namespace_hash = hash(bpy.context.manager)
|
get_console.consoles_namespace_hash = hash_next
|
||||||
else:
|
else:
|
||||||
# check if clearning the namespace is needed to avoid a memory leak.
|
# check if clearning the namespace is needed to avoid a memory leak.
|
||||||
# the window manager is normally loaded with new blend files
|
# the window manager is normally loaded with new blend files
|
||||||
# so this is a reasonable way to deal with namespace clearing.
|
# so this is a reasonable way to deal with namespace clearing.
|
||||||
# bpy.data hashing is reset by undo so cant be used.
|
# bpy.data hashing is reset by undo so cant be used.
|
||||||
hash_prev = getattr(get_console, "consoles_namespace_hash", 0)
|
hash_prev = getattr(get_console, "consoles_namespace_hash", 0)
|
||||||
hash_next = hash(bpy.context.manager)
|
|
||||||
|
|
||||||
if hash_prev != hash_next:
|
if hash_prev != hash_next:
|
||||||
get_console.consoles_namespace_hash = hash_next
|
get_console.consoles_namespace_hash = hash_next
|
||||||
|
|||||||
@@ -160,11 +160,10 @@ static PyObject *CreateGlobalDictionary(bContext *C, const char *filename)
|
|||||||
PyObject *mod_main= PyModule_New("__main__");
|
PyObject *mod_main= PyModule_New("__main__");
|
||||||
PyDict_SetItemString(interp->modules, "__main__", mod_main);
|
PyDict_SetItemString(interp->modules, "__main__", mod_main);
|
||||||
Py_DECREF(mod_main); /* sys.modules owns now */
|
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, "__name__", "__main__");
|
||||||
PyModule_AddStringConstant(mod_main, "__file__", filename); /* __file__ only for nice UI'ness */
|
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);
|
return PyModule_GetDict(mod_main);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user