use weak references for the internal metaclass typemap,
authorCampbell Barton <ideasman42@gmail.com>
Fri, 11 Feb 2011 00:39:07 +0000 (00:39 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 11 Feb 2011 00:39:07 +0000 (00:39 +0000)
this should help with blender leaking memory with python classes though the bug is still not fixed.

release/scripts/modules/bpy/utils.py
release/scripts/modules/bpy_types.py

index c806aa1e0e664b379a30c9df9411156c9673614b..a86cfacb56bdf72212e013aca5b82cd20570765a 100644 (file)
@@ -579,35 +579,40 @@ def user_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, path, line = typemap_list[i]
+        cls = cls_weakref()
+
+        if cls is None:
+            del typemap_list[i]
+        elif is_registered == ("bl_rna" in cls.__dict__):
+            yield (cls, path, line)
+            i += 1
+
+
 def register_module(module):
     import traceback
-    total = 0
-    for cls, path, line in _bpy_types.TypeMap.get(module, ()):
-        if not "bl_rna" in cls.__dict__:
-            total += 1
-            try:
-                register_class(cls)
-            except:
-                print("bpy.utils.register_module(): failed to registering class '%s.%s'" % (cls.__module__, cls.__name__))
-                print("\t", path, "line", line)
-                traceback.print_exc()
+    for cls, path, line in _bpy_module_classes(module, is_registered=False):
+        try:
+            register_class(cls)
+        except:
+            print("bpy.utils.register_module(): failed to registering class '%s.%s'" % (cls.__module__, cls.__name__))
+            print("\t", path, "line", line)
+            traceback.print_exc()
 
-    if total == 0:
+    if "cls" not in locals():
         raise Exception("register_module(%r): defines no classes" % module)
 
 
 def unregister_module(module):
     import traceback
-    total = 0
-    for cls, path, line in _bpy_types.TypeMap.get(module, ()):
-        if "bl_rna" in cls.__dict__:
-            total += 1
-            try:
-                unregister_class(cls)
-            except:
-                print("bpy.utils.unregister_module(): failed to unregistering class '%s.%s'" % (cls.__module__, cls.__name__))
-                print("\t", path, "line", line)
-                traceback.print_exc()
-
-    if total == 0:
-        raise Exception("unregister_module(%r): defines no classes" % module)
+    for cls, path, line in _bpy_module_classes(module, is_registered=True):
+        try:
+            unregister_class(cls)
+        except:
+            print("bpy.utils.unregister_module(): failed to unregistering class '%s.%s'" % (cls.__module__, cls.__name__))
+            print("\t", path, "line", line)
+            traceback.print_exc()
index b11ef203df5ce106733fb75f92f1ae0d907bb793..fcc3166b066645888e4301c89f8e899d5799d10b 100644 (file)
@@ -556,9 +556,10 @@ TypeMap = {}
 
 class RNAMeta(type):
     def __new__(cls, name, bases, classdict, **args):
-        import traceback
         result = type.__new__(cls, name, bases, classdict)
         if bases and bases[0] != StructRNA:
+            import traceback
+            import weakref
             module = result.__module__
 
             # first part of packages only
@@ -567,7 +568,7 @@ class RNAMeta(type):
 
             sf = traceback.extract_stack(limit=2)[0]
 
-            TypeMap.setdefault(module, []).append((result, sf[0], sf[1]))
+            TypeMap.setdefault(module, []).append((weakref.ref(result), sf[0], sf[1]))
 
         return result