Browse Source

direct: Clean up broken usage of "types" module with Python 3

Daniel 3 years ago
parent
commit
24c14296c0

+ 26 - 6
direct/src/showbase/ContainerLeakDetector.py

@@ -11,12 +11,15 @@ import weakref
 import random
 import random
 import builtins
 import builtins
 
 
-deadEndTypes = (bool, types.BuiltinFunctionType,
-                types.BuiltinMethodType, complex,
-                float, int,
-                type(None), type(NotImplemented),
-                type, types.CodeType, types.FunctionType,
-                bytes, str, tuple)
+deadEndTypes = frozenset((
+    types.BuiltinFunctionType, types.BuiltinMethodType,
+    types.CodeType, types.FunctionType,
+    types.GeneratorType, types.CoroutineType,
+    types.AsyncGeneratorType,
+    bool, complex, float, int, type,
+    bytes, str, list, tuple,
+    type(None), type(NotImplemented)
+))
 
 
 
 
 def _createContainerLeak():
 def _createContainerLeak():
@@ -547,6 +550,23 @@ class FindContainers(Job):
                 # if we hit a dead end, start over from another container
                 # if we hit a dead end, start over from another container
                 curObjRef = None
                 curObjRef = None
 
 
+                # types.CellType was added in Python 3.8
+                if sys.version_info >= (3, 8) and type(curObj) is types.CellType:
+                    child = curObj.cell_contents
+                    hasLength = self._hasLength(child)
+                    notDeadEnd = not self._isDeadEnd(child)
+                    if hasLength or notDeadEnd:
+                        objRef = ObjectRef(Indirection(evalStr='.cell_contents'),
+                                           id(child), parentObjRef)
+                        yield None
+                        if hasLength:
+                            for i in self._addContainerGen(child, objRef):
+                                yield None
+                        if notDeadEnd:
+                            self._addDiscoveredStartRef(child, objRef)
+                            curObjRef = objRef
+                    continue
+
                 if hasattr(curObj, '__dict__'):
                 if hasattr(curObj, '__dict__'):
                     child = curObj.__dict__
                     child = curObj.__dict__
                     hasLength = self._hasLength(child)
                     hasLength = self._hasLength(child)

+ 28 - 14
direct/src/showbase/ContainerReport.py

@@ -3,7 +3,10 @@ from direct.showbase.PythonUtil import Queue, invertDictLossless
 from direct.showbase.PythonUtil import safeRepr
 from direct.showbase.PythonUtil import safeRepr
 from direct.showbase.Job import Job
 from direct.showbase.Job import Job
 from direct.showbase.JobManagerGlobal import jobMgr
 from direct.showbase.JobManagerGlobal import jobMgr
+from direct.showbase.ContainerLeakDetector import deadEndTypes
 import types
 import types
+import sys
+import io
 
 
 
 
 class ContainerReport(Job):
 class ContainerReport(Job):
@@ -89,14 +92,6 @@ class ContainerReport(Job):
             if isinstance(parentObj, (str, bytes)):
             if isinstance(parentObj, (str, bytes)):
                 continue
                 continue
 
 
-            if type(parentObj) in (types.ModuleType, types.InstanceType):
-                child = parentObj.__dict__
-                if self._examine(child):
-                    assert self._queue.back() is child
-                    self._instanceDictIds.add(id(child))
-                    self._id2pathStr[id(child)] = str(self._id2pathStr[id(parentObj)])
-                continue
-
             if isinstance(parentObj, dict):
             if isinstance(parentObj, dict):
                 key = None
                 key = None
                 attr = None
                 attr = None
@@ -126,7 +121,25 @@ class ContainerReport(Job):
                 del attr
                 del attr
                 continue
                 continue
 
 
-            if type(parentObj) is not types.FileType:
+            # types.CellType was added in Python 3.8
+            if sys.version_info >= (3, 8) and type(parentObj) is types.CellType:
+                child = parentObj.cell_contents
+                if self._examine(child):
+                    assert (self._queue.back() is child)
+                    self._instanceDictIds.add(id(child))
+                    self._id2pathStr[id(child)] = str(self._id2pathStr[id(parentObj)]) + '.cell_contents'
+                continue
+
+            if hasattr(parentObj, '__dict__'):
+                # Instance of a class
+                child = parentObj.__dict__
+                if self._examine(child):
+                    assert (self._queue.back() is child)
+                    self._instanceDictIds.add(id(child))
+                    self._id2pathStr[id(child)] = str(self._id2pathStr[id(parentObj)])
+                continue
+
+            if not isinstance(parentObj, io.TextIOWrapper):
                 try:
                 try:
                     itr = iter(parentObj)
                     itr = iter(parentObj)
                 except:
                 except:
@@ -161,7 +174,10 @@ class ContainerReport(Job):
                 childName = None
                 childName = None
                 child = None
                 child = None
                 for childName in childNames:
                 for childName in childNames:
-                    child = getattr(parentObj, childName)
+                    try:
+                        child = getattr(parentObj, childName)
+                    except:
+                        continue
                     if id(child) not in self._visitedIds:
                     if id(child) not in self._visitedIds:
                         self._visitedIds.add(id(child))
                         self._visitedIds.add(id(child))
                         if self._examine(child):
                         if self._examine(child):
@@ -198,9 +214,7 @@ class ContainerReport(Job):
             self._type2id2len[type(obj)][objId] = length
             self._type2id2len[type(obj)][objId] = length
     def _examine(self, obj):
     def _examine(self, obj):
         # return False if it's an object that can't contain or lead to other objects
         # return False if it's an object that can't contain or lead to other objects
-        if type(obj) in (bool, types.BuiltinFunctionType, types.BuiltinMethodType,
-                         complex, float, int, type(None), type(NotImplemented),
-                         type, types.CodeType, types.FunctionType):
+        if type(obj) in deadEndTypes:
             return False
             return False
         # if it's an internal object, ignore it
         # if it's an internal object, ignore it
         if id(obj) in ContainerReport.PrivateIds:
         if id(obj) in ContainerReport.PrivateIds:
@@ -243,7 +257,7 @@ class ContainerReport(Job):
             for i in self._outputType(type, **kArgs):
             for i in self._outputType(type, **kArgs):
                 yield None
                 yield None
         otherTypes = list(set(self._type2id2len.keys()).difference(set(initialTypes)))
         otherTypes = list(set(self._type2id2len.keys()).difference(set(initialTypes)))
-        otherTypes.sort()
+        otherTypes.sort(key=lambda obj: obj.__name__)
         for type in otherTypes:
         for type in otherTypes:
             for i in self._outputType(type, **kArgs):
             for i in self._outputType(type, **kArgs):
                 yield None
                 yield None

+ 0 - 0
direct/src/showbase/GarbageReport.py