Page MenuHome
Paste P455

Patch to help remove register_module use in 2.8
ActivePublic

Authored by Campbell Barton (campbellbarton) on Mar 18 2017, 9:59 AM.
diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py
index 04aaa7bd69d..547a2992838 100644
--- a/release/scripts/modules/bpy/utils/__init__.py
+++ b/release/scripts/modules/bpy/utils/__init__.py
@@ -51,6 +51,7 @@ __all__ = (
"smpte_from_seconds",
"units",
"unregister_class",
+ "unregister_module",
"unregister_tool",
"user_resource",
"execfile",
@@ -187,6 +188,10 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
for module_name in [ext.module for ext in _preferences.addons]:
_addon_utils.disable(module_name)
+ # *AFTER* unregistering all add-ons, otherwise all calls to
+ # unregister_module() will silently fail (do nothing).
+ _bpy_types.TypeMap.clear()
+
def register_module_call(mod):
register = getattr(mod, "register", None)
if register:
@@ -672,6 +677,105 @@ def user_resource(resource_type, path="", create=False):
return target_path
+def _bpy_module_classes(module, is_registered=False):
+ typemap_list = _bpy_types.TypeMap.get(module, ())
+ i = 0
+ while i < len(typemap_list):
+ cls_weakref = typemap_list[i]
+ cls = cls_weakref()
+
+ if cls is None:
+ del typemap_list[i]
+ else:
+ if is_registered == cls.is_registered:
+ yield cls
+ i += 1
+
+
+def register_module(module, verbose=False):
+ if verbose:
+ print("bpy.utils.register_module(%r): ..." % module)
+
+ # Always print this text
+ if True:
+ print("# bpy.utils.register_module is deprecated! replace code with this:")
+ ls = list(_bpy_module_classes(module, is_registered=False))
+ ls.sort(key=lambda cls: cls.__module__)
+ mod_prev = None
+ for cls in ls:
+ if mod_prev != cls.__module__:
+ if mod_prev is not None:
+ print(")\n")
+ print("#", cls.__module__.replace(".", "/") + ".py")
+ print("classes = (")
+ mod_prev = cls.__module__
+ print(" %s," % cls.__name__)
+ print(")\n")
+ print("\n")
+ print("# add these 2 functions to all .py files listed in code above:\n")
+ print("def register():")
+ print(" from bpy.utils import register_class")
+ print(" for cls in classes:")
+ print(" register_class(cls)")
+ print("\n")
+ print("def unregister():")
+ print(" from bpy.utils import unregister_class")
+ print(" for cls in reversed(classes):")
+ print(" unregister_class(cls)")
+ print("\n")
+
+ mod_len = len(module) + 1
+ new_mod_ls = []
+ mod_prev = None
+ for cls in ls:
+ if mod_prev != cls.__module__:
+ mod_name = cls.__module__[mod_len:].replace(".", "/")
+ if mod_name != "":
+ new_mod_ls.append(mod_name)
+ mod_prev = cls.__module__
+ print("# add to __init__.py file 'register' function:\n")
+ for mod in new_mod_ls:
+ print(" ", mod + ".register()")
+ print("\n")
+ print("# add to __init__.py file 'unregister' function:\n")
+ for mod in reversed(new_mod_ls):
+ print(" ", mod + ".unregister()")
+ print("\n")
+
+ cls = None
+ for cls in _bpy_module_classes(module, is_registered=False):
+ if verbose:
+ print(" %r" % cls)
+ try:
+ register_class(cls)
+ except:
+ print("bpy.utils.register_module(): "
+ "failed to registering class %r" % cls)
+ import traceback
+ traceback.print_exc()
+ if verbose:
+ print("done.\n")
+ if cls is None:
+ raise Exception("register_module(%r): defines no classes" % module)
+
+
+def unregister_module(module, verbose=False):
+ if verbose:
+ print("bpy.utils.unregister_module(%r): ..." % module)
+ for cls in _bpy_module_classes(module, is_registered=True):
+ if verbose:
+ print(" %r" % cls)
+ try:
+ unregister_class(cls)
+ except:
+ print("bpy.utils.unregister_module(): "
+ "failed to unregistering class %r" % cls)
+ import traceback
+ traceback.print_exc()
+ if verbose:
+ print("done.\n")
+
+
def register_classes_factory(classes):
"""
Utility function to create register and unregister functions
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index a3787506da4..b838559283a 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -523,6 +523,10 @@ class Text(bpy_types.ID):
return mod
+# values are module: [(cls, path, line), ...]
+TypeMap = {}
+
+
class Sound(bpy_types.ID):
__slots__ = ()
@@ -534,7 +538,21 @@ class Sound(bpy_types.ID):
class RNAMeta(type):
- # TODO(campbell): move to C-API
+
+ def __new__(cls, name, bases, classdict, **args):
+ result = type.__new__(cls, name, bases, classdict)
+ if bases and bases[0] is not StructRNA:
+ from _weakref import ref as ref
+ module = result.__module__
+
+ # first part of packages only
+ if "." in module:
+ module = module[:module.index(".")]
+
+ TypeMap.setdefault(module, []).append(ref(result))
+
+ return result
+
@property
def is_registered(cls):
return "bl_rna" in cls.__dict__

Event Timeline

Campbell Barton (campbellbarton) changed the title of this paste from Patch to help remove register_module use to Patch to help remove register_module use in 2.8.Aug 13 2018, 4:57 AM
Campbell Barton (campbellbarton) edited the content of this paste. (Show Details)